[rhq] Changes to 'bug/822247'
by Thomas Segismont
New branch 'bug/822247' available with the following commits:
commit f77b28d6690abf904706489fbed1f3cb77be6841
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Thu Jun 20 10:51:52 2013 +0200
Bug 822247 - Web Application Response Time Log File not being imported
10 years, 11 months
[rhq] modules/enterprise
by mike thompson
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
New commits:
commit df51a764568a973f1bc48e1efda533d23c6f9590
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 19:48:33 2013 -0700
On Graphs fix OOB metric lines to account for metrics of type units == 'percentage'
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 33d0303..3922d44 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -495,14 +495,14 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
}
function createOOBLines() {
-
- var minBaselineLine = $wnd.d3.svg.line()
+ var unitsPercentMultiplier = chartContext.yAxisUnits === '%' ? 100 : 1,
+ minBaselineLine = $wnd.d3.svg.line()
.interpolate(interpolation)
.x(function (d) {
return timeScale(d.x);
})
.y(function (d) {
- return yScale(d.baselineMin);
+ return yScale(d.baselineMin * unitsPercentMultiplier);
}),
maxBaselineLine = $wnd.d3.svg.line()
.interpolate(interpolation)
@@ -510,7 +510,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
return timeScale(d.x);
})
.y(function (d) {
- return yScale(d.baselineMax);
+ return yScale(d.baselineMax * unitsPercentMultiplier);
});
// min baseline Line
10 years, 11 months
[rhq] 2 commits - modules/common modules/plugins
by John Sanda
modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java | 2 -
modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeDiscoveryComponent.java | 12 ++++++++--
modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeDiscoveryComponent.java | 9 +++++++
modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml | 4 +--
4 files changed, 22 insertions(+), 5 deletions(-)
New commits:
commit f4ba531a77747a45b7c65b81aeb742bd83d1dfcd
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 19 22:56:50 2013 -0400
use rhqadmin/rhqadmin as default username/password for storage node plugin
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeDiscoveryComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeDiscoveryComponent.java
index ffc4c2c..e7686b0 100644
--- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeDiscoveryComponent.java
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeDiscoveryComponent.java
@@ -210,8 +210,8 @@ public class CassandraNodeDiscoveryComponent extends JMXDiscoveryComponent {
String path = processInfo.getExecutable().getCwd();
pluginConfig.put(new PropertySimple(BASEDIR_PROPERTY, new File(path).getParentFile().getAbsolutePath()));
- pluginConfig.put(new PropertySimple(USERNAME_PROPERTY, "cassandra"));
- pluginConfig.put(new PropertySimple(PASSWORD_PROPERTY, "cassandra"));
+ pluginConfig.put(new PropertySimple(USERNAME_PROPERTY, getDefaultUserName()));
+ pluginConfig.put(new PropertySimple(PASSWORD_PROPERTY, getDefaultPassword()));
return new DiscoveredResourceDetails(context.getResourceType(), resourceKey, resourceName, null, null,
pluginConfig, processInfo);
@@ -224,4 +224,12 @@ public class CassandraNodeDiscoveryComponent extends JMXDiscoveryComponent {
return null;
}
+ protected String getDefaultUserName() {
+ return "cassandra";
+ }
+
+ protected String getDefaultPassword() {
+ return "cassandra";
+ }
+
}
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeDiscoveryComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeDiscoveryComponent.java
index 2715b2e..5d1888d 100644
--- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeDiscoveryComponent.java
+++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeDiscoveryComponent.java
@@ -119,4 +119,13 @@ public class StorageNodeDiscoveryComponent extends CassandraNodeDiscoveryCompone
return result;
}
+ @Override
+ protected String getDefaultUserName() {
+ return "rhqadmin";
+ }
+
+ @Override
+ protected String getDefaultPassword() {
+ return "rhqadmin";
+ }
}
diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
index 2457b0c..66889f8 100644
--- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
@@ -27,8 +27,8 @@
description="The RMI URL with which to connect to the Cassandra node (e.g. service:jmx:rmi:///jndi/rmi://localhost:7199/jmxrmi)."/>
<c:simple-property name="type" readOnly="true" default="org.mc4j.ems.connection.support.metadata.J2SE5ConnectionTypeDescriptor"
description="The type used to establish the EMS connection to the Cassandra node."/>
- <c:simple-property name="username" default="cassandra" required="true" description="The login username"/>
- <c:simple-property name="password" default="cassandra" required="true" type="password" description="The login password"/>
+ <c:simple-property name="username" default="rhqadmin" required="true" description="The login username"/>
+ <c:simple-property name="password" default="rhqadmin" required="true" type="password" description="The login password"/>
<c:simple-property name="baseDir" displayName="Base Directory" description="The base directory from which the Cassandra Daemon was launched." required="false"/>
<c:simple-property name="yamlConfiguration" displayName="YAML Configuration File" description="YAML Configuration File"/>
<c:simple-property name="nativeTransportPort" description="The port on which Cassandra listens for CQL client connections." default="9042" type="integer"/>
commit ce9f16ca1b4a628e51bbfa1494daaf9b65f88221
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 19 22:52:13 2013 -0400
default to the IP address instead of hostname for listen_address property
Cassandra uses the IP address for gossip communication, and during various
maintenance tasks we need to compare addresses with the addresses we have in
StorageNode entities. By defaulting to the hostname as previously did, we have
a mapping layer we have to go through. Using the IP address allows us to avoid
that extra work.
diff --git a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
index 5c99b89..c1995b6 100644
--- a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
+++ b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
@@ -277,7 +277,7 @@ public class StorageInstaller {
if (cmdLine.hasOption("n")) {
hostname = cmdLine.getOptionValue("n");
} else {
- hostname = InetAddress.getLocalHost().getHostName();
+ hostname = InetAddress.getLocalHost().getHostAddress();
}
deploymentOptions.setListenAddress(hostname);
deploymentOptions.setRpcAddress(hostname);
10 years, 11 months
[rhq] 2 commits - modules/common modules/enterprise modules/helpers
by John Sanda
modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java | 17 +-
modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java | 78 ++++------
modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java | 10 -
modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java | 8 -
modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java | 24 +++
modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java | 47 +++++-
modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml | 10 +
modules/common/cassandra-schema/src/main/resources/topology/0001.xml | 4
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java | 11 -
modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/CassandraIntegrationTest.java | 6
modules/enterprise/server/server-metrics/src/test/resources/log4j.properties | 2
modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java | 2
12 files changed, 134 insertions(+), 85 deletions(-)
New commits:
commit 26e9cc7c6ae7c0b0fa4748b5c217fc2c637bd110
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 19 21:21:28 2013 -0400
drop default cassandra user and perform schema changes with rhqadmin user
Previously we were applying RF (replication_factor) changes after creating the
rhqadmin user. This would result in inconsistent reads when there are multiple
nodes and we wind up increasing the RF. The inconsistent reads means that we
would wind up with failed authentication some times. The easiest fix is to
increase the RF before we create the rhqadmin user.
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java b/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java
index 6a19d30..d307f0b 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java
+++ b/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java
@@ -26,6 +26,7 @@
package org.rhq.cassandra.ccm.arquillian;
import java.io.File;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
@@ -113,6 +114,8 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
public Void call() throws Exception {
SchemaManager schemaManager;
+ ClusterInitService clusterInitService = new ClusterInitService();
+ List<StorageNode> nodes = Collections.emptyList();
if (!Boolean.valueOf(System.getProperty("itest.use-external-storage-node", "false"))) {
@@ -121,21 +124,21 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
File basedir = new File("target");
File clusterDir = new File(basedir, "cassandra");
- options.setUsername("cassandra");
- options.setPassword("cassandra");
+ options.setUsername("rhqadmin");
+ options.setPassword("rhqadmin");
options.setClusterDir(clusterDir.getAbsolutePath());
options.setHeapSize("256M");
options.setHeapNewSize("64M");
+ options.setStartRpc(true);
ccm = new CassandraClusterManager(options);
- List<StorageNode> nodes = ccm.createCluster();
+ nodes = ccm.createCluster();
ccm.startCluster(false);
try {
- ClusterInitService clusterInitService = new ClusterInitService();
clusterInitService.waitForClusterToStart(nodes, nodes.size(), 1500, 20, 5);
- schemaManager = new SchemaManager("cassandra", "cassandra", nodes);
+ schemaManager = new SchemaManager("rhqadmin", "rhqadmin", nodes);
} catch (Exception e) {
if (null != ccm) {
@@ -146,7 +149,7 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
} else {
try {
String seed = System.getProperty("rhq.cassandra.seeds", "127.0.0.1|7199|9042");
- schemaManager = new SchemaManager("cassandra", "cassandra", seed);
+ schemaManager = new SchemaManager("rhqadmin", "rhqadmin", seed);
} catch (Exception e) {
throw new RuntimeException("External Cassandra initialization failed", e);
@@ -155,8 +158,8 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
try {
schemaManager.install();
+ clusterInitService.waitForSchemaAgreement(nodes);
schemaManager.updateTopology();
-
} catch (Exception e) {
if (null != ccm) {
ccm.shutdownCluster();
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java b/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java
index 639f4e2..a9292f7 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java
+++ b/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java
@@ -126,18 +126,10 @@ public class CCMTestNGListener implements IInvokedMethodListener {
SchemaManager schemaManager = new SchemaManager(annotation.username(), annotation.password(), nodes);
schemaManager.install();
- schemaManager.updateTopology();
-
if (annotation.waitForSchemaAgreement()) {
- // TODO do not hard code cluster name
- // I am ok with hard coding the cluster name for now as it is only required
- // by the Hector API, and it is to be determined whether or not we will continue
- // using Hector. If we wind up directly using the underlying Thrift API, there
- // is no cluster name argument.
- //
- // jsanda
clusterInitService.waitForSchemaAgreement(nodes);
}
+ schemaManager.updateTopology();
}
private void shutdownCluster() throws Exception {
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
index 6cecbb2..bcf9831 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
@@ -85,9 +85,6 @@ public class AbstractManager {
this.username = username;
this.password = password;
this.nodes = nodes;
-
- this.initCluster();
- this.shutdown();
} catch (NoHostAvailableException e) {
throw new RuntimeException("Unable create storage node session.", e);
}
@@ -228,8 +225,11 @@ public class AbstractManager {
return files;
}
+ protected void initCluster() {
+ initCluster(username, password);
+ }
- protected void initCluster() throws NoHostAvailableException {
+ protected void initCluster(String username, String password) {
String[] hostNames = new String[nodes.size()];
for (int i = 0; i < hostNames.length; ++i) {
hostNames[i] = nodes.get(i).getAddress();
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
index fcb8d94..8f8c47e 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
@@ -45,14 +45,38 @@ public class SchemaManager {
private final Log log = LogFactory.getLog(SchemaManager.class);
+ /**
+ * The username that RHQ will use to connect to the storage cluster.
+ */
private final String username;
+
+ /**
+ * The password that RHQ will use to connect to the storage cluster.
+ */
private final String password;
+
private final List<StorageNode> nodes = new ArrayList<StorageNode>();
+ /**
+ *
+ * @param username The username RHQ will use to connect to the storage cluster.
+ * @param password The password RHQ will use to connect to the storage cluster.
+ * @param nodes A list of seeds nodes that are assumed to be already running and
+ * clustered prior to apply schema changes. The format for each node
+ * should be address|jmx_port|cql_port,address|jmx_port|cql_port.
+ * Each node consists of three fields that are pipe-delimited.
+ */
public SchemaManager(String username, String password, String... nodes) {
this(username, password, parseNodeInformation(nodes));
}
+ /**
+ *
+ * @param username The username RHQ will use to connect to the storage cluster.
+ * @param password The password RHQ will use to connect to the storage cluster.
+ * @param nodes A list of seeds nodes that are assumed to be already running and
+ * clustered prior to apply schema changes.
+ */
public SchemaManager(String username, String password, List<StorageNode> nodes) {
this.username = username;
this.password = password;
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java
index 437e097..5ad78d5 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java
@@ -30,6 +30,7 @@ import java.util.List;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.exceptions.AuthenticationException;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
import org.apache.commons.logging.Log;
@@ -71,16 +72,52 @@ public class VersionManager extends AbstractManager {
log.info("Preparing to install schema");
try {
initCluster();
+ } catch (AuthenticationException e) {
+ // If we cannot connect with the rhqadmin user, then assume it has not been
+ // created; so, we need to perform the "bootstrap" step of creating the user
+ // before we apply any schema changes. We want to create the user first so that
+ // we can go ahead and remove the default cassandra user and apply all changes
+ // using the rhqadmin user.
+ bootstrap();
+ }
+ try {
+ initCluster();
if (!schemaExists()) {
this.executeTask(Task.Create);
- } else {
+ } else {
log.info("RHQ schema already exists.");
}
-
this.executeTask(Task.Update);
- } catch (NoHostAvailableException e) {
- throw new RuntimeException(e);
+ } finally {
+ shutdown();
+ }
+ }
+
+ /**
+ * Before applying any schema, we need to create the rhqadmin user. If we have more
+ * than a single node cluster then we also need to set the RF of the system_auth
+ * keyspace BEFORE we create the rhqadmin user. If we do not do in this order we will
+ * get inconsistent reads which will can result in failed authentication.
+ */
+ public void bootstrap() {
+ try {
+ initCluster("cassandra", "cassandra");
+
+ int replicationFactor;
+ if (nodes.size() < 3) {
+ replicationFactor = nodes.size();
+ } else if (nodes.size() < 4) {
+ replicationFactor = 2;
+ } else {
+ replicationFactor = 3;
+ }
+ log.info("Updating replication_factor of system_auth keyspace to " + replicationFactor);
+ session.execute("ALTER KEYSPACE system_auth WITH replication = {'class': 'SimpleStrategy', " +
+ "'replication_factor': " + replicationFactor + "}");
+
+ log.info("Creating rhqadmin user");
+ session.execute("CREATE USER rhqadmin WITH PASSWORD 'rhqadmin' SUPERUSER");
} finally {
shutdown();
}
@@ -103,7 +140,7 @@ public class VersionManager extends AbstractManager {
}
}
- private void executeTask(Task task) throws Exception {
+ private void executeTask(Task task) {
try {
log.info("Starting to execute " + task + " task.");
diff --git a/modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml b/modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml
index 744bf60..ebd8cbf 100644
--- a/modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml
+++ b/modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml
@@ -1,6 +1,6 @@
<updatePlan>
<step>
- CREATE USER rhqadmin WITH PASSWORD 'rhqadmin' SUPERUSER;
+ DROP USER cassandra;
</step>
<step>
@@ -9,6 +9,14 @@
</step>
<step>
+ GRANT ALL PERMISSIONS ON KEYSPACE system_auth to rhqadmin;
+ </step>
+
+ <step>
+ GRANT ALL PERMISSIONS ON KEYSPACE rhq to rhqadmin;
+ </step>
+
+ <step>
CREATE TABLE rhq.schema_version (
version int,
time timestamp,
diff --git a/modules/common/cassandra-schema/src/main/resources/topology/0001.xml b/modules/common/cassandra-schema/src/main/resources/topology/0001.xml
index cbae01f..5cbd7eb 100644
--- a/modules/common/cassandra-schema/src/main/resources/topology/0001.xml
+++ b/modules/common/cassandra-schema/src/main/resources/topology/0001.xml
@@ -2,8 +2,4 @@
<step>
ALTER KEYSPACE rhq WITH replication = {'class': 'SimpleStrategy', 'replication_factor': %s};
</step>
-
- <step>
- ALTER KEYSPACE system_auth WITH replication = {'class': 'SimpleStrategy', 'replication_factor': %s};
- </step>
</updatePlan>
\ No newline at end of file
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 2e4c401..fbd869b 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -1156,16 +1156,7 @@ public class InstallerServiceImpl implements InstallerService {
String username = serverProps.get("rhq.cassandra.username");
String password = serverProps.get("rhq.cassandra.password");
- // We have to connect with the default cassandra super user here. The
- // username/password specified in rhq-server.properties is one that we create
- // during schema installation so we cannot make the initial connection with
- // that user. In fact, I am not even so sure we need to put those credentials
- // in rhq-server.properties. That user is for internal use by the server to
- // talk to storage nodes. Not sure we even want to expose it to the user, at
- // least not directly.
- //
- // jsanda
- return new SchemaManager("cassandra", "cassandra", hosts);
+ return new SchemaManager(username, password, hosts);
}
private void writeInstalledFileMarker() throws Exception {
diff --git a/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/CassandraIntegrationTest.java b/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/CassandraIntegrationTest.java
index 3e98490..c4c48c8 100644
--- a/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/CassandraIntegrationTest.java
+++ b/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/CassandraIntegrationTest.java
@@ -68,13 +68,13 @@ public class CassandraIntegrationTest {
private static DateTimeService dateTimeService;
@BeforeSuite
- @DeployCluster(numNodes = 1, username = "cassandra", password = "cassandra")
+ @DeployCluster(numNodes = 2, username = "rhqadmin", password = "rhqadmin", waitForSchemaAgreement = true)
public void deployCluster() throws Exception {
dateTimeService = new DateTimeService();
Cluster cluster = new ClusterBuilder()
- .addContactPoints("127.0.0.1")
- .withCredentials("cassandra", "cassandra")
+ .addContactPoints("127.0.0.1", "127.0.02")
+ .withCredentials("rhqadmin", "rhqadmin")
.build();
session = cluster.connect("rhq");
}
diff --git a/modules/enterprise/server/server-metrics/src/test/resources/log4j.properties b/modules/enterprise/server/server-metrics/src/test/resources/log4j.properties
index c13e2bd..67db049 100644
--- a/modules/enterprise/server/server-metrics/src/test/resources/log4j.properties
+++ b/modules/enterprise/server/server-metrics/src/test/resources/log4j.properties
@@ -39,4 +39,4 @@ log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c %m%n
log4j.logger.org.rhq=DEBUG
-log4j.logger.com.datastax=INFO
+log4j.logger.com.datastax=DEBUG
diff --git a/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java b/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java
index 5bb31aa..7ff8f6c 100644
--- a/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java
+++ b/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java
@@ -217,7 +217,7 @@ public class Simulator implements ShutdownManager {
private void createSchema(List<StorageNode> nodes) {
try {
log.info("Creating schema");
- SchemaManager schemaManager = new SchemaManager("cassandra", "cassandra", nodes);
+ SchemaManager schemaManager = new SchemaManager("rhqadmin", "rhqadmin", nodes);
schemaManager.install();
} catch (Exception e) {
throw new RuntimeException("Failed to start simulator. An error occurred during schema creation.", e);
commit 1eaba6617616aa4a511180bc27bcb36978ca029d
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 19 16:57:04 2013 -0400
do schema check via jmx instead of over cql
Initializing and tearing down a session to check the schema version on each
ndode is rather inefficient. Doing it over jmx is faster and simpler and will
speed up test code.
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java
index 707914a..ac2313b 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java
+++ b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java
@@ -68,25 +68,6 @@ public final class ClusterInitService {
private final Log log = LogFactory.getLog(ClusterInitService.class);
- private Session initRhqSession(List<StorageNode> storageNodes) {
- return initSession(storageNodes, "rhq", "rhqadmin", "rhqadmin");
- }
-
- private Session initSession(List<StorageNode> hosts, String keySpace, String username, String password) {
- if (hosts == null) {
- throw new IllegalArgumentException("No cassandra nodes were provided.");
- }
- String[] addresses = new String[hosts.size()];
- for (int i = 0; i < hosts.size(); i++) {
- addresses[i] = hosts.get(i).getAddress();
- }
- Cluster cluster = Cluster.builder().addContactPoints(addresses).withoutMetrics()
- .withCredentials(username, password)
- .build();
- Session session = cluster.connect(keySpace);
- return session;
- }
-
public boolean ping(List<StorageNode> storageNodes, int numHosts) {
int connections = 0;
long sleep = 100;
@@ -240,7 +221,7 @@ public final class ClusterInitService {
*
* @param hosts The cluster nodes
*/
- public void waitForSchemaAgreement(List<StorageNode> storageNodes) {
+ public void waitForSchemaAgreement(List<StorageNode> storageNodes) throws Exception {
if (storageNodes == null) {
return;
}
@@ -249,15 +230,13 @@ public final class ClusterInitService {
boolean schemaInAgreement = false;
while (!schemaInAgreement) {
- Set<UUID> schemaVersions = new HashSet<UUID>();
- try {
+ Set<String> schemaVersions = new HashSet<String>();
for (StorageNode host : storageNodes) {
- UUID otherSchchemaVersion = getSchemaVersionForNode(host);
- schemaVersions.add(otherSchchemaVersion);
+ String otherSchchemaVersion = getSchemaVersionForNode(host);
+ if (otherSchchemaVersion != null) {
+ schemaVersions.add(otherSchchemaVersion);
+ }
}
- } catch (NoHostAvailableException e) {
- throw new RuntimeException("Unable to get schema versions from " + storageNodes.get(0), e);
- }
if (schemaVersions.size() > 1) {
if (log.isInfoEnabled()) {
log.info("Schema agreement has not been reached. Found " + schemaVersions.size() +
@@ -271,7 +250,7 @@ public final class ClusterInitService {
} catch (InterruptedException e) {
}
} else {
- UUID schemaVersion = schemaVersions.iterator().next();
+ String schemaVersion = schemaVersions.iterator().next();
if (schemaVersion != null) {
schemaInAgreement = true;
} else {
@@ -327,21 +306,40 @@ public final class ClusterInitService {
return nativeTransportRunning;
}
- private UUID getSchemaVersionForNode(StorageNode storageNode) {
- Session session = null;
+ private String getSchemaVersionForNode(StorageNode storageNode) throws Exception {
+ String url = storageNode.getJMXConnectionURL();
+ JMXServiceURL serviceURL = new JMXServiceURL(url);
+ Map<String, String> env = new HashMap<String, String>();
+ // see https://issues.jboss.org/browse/AS7-2138
+ env.put(Context.INITIAL_CONTEXT_FACTORY, RMIContextFactory.class.getName());
+ JMXConnector connector = null;
+
try {
- session = initRhqSession(Arrays.asList(storageNode));
- PreparedStatement statement = session.prepare("SELECT schema_version from system.local");
- BoundStatement boundStatement = statement.bind();
- ResultSet rs = session.execute(boundStatement);
- for (Row row : rs) {
- return row.getUUID(0);
+ connector = JMXConnectorFactory.connect(serviceURL, env);
+ MBeanServerConnection serverConnection = connector.getMBeanServerConnection();
+ ObjectName storageService = new ObjectName("org.apache.cassandra.db:type=StorageService");
+ String attribute = "SchemaVersion";
+ try {
+ return (String) serverConnection.getAttribute(storageService, attribute);
+ } catch (Exception e) {
+ // It is ok to just catch and log exceptions here particularly in an integration
+ // test environment where we could potentially try to do the JMX query before
+ // Cassandra is fully initialized. We can query StorageService before the native
+ // transport server is initialized which will result in Cassandra throwing a NPE.
+ // We do not want propagate that exception because it is just a matter of waiting
+ // for Cassandra to finish initializing.
+ if (log.isDebugEnabled()) {
+ log.debug("Failed to read attribute [" + attribute + "] from " + storageService, e);
+ } else {
+ log.info("Faied to read attribute [" + attribute + "] from " + storageService + ": " +
+ e.getMessage());
+ }
}
- return null;
} finally {
- if (session != null)
- session.getCluster().shutdown();
+ if (connector != null) {
+ connector.close();
+ }
}
+ return null;
}
-
}
\ No newline at end of file
10 years, 11 months
[rhq] modules/enterprise
by mike thompson
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit a5819303fa8ef5e5047b86933b55ead9d7ad6768
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 16:25:58 2013 -0700
Fix issue with cut down version of Portal graph as it is loosing last value (off by one error).
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index b1f0648..33d0303 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -118,7 +118,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
width = 250;
xTicks = 3;
xTickSubDivide = 2;
- chartData = chartContext.data.slice(chartContext.data.length - numberOfBarsForSmallGraph, chartContext.data.length - 1);
+ chartData = chartContext.data.slice(chartContext.data.length - numberOfBarsForSmallGraph, chartContext.data.length);
}
else {
console.log("Using Large Charts Profile");
10 years, 11 months
[rhq] 65 commits - modules/enterprise
by mike thompson
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java | 21
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AbstractGraph.java | 174
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java | 41
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java | 307
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java | 383
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/HasD3MetricJsniChart.java | 38
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/LineMetricGraph.java | 155
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java | 456
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java | 89
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java | 46
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java | 622
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java | 222
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AvailabilityGraphType.java | 44
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java | 329
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/HasD3MetricJsniChart.java | 38
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java | 454
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/RedrawGraphs.java | 29
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityLineGraphType.java | 308
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java | 384
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java | 158
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java | 92
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java | 49
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java | 677
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java | 37
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupD3GraphListView.java | 130
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableDataSource.java | 175
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableView.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMetricsTableDataSource.java | 175
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java | 4
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java | 60
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java | 243
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java | 211
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java | 180
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java | 123
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java | 124
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java | 164
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java | 152
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java | 166
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/preferences/MeasurementUserPreferences.java | 112
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml | 14
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 18
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties | 20
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties | 11
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 18
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties | 18
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties | 18
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties | 18
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties | 18
modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html | 12
modules/enterprise/gui/coregui/src/main/webapp/css/charts.css | 13
modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js |12891 +++++-----
modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js | 9
modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.js | 9597 +++++++
modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.min.js | 5
modules/enterprise/gui/coregui/src/main/webapp/js/moment.js | 1400 +
modules/enterprise/gui/coregui/src/main/webapp/js/moment.min.js | 6
modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js | 155
modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js | 6
modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js | 56
64 files changed, 21937 insertions(+), 9573 deletions(-)
New commits:
commit 979ee1876f024e1ae54d1347ff6ff68512b4afcd
Merge: 3ca9f21 8b13859
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Wed Jun 19 15:31:52 2013 -0700
Merge branch 'mtho11/d3-slider'
commit 8b1385965c523bfefb2686b63257883a1b51d2b9
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 14:59:22 2013 -0700
Remove old style Date Range control from MeasurementTableView.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index 9cb5c6a..1d456f4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -32,8 +32,6 @@ import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.CloseClickEvent;
import com.smartgwt.client.widgets.events.CloseClickHandler;
-import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
-import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
@@ -44,7 +42,6 @@ import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.core.domain.resource.composite.ResourceComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.components.table.Table;
import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
@@ -72,7 +69,6 @@ public class MeasurementTableView extends Table<MetricsTableDataSource> {
protected void configureTable() {
ArrayList<ListGridField> fields = getDataSource().getListGridFields();
setListGridFields(fields.toArray(new ListGridField[0]));
- addExtraWidget(new UserPreferencesMeasurementRangeEditor(), true);
addTableAction(MSG.view_measureTable_getLive(), new TableAction() {
@Override
public boolean isEnabled(ListGridRecord[] selection) {
commit 09aa4cdbc35c59a3885d2ff31c9c29ab0874ffd0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 12:14:08 2013 -0700
Remove the d3GraphView.addSetButtonClickHandler() as this is now done with new ButtonBarDateTimeEditor.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index 4c47d3f..3a0c67f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -282,12 +282,6 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
graphView = D3GraphListView
.createSingleGraph(resourceComposite.getResource(),
md.getId(), true);
- graphView.addSetButtonClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- graphView.redrawGraphs();
- }
- });
window.addItem(graphView);
window.show();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 5bfb2af..65893ce 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -46,7 +46,6 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
@@ -116,11 +115,6 @@ public class D3GraphListView extends AbstractD3GraphListView {
setOverflow(Overflow.HIDDEN);
}
- @Deprecated
- public void addSetButtonClickHandler(ClickHandler clickHandler) {
- Log.debug("measurementRangeEditor " + buttonBarDateTimeRangeEditor);
- // graphDateTimeRangeEditor.getSetButton().addClickHandler(clickHandler);
- }
@Override
protected void onDraw() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index a326145..9cb5c6a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -189,12 +189,7 @@ public class MeasurementTableView extends Table<MetricsTableDataSource> {
ChartViewWindow window = new ChartViewWindow("");
final D3GraphListView graphListView = D3GraphListView.createMultipleGraphs(
resourceComposite.getResource(), definitionIds, true);
- graphListView.addSetButtonClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- graphListView.redrawGraphs();
- }
- });
+
window.addItem(graphListView);
window.show();
refreshTableInfo();
commit 04358537f17203ba1a7a0a39311a9f3d5aff6e21
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 11:45:27 2013 -0700
Eliminate Charting brush resize 'handles' code as that has been removed.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 5b4b408..b1f0648 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -538,27 +538,9 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
}
function createBrush(){
- // slightly modified but originally from crossfilter (http://square.github.com/crossfilter/)
- var resizePath = function (d) {
- var e1 = +(d === "e"),
- e = e1 ? 1 : 0 ,
- x = e ? 1 : -1,
- y = height / 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);
- },
- brush = $wnd.d3.svg.brush()
+
+ var brush = $wnd.d3.svg.brush()
.x(timeScale)
- //.extent($wnd.d3.extent(chartData, function (d) {
- //return d.x;
- //}))
.on("brushstart", brushstart)
.on("brush", brushmove)
.on("brushend", brushend),
@@ -589,9 +571,6 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::redrawGraphs()();
}
- //brushstart();
- //brushmove();
-
function updateDateRangeDisplay(startDate, endDate ) {
//@todo: i18n the date format
var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
commit 83888bc0e47e1b78150688f17d43cb32754ab7f0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 08:53:37 2013 -0700
Remove bootstrap css and js as it is not needed now for dual slider chart control.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.css b/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.css
deleted file mode 100755
index e5e2ce3..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.css
+++ /dev/null
@@ -1,766 +0,0 @@
-/*!
- * Bootstrap v2.3.1
- *
- * Copyright 2012 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- */
-.clearfix {
- *zoom: 1;
-}
-
-.clearfix:before,
-.clearfix:after {
- display: table;
- content: "";
- line-height: 0;
-}
-
-.clearfix:after {
- clear: both;
-}
-
-.hide-text {
- font: 0/0 a;
- color: transparent;
- text-shadow: none;
- background-color: transparent;
- border: 0;
-}
-
-.input-block-level {
- display: block;
- width: 100%;
- min-height: 30px;
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-.btn {
- display: inline-block;
- *display: inline;
- /* IE7 inline-block hack */
-
- *zoom: 1;
- padding: 4px 12px;
- margin-bottom: 0;
- font-size: 14px;
- line-height: 20px;
- text-align: center;
- vertical-align: middle;
- cursor: pointer;
- color: #333333;
- text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
- background-color: #f5f5f5;
- background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
- background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
- background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
- background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
- background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
- border-color: #e6e6e6 #e6e6e6 #bfbfbf;
- border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
- *background-color: #e6e6e6;
- /* Darken IE7 buttons by default so they stand out more given they won't have borders */
-
- filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
- border: 1px solid #cccccc;
- *border: 0;
- border-bottom-color: #b3b3b3;
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- border-radius: 4px;
- *margin-left: .3em;
- -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
- -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
-}
-
-.btn:hover,
-.btn:focus,
-.btn:active,
-.btn.active,
-.btn.disabled,
-.btn[disabled] {
- color: #333333;
- background-color: #e6e6e6;
- *background-color: #d9d9d9;
-}
-
-.btn:active,
-.btn.active {
- background-color: #cccccc \9;
-}
-
-.btn:first-child {
- *margin-left: 0;
-}
-
-.btn:hover,
-.btn:focus {
- color: #333333;
- text-decoration: none;
- background-position: 0 -15px;
- -webkit-transition: background-position 0.1s linear;
- -moz-transition: background-position 0.1s linear;
- -o-transition: background-position 0.1s linear;
- transition: background-position 0.1s linear;
-}
-
-.btn:focus {
- outline: thin dotted #333;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-
-.btn.active,
-.btn:active {
- background-image: none;
- outline: 0;
- -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
- -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
- box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
-}
-
-.btn.disabled,
-.btn[disabled] {
- cursor: default;
- background-image: none;
- opacity: 0.65;
- filter: alpha(opacity=65);
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- box-shadow: none;
-}
-
-.btn-large {
- padding: 11px 19px;
- font-size: 17.5px;
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
-}
-
-.btn-large [class^="icon-"],
-.btn-large [class*=" icon-"] {
- margin-top: 4px;
-}
-
-.btn-small {
- padding: 2px 10px;
- font-size: 11.9px;
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- border-radius: 3px;
-}
-
-.btn-small [class^="icon-"],
-.btn-small [class*=" icon-"] {
- margin-top: 0;
-}
-
-.btn-mini [class^="icon-"],
-.btn-mini [class*=" icon-"] {
- margin-top: -1px;
-}
-
-.btn-mini {
- padding: 0 6px;
- font-size: 10.5px;
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- border-radius: 3px;
-}
-
-.btn-block {
- display: block;
- width: 100%;
- padding-left: 0;
- padding-right: 0;
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-.btn-block + .btn-block {
- margin-top: 5px;
-}
-
-input[type="submit"].btn-block,
-input[type="reset"].btn-block,
-input[type="button"].btn-block {
- width: 100%;
-}
-
-.btn-primary.active,
-.btn-warning.active,
-.btn-danger.active,
-.btn-success.active,
-.btn-info.active,
-.btn-inverse.active {
- color: rgba(255, 255, 255, 0.75);
-}
-
-.btn-primary {
- color: #ffffff;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
- background-color: #006dcc;
- background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
- background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
- background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
- background-image: -o-linear-gradient(top, #0088cc, #0044cc);
- background-image: linear-gradient(to bottom, #0088cc, #0044cc);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
- border-color: #0044cc #0044cc #002a80;
- border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
- *background-color: #0044cc;
- /* Darken IE7 buttons by default so they stand out more given they won't have borders */
-
- filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-primary:hover,
-.btn-primary:focus,
-.btn-primary:active,
-.btn-primary.active,
-.btn-primary.disabled,
-.btn-primary[disabled] {
- color: #ffffff;
- background-color: #0044cc;
- *background-color: #003bb3;
-}
-
-.btn-primary:active,
-.btn-primary.active {
- background-color: #003399 \9;
-}
-
-.btn-warning {
- color: #ffffff;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
- background-color: #faa732;
- background-image: -moz-linear-gradient(top, #fbb450, #f89406);
- background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
- background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
- background-image: -o-linear-gradient(top, #fbb450, #f89406);
- background-image: linear-gradient(to bottom, #fbb450, #f89406);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
- border-color: #f89406 #f89406 #ad6704;
- border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
- *background-color: #f89406;
- /* Darken IE7 buttons by default so they stand out more given they won't have borders */
-
- filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-warning:hover,
-.btn-warning:focus,
-.btn-warning:active,
-.btn-warning.active,
-.btn-warning.disabled,
-.btn-warning[disabled] {
- color: #ffffff;
- background-color: #f89406;
- *background-color: #df8505;
-}
-
-.btn-warning:active,
-.btn-warning.active {
- background-color: #c67605 \9;
-}
-
-.btn-danger {
- color: #ffffff;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
- background-color: #da4f49;
- background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
- background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
- background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
- background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
- background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
- border-color: #bd362f #bd362f #802420;
- border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
- *background-color: #bd362f;
- /* Darken IE7 buttons by default so they stand out more given they won't have borders */
-
- filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-danger:hover,
-.btn-danger:focus,
-.btn-danger:active,
-.btn-danger.active,
-.btn-danger.disabled,
-.btn-danger[disabled] {
- color: #ffffff;
- background-color: #bd362f;
- *background-color: #a9302a;
-}
-
-.btn-danger:active,
-.btn-danger.active {
- background-color: #942a25 \9;
-}
-
-.btn-success {
- color: #ffffff;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
- background-color: #5bb75b;
- background-image: -moz-linear-gradient(top, #62c462, #51a351);
- background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
- background-image: -webkit-linear-gradient(top, #62c462, #51a351);
- background-image: -o-linear-gradient(top, #62c462, #51a351);
- background-image: linear-gradient(to bottom, #62c462, #51a351);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
- border-color: #51a351 #51a351 #387038;
- border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
- *background-color: #51a351;
- /* Darken IE7 buttons by default so they stand out more given they won't have borders */
-
- filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-success:hover,
-.btn-success:focus,
-.btn-success:active,
-.btn-success.active,
-.btn-success.disabled,
-.btn-success[disabled] {
- color: #ffffff;
- background-color: #51a351;
- *background-color: #499249;
-}
-
-.btn-success:active,
-.btn-success.active {
- background-color: #408140 \9;
-}
-
-.btn-info {
- color: #ffffff;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
- background-color: #49afcd;
- background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
- background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
- background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
- background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
- background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
- border-color: #2f96b4 #2f96b4 #1f6377;
- border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
- *background-color: #2f96b4;
- /* Darken IE7 buttons by default so they stand out more given they won't have borders */
-
- filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-info:hover,
-.btn-info:focus,
-.btn-info:active,
-.btn-info.active,
-.btn-info.disabled,
-.btn-info[disabled] {
- color: #ffffff;
- background-color: #2f96b4;
- *background-color: #2a85a0;
-}
-
-.btn-info:active,
-.btn-info.active {
- background-color: #24748c \9;
-}
-
-.btn-inverse {
- color: #ffffff;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
- background-color: #363636;
- background-image: -moz-linear-gradient(top, #444444, #222222);
- background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
- background-image: -webkit-linear-gradient(top, #444444, #222222);
- background-image: -o-linear-gradient(top, #444444, #222222);
- background-image: linear-gradient(to bottom, #444444, #222222);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
- border-color: #222222 #222222 #000000;
- border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
- *background-color: #222222;
- /* Darken IE7 buttons by default so they stand out more given they won't have borders */
-
- filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-inverse:hover,
-.btn-inverse:focus,
-.btn-inverse:active,
-.btn-inverse.active,
-.btn-inverse.disabled,
-.btn-inverse[disabled] {
- color: #ffffff;
- background-color: #222222;
- *background-color: #151515;
-}
-
-.btn-inverse:active,
-.btn-inverse.active {
- background-color: #080808 \9;
-}
-
-button.btn,
-input[type="submit"].btn {
- *padding-top: 3px;
- *padding-bottom: 3px;
-}
-
-button.btn::-moz-focus-inner,
-input[type="submit"].btn::-moz-focus-inner {
- padding: 0;
- border: 0;
-}
-
-button.btn.btn-large,
-input[type="submit"].btn.btn-large {
- *padding-top: 7px;
- *padding-bottom: 7px;
-}
-
-button.btn.btn-small,
-input[type="submit"].btn.btn-small {
- *padding-top: 3px;
- *padding-bottom: 3px;
-}
-
-button.btn.btn-mini,
-input[type="submit"].btn.btn-mini {
- *padding-top: 1px;
- *padding-bottom: 1px;
-}
-
-.btn-link,
-.btn-link:active,
-.btn-link[disabled] {
- background-color: transparent;
- background-image: none;
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- box-shadow: none;
-}
-
-.btn-link {
- border-color: transparent;
- cursor: pointer;
- color: #0088cc;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- border-radius: 0;
-}
-
-.btn-link:hover,
-.btn-link:focus {
- color: #005580;
- text-decoration: underline;
- background-color: transparent;
-}
-
-.btn-link[disabled]:hover,
-.btn-link[disabled]:focus {
- color: #333333;
- text-decoration: none;
-}
-
-.btn-group {
- position: relative;
- display: inline-block;
- *display: inline;
- /* IE7 inline-block hack */
-
- *zoom: 1;
- font-size: 0;
- vertical-align: middle;
- white-space: nowrap;
- *margin-left: .3em;
-}
-
-.btn-group:first-child {
- *margin-left: 0;
-}
-
-.btn-group + .btn-group {
- margin-left: 5px;
-}
-
-.btn-toolbar {
- font-size: 0;
- margin-top: 10px;
- margin-bottom: 10px;
-}
-
-.btn-toolbar > .btn + .btn,
-.btn-toolbar > .btn-group + .btn,
-.btn-toolbar > .btn + .btn-group {
- margin-left: 5px;
-}
-
-.btn-group > .btn {
- position: relative;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- border-radius: 0;
-}
-
-.btn-group > .btn + .btn {
- margin-left: -1px;
-}
-
-.btn-group > .btn,
-.btn-group > .dropdown-menu,
-.btn-group > .popover {
- font-size: 12px;
-}
-
-.btn-group > .btn-mini {
- font-size: 10.5px;
-}
-
-.btn-group > .btn-small {
- font-size: 11.9px;
-}
-
-.btn-group > .btn-large {
- font-size: 17.5px;
-}
-
-.btn-group > .btn:first-child {
- margin-left: 0;
- -webkit-border-top-left-radius: 4px;
- -moz-border-radius-topleft: 4px;
- border-top-left-radius: 4px;
- -webkit-border-bottom-left-radius: 4px;
- -moz-border-radius-bottomleft: 4px;
- border-bottom-left-radius: 4px;
-}
-
-.btn-group > .btn:last-child,
-.btn-group > .dropdown-toggle {
- -webkit-border-top-right-radius: 4px;
- -moz-border-radius-topright: 4px;
- border-top-right-radius: 4px;
- -webkit-border-bottom-right-radius: 4px;
- -moz-border-radius-bottomright: 4px;
- border-bottom-right-radius: 4px;
-}
-
-.btn-group > .btn.large:first-child {
- margin-left: 0;
- -webkit-border-top-left-radius: 6px;
- -moz-border-radius-topleft: 6px;
- border-top-left-radius: 6px;
- -webkit-border-bottom-left-radius: 6px;
- -moz-border-radius-bottomleft: 6px;
- border-bottom-left-radius: 6px;
-}
-
-.btn-group > .btn.large:last-child,
-.btn-group > .large.dropdown-toggle {
- -webkit-border-top-right-radius: 6px;
- -moz-border-radius-topright: 6px;
- border-top-right-radius: 6px;
- -webkit-border-bottom-right-radius: 6px;
- -moz-border-radius-bottomright: 6px;
- border-bottom-right-radius: 6px;
-}
-
-.btn-group > .btn:hover,
-.btn-group > .btn:focus,
-.btn-group > .btn:active,
-.btn-group > .btn.active {
- z-index: 2;
-}
-
-.btn-group .dropdown-toggle:active,
-.btn-group.open .dropdown-toggle {
- outline: 0;
-}
-
-.btn-group > .btn + .dropdown-toggle {
- padding-left: 8px;
- padding-right: 8px;
- -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, .125), inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
- -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, .125), inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
- box-shadow: inset 1px 0 0 rgba(255, 255, 255, .125), inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
- *padding-top: 5px;
- *padding-bottom: 5px;
-}
-
-.btn-group > .btn-mini + .dropdown-toggle {
- padding-left: 5px;
- padding-right: 5px;
- *padding-top: 2px;
- *padding-bottom: 2px;
-}
-
-.btn-group > .btn-small + .dropdown-toggle {
- *padding-top: 5px;
- *padding-bottom: 4px;
-}
-
-.btn-group > .btn-large + .dropdown-toggle {
- padding-left: 12px;
- padding-right: 12px;
- *padding-top: 7px;
- *padding-bottom: 7px;
-}
-
-.btn-group.open .dropdown-toggle {
- background-image: none;
- -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
- -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
- box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
-}
-
-.btn-group.open .btn.dropdown-toggle {
- background-color: #e6e6e6;
-}
-
-.btn-group.open .btn-primary.dropdown-toggle {
- background-color: #0044cc;
-}
-
-.btn-group.open .btn-warning.dropdown-toggle {
- background-color: #f89406;
-}
-
-.btn-group.open .btn-danger.dropdown-toggle {
- background-color: #bd362f;
-}
-
-.btn-group.open .btn-success.dropdown-toggle {
- background-color: #51a351;
-}
-
-.btn-group.open .btn-info.dropdown-toggle {
- background-color: #2f96b4;
-}
-
-.btn-group.open .btn-inverse.dropdown-toggle {
- background-color: #222222;
-}
-
-.btn .caret {
- margin-top: 8px;
- margin-left: 0;
-}
-
-.btn-large .caret {
- margin-top: 6px;
-}
-
-.btn-large .caret {
- border-left-width: 5px;
- border-right-width: 5px;
- border-top-width: 5px;
-}
-
-.btn-mini .caret,
-.btn-small .caret {
- margin-top: 8px;
-}
-
-.dropup .btn-large .caret {
- border-bottom-width: 5px;
-}
-
-.btn-primary .caret,
-.btn-warning .caret,
-.btn-danger .caret,
-.btn-info .caret,
-.btn-success .caret,
-.btn-inverse .caret {
- border-top-color: #ffffff;
- border-bottom-color: #ffffff;
-}
-
-.btn-group-vertical {
- display: inline-block;
- *display: inline;
- /* IE7 inline-block hack */
-
- *zoom: 1;
-}
-
-.btn-group-vertical > .btn {
- display: block;
- float: none;
- max-width: 100%;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- border-radius: 0;
-}
-
-.btn-group-vertical > .btn + .btn {
- margin-left: 0;
- margin-top: -1px;
-}
-
-.btn-group-vertical > .btn:first-child {
- -webkit-border-radius: 4px 4px 0 0;
- -moz-border-radius: 4px 4px 0 0;
- border-radius: 4px 4px 0 0;
-}
-
-.btn-group-vertical > .btn:last-child {
- -webkit-border-radius: 0 0 4px 4px;
- -moz-border-radius: 0 0 4px 4px;
- border-radius: 0 0 4px 4px;
-}
-
-.btn-group-vertical > .btn-large:first-child {
- -webkit-border-radius: 6px 6px 0 0;
- -moz-border-radius: 6px 6px 0 0;
- border-radius: 6px 6px 0 0;
-}
-
-.btn-group-vertical > .btn-large:last-child {
- -webkit-border-radius: 0 0 6px 6px;
- -moz-border-radius: 0 0 6px 6px;
- border-radius: 0 0 6px 6px;
-}
-
-.accordion {
- margin-bottom: 20px;
-}
-
-.accordion-group {
- margin-bottom: 2px;
- border: 1px solid #e5e5e5;
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- border-radius: 4px;
-}
-
-.accordion-heading {
- border-bottom: 0;
-}
-
-.accordion-heading .accordion-toggle {
- display: block;
- padding: 8px 15px;
-}
-
-.accordion-toggle {
- cursor: pointer;
-}
-
-.accordion-inner {
- padding: 9px 15px;
- border-top: 1px solid #e5e5e5;
-}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.min.css b/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.min.css
deleted file mode 100755
index 4d7b8c7..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.min.css
+++ /dev/null
@@ -1,96 +0,0 @@
-/*!
- * Bootstrap v2.3.1
- *
- * Copyright 2012 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- */
-.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;}
-.clearfix:after{clear:both;}
-.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}
-.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
-.btn{display:inline-block;*display:inline;*zoom:1;padding:4px 12px;margin-bottom:0;font-size:14px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#333333;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #ffffff, #e6e6e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(top, #ffffff, #e6e6e6);background-image:-o-linear-gradient(top, #ffffff, #e6e6e6);background-image:linear-gradient(to bottom, #ffffff, #e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #cccccc;*border:0;border-bottom-color:#b
3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333333;background-color:#e6e6e6;*background-color:#d9d9d9;}
-.btn:active,.btn.active{background-color:#cccccc \9;}
-.btn:first-child{*margin-left:0;}
-.btn:hover,.btn:focus{color:#333333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;}
-.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
-.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
-.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
-.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
-.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px;}
-.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
-.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0;}
-.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px;}
-.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
-.btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
-.btn-block+.btn-block{margin-top:5px;}
-input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;}
-.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255, 255, 255, 0.75);}
-.btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(to bottom, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#0044cc;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#ffffff;background-color:#0044cc;*background-color:#003bb3;}
-.btn-primary:active,.btn-primary.active{background-color:#003399 \9;}
-.btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#ffffff;background-color:#f89406;*background-color:#df8505;}
-.btn-warning:active,.btn-warning.active{background-color:#c67605 \9;}
-.btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(to bottom, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#ffffff;background-color:#bd362f;*background-color:#a9302a;}
-.btn-danger:active,.btn-danger.active{background-color:#942a25 \9;}
-.btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(to bottom, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#ffffff;background-color:#51a351;*background-color:#499249;}
-.btn-success:active,.btn-success.active{background-color:#408140 \9;}
-.btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(to bottom, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#ffffff;background-color:#2f96b4;*background-color:#2a85a0;}
-.btn-info:active,.btn-info.active{background-color:#24748c \9;}
-.btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#363636;background-image:-moz-linear-gradient(top, #444444, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));background-image:-webkit-linear-gradient(top, #444444, #222222);background-image:-o-linear-gradient(top, #444444, #222222);background-image:linear-gradient(to bottom, #444444, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#222222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#ffffff;background-color:#222222;*background-color:#151515;}
-.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9;}
-button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}
-button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px;}
-button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px;}
-button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px;}
-.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
-.btn-link{border-color:transparent;cursor:pointer;color:#0088cc;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
-.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent;}
-.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333333;text-decoration:none;}
-.btn-group{position:relative;display:inline-block;*display:inline;*zoom:1;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em;}.btn-group:first-child{*margin-left:0;}
-.btn-group+.btn-group{margin-left:5px;}
-.btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px;}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px;}
-.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
-.btn-group>.btn+.btn{margin-left:-1px;}
-.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px;}
-.btn-group>.btn-mini{font-size:10.5px;}
-.btn-group>.btn-small{font-size:11.9px;}
-.btn-group>.btn-large{font-size:17.5px;}
-.btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
-.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
-.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
-.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
-.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2;}
-.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}
-.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);*padding-top:5px;*padding-bottom:5px;}
-.btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px;}
-.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px;}
-.btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px;}
-.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
-.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6;}
-.btn-group.open .btn-primary.dropdown-toggle{background-color:#0044cc;}
-.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406;}
-.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f;}
-.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351;}
-.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4;}
-.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222222;}
-.btn .caret{margin-top:8px;margin-left:0;}
-.btn-large .caret{margin-top:6px;}
-.btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px;}
-.btn-mini .caret,.btn-small .caret{margin-top:8px;}
-.dropup .btn-large .caret{border-bottom-width:5px;}
-.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
-.btn-group-vertical{display:inline-block;*display:inline;*zoom:1;}
-.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
-.btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px;}
-.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}
-.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}
-.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0;}
-.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;}
-.accordion{margin-bottom:20px;}
-.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
-.accordion-heading{border-bottom:0;}
-.accordion-heading .accordion-toggle{display:block;padding:8px 15px;}
-.accordion-toggle{cursor:pointer;}
-.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.js b/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.js
deleted file mode 100755
index b5ca464..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.js
+++ /dev/null
@@ -1,165 +0,0 @@
-/* ===================================================
- * bootstrap-transition.js v2.3.1
- * http://twitter.github.com/bootstrap/javascript.html#transitions
- * ===================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed 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.
- * ========================================================== */
-
-
-!function ($) {
-
- "use strict"; // jshint ;_;
-
-
- /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
- * ======================================================= */
-
- $(function () {
-
- $.support.transition = (function () {
-
- var transitionEnd = (function () {
-
- var el = document.createElement('bootstrap')
- , transEndEventNames = {
- 'WebkitTransition' : 'webkitTransitionEnd'
- , 'MozTransition' : 'transitionend'
- , 'OTransition' : 'oTransitionEnd otransitionend'
- , 'transition' : 'transitionend'
- }
- , name
-
- for (name in transEndEventNames){
- if (el.style[name] !== undefined) {
- return transEndEventNames[name]
- }
- }
-
- }())
-
- return transitionEnd && {
- end: transitionEnd
- }
-
- })()
-
- })
-
-}(window.jQuery);
-/* ============================================================
- * bootstrap-button.js v2.3.1
- * http://twitter.github.com/bootstrap/javascript.html#buttons
- * ============================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed 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.
- * ============================================================ */
-
-
-!function ($) {
-
- "use strict"; // jshint ;_;
-
-
- /* BUTTON PUBLIC CLASS DEFINITION
- * ============================== */
-
- var Button = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, $.fn.button.defaults, options)
- }
-
- Button.prototype.setState = function (state) {
- var d = 'disabled'
- , $el = this.$element
- , data = $el.data()
- , val = $el.is('input') ? 'val' : 'html'
-
- state = state + 'Text'
- data.resetText || $el.data('resetText', $el[val]())
-
- $el[val](data[state] || this.options[state])
-
- // push to event loop to allow forms to submit
- setTimeout(function () {
- state == 'loadingText' ?
- $el.addClass(d).attr(d, d) :
- $el.removeClass(d).removeAttr(d)
- }, 0)
- }
-
- Button.prototype.toggle = function () {
- var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
-
- $parent && $parent
- .find('.active')
- .removeClass('active')
-
- this.$element.toggleClass('active')
- }
-
-
- /* BUTTON PLUGIN DEFINITION
- * ======================== */
-
- var old = $.fn.button
-
- $.fn.button = function (option) {
- return this.each(function () {
- var $this = $(this)
- , data = $this.data('button')
- , options = typeof option == 'object' && option
- if (!data) $this.data('button', (data = new Button(this, options)))
- if (option == 'toggle') data.toggle()
- else if (option) data.setState(option)
- })
- }
-
- $.fn.button.defaults = {
- loadingText: 'loading...'
- }
-
- $.fn.button.Constructor = Button
-
-
- /* BUTTON NO CONFLICT
- * ================== */
-
- $.fn.button.noConflict = function () {
- $.fn.button = old
- return this
- }
-
-
- /* BUTTON DATA-API
- * =============== */
-
- $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
- var $btn = $(e.target)
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
- $btn.button('toggle')
- })
-
-}(window.jQuery);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.min.js
deleted file mode 100755
index ba3c81a..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
-* Bootstrap.js by @fat & @mdo
-* plugins: bootstrap-transition.js, bootstrap-button.js
-* Copyright 2012 Twitter, Inc.
-* http://www.apache.org/licenses/LICENSE-2.0.txt
-*/
-!function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(t
his),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})}(window.jQuery)
\ No newline at end of file
commit 85b69b5e7391ecbfc36ea006f4022b6536ff5ab0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 18 20:36:10 2013 -0700
Button alignment with form and form height change.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 2dfaaf1..2cda97b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -255,7 +255,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
setIsModal(true);
setShowModalMask(true);
setWidth(450);
- setHeight(300);
+ setHeight(340);
setShowResizer(true);
setCanDragResize(true);
centerInPage();
@@ -281,7 +281,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
this.addItem(form);
HLayout buttonHLayout = new HLayout();
- buttonHLayout.setMargin(15);
+ buttonHLayout.setMargin(75);
buttonHLayout.setMembersMargin(20);
IButton cancelButton = new IButton(MSG.common_buttonbar_custom_cancel());
cancelButton.addClickHandler(new ClickHandler() {
commit 2b8eb5e3551e4beaed4bfcce9e505584936ddf8c
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 18 18:56:44 2013 -0700
Update the composite multi-line graph to use the new date range navigation.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index 9ceb5f8..29428ae 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -30,6 +30,7 @@ import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.AutoRefreshUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.RedrawGraphs;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -39,7 +40,7 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPre
* Provide the shared stuff for create GraphListViews like Availability graphs
* and User Preferences pickers for the date range.
*/
-public abstract class AbstractD3GraphListView extends EnhancedVLayout implements AutoRefresh {
+public abstract class AbstractD3GraphListView extends EnhancedVLayout implements AutoRefresh,RedrawGraphs {
protected final static int SINGLE_CHART_HEIGHT = 225;
protected final static int MULTI_CHART_HEIGHT = 210;
protected static Label loadingLabel = new Label(MSG.common_msg_loading());
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index ac2462c..2dfaaf1 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -33,7 +33,6 @@ import com.smartgwt.client.widgets.events.CloseClickEvent;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.DateItem;
-import com.smartgwt.client.widgets.form.fields.DateTimeItem;
import com.smartgwt.client.widgets.form.fields.RowSpacerItem;
import com.smartgwt.client.widgets.form.fields.TimeItem;
import com.smartgwt.client.widgets.layout.HLayout;
@@ -42,7 +41,6 @@ import com.smartgwt.client.widgets.toolbar.ToolStrip;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -61,7 +59,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
static final int BUTTON_WIDTH = 28;
private MeasurementUserPreferences measurementUserPreferences;
- private AbstractD3GraphListView d3GraphListView;
+ private RedrawGraphs d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
private Label dateRangeLabel;
private static final DateTimeFormat fmt = DateTimeFormat.getFormat(MSG.common_buttonbar_datetime_format());
@@ -70,7 +68,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
final private ButtonBarDateTimeRangeEditor self;
public ButtonBarDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
- AbstractD3GraphListView d3GraphListView) {
+ RedrawGraphs d3GraphListView) {
this.self = this;
this.measurementUserPreferences = measurementUserPrefs;
this.d3GraphListView = d3GraphListView;
@@ -248,11 +246,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
public class CustomDateRangeWindow extends Window {
public CustomDateRangeWindow(String title, String windowTitle,
- final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor) {
- new CustomDateRangeWindow(title, windowTitle, buttonBarDateTimeRangeEditor, new Date(), new Date());
- }
-
- public CustomDateRangeWindow(String title, String windowTitle,
final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor, Date startTime, Date endTime) {
super();
setTitle(windowTitle + ": " + title);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/RedrawGraphs.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/RedrawGraphs.java
new file mode 100644
index 0000000..e590281
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/RedrawGraphs.java
@@ -0,0 +1,29 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+/**
+ * Define the capability to Redraw a Graph.
+ * @author Mike Thompson
+ */
+public interface RedrawGraphs {
+
+ void redrawGraphs();
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupD3GraphListView.java
index acdc211..dfb53b3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupD3GraphListView.java
@@ -25,8 +25,6 @@ import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
-import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import org.rhq.core.domain.criteria.ResourceGroupCriteria;
@@ -40,15 +38,18 @@ import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.JsonMetricProducer;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.RedrawGraphs;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.async.Command;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedHLayout;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
/**
* This composite graph view has different graph types and data structures for
@@ -57,10 +58,7 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
*
* @author Mike Thompson
*/
-public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout implements JsonMetricProducer
-{
-
- private HTMLFlow resourceTitle;
+public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout implements JsonMetricProducer, RedrawGraphs {
private int groupId;
private int definitionId;
@@ -68,7 +66,8 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
private MeasurementDefinition definition;
- private UserPreferencesMeasurementRangeEditor measurementRangeEditor;
+ private MeasurementUserPreferences measurementUserPreferences;
+ private ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor;
/**
* measurementForEachResource is a list of a list of single Measurement data for multiple resources.
@@ -84,7 +83,8 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
this.isAutogroup = isAutogroup;
setDefinitionId(defId);
measurementForEachResource = new ArrayList<MultiLineGraphData>();
- measurementRangeEditor = new UserPreferencesMeasurementRangeEditor();
+ measurementUserPreferences = new MeasurementUserPreferences(UserSessionManager.getUserPreferences());
+ buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPreferences, this);
setHeight100();
setWidth100();
setPadding(10);
@@ -117,8 +117,8 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
Log.debug("group name: " + parentGroup.getName());
Log.debug("# of child resources: " + parentGroup.getExplicitResources().size());
// setting up a deferred Command to execute after all resource queries have completed (successfully or unsuccessfully)
- final CountDownLatch countDownLatch = CountDownLatch.create(parentGroup.getExplicitResources().size(),
- new Command() {
+ final CountDownLatch countDownLatch = CountDownLatch.create(parentGroup.getExplicitResources()
+ .size(), new Command() {
@Override
/**
* Do this only after ALL of the metric queries for each resource
@@ -149,43 +149,30 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
}
}
- List<Long> times = measurementRangeEditor.getBeginEndTimes();
- Long startTime = times.get(0);
- Long endTime = times.get(1);
- measurementRangeEditor.getSetButton().addClickHandler(new ClickHandler()
- {
- @Override
- public void onClick(ClickEvent event)
- {
- drawGraph();
- populateData();
- markForRedraw();
- }
- });
-
for (final Resource childResource : childResources) {
Log.debug("Adding child composite: " + childResource.getName()
+ childResource.getId());
GWTServiceLookup.getMeasurementDataService().findDataForResource(
- childResource.getId(), new int[]{getDefinitionId()}, startTime, endTime, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>()
- {
- @Override
- public void onFailure(Throwable caught)
- {
- countDownLatch.countDown();
- CoreGUI.getErrorHandler().handleError(
- MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- @Override
- public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> result)
- {
- addMeasurementForEachResource(childResource.getName(), childResource.getId(), result.get(0));
- countDownLatch.countDown();
- }
- });
+ childResource.getId(), new int[] { getDefinitionId() },
+ buttonBarDateTimeRangeEditor.getStartTime(),
+ buttonBarDateTimeRangeEditor.getEndTime(), 60,
+ new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(
+ MSG.view_resource_monitor_graphs_loadFailed(), caught);
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void onSuccess(
+ List<List<MeasurementDataNumericHighLowComposite>> result) {
+ addMeasurementForEachResource(childResource.getName(),
+ childResource.getId(), result.get(0));
+ countDownLatch.countDown();
+ }
+ });
}
}
});
@@ -199,31 +186,27 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
/**
* Immutable data for each graph line.
*/
- private final class MultiLineGraphData
- {
+ private final class MultiLineGraphData {
private String resourceName;
private int resourceId;
private List<MeasurementDataNumericHighLowComposite> measurementData;
- private MultiLineGraphData(String resourceName, int resourceId, List<MeasurementDataNumericHighLowComposite> measurmentData)
- {
+ private MultiLineGraphData(String resourceName, int resourceId,
+ List<MeasurementDataNumericHighLowComposite> measurmentData) {
this.resourceName = resourceName;
this.resourceId = resourceId;
this.measurementData = measurmentData;
}
- public String getResourceName()
- {
+ public String getResourceName() {
return resourceName;
}
- public int getResourceId()
- {
+ public int getResourceId() {
return resourceId;
}
- public List<MeasurementDataNumericHighLowComposite> getMeasurementData()
- {
+ public List<MeasurementDataNumericHighLowComposite> getMeasurementData() {
return measurementData;
}
}
@@ -232,9 +215,10 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
* Adding is done asynchronously, so we must synchronize the add.
* @param resourceMeasurementList
*/
- public synchronized void addMeasurementForEachResource(String resourceName, int resourceId, List<MeasurementDataNumericHighLowComposite> resourceMeasurementList) {
+ public synchronized void addMeasurementForEachResource(String resourceName, int resourceId,
+ List<MeasurementDataNumericHighLowComposite> resourceMeasurementList) {
- measurementForEachResource.add(new MultiLineGraphData(resourceName,resourceId,resourceMeasurementList));
+ measurementForEachResource.add(new MultiLineGraphData(resourceName, resourceId, resourceMeasurementList));
}
@Override
@@ -271,22 +255,32 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
this.definition = definition;
}
- private void removeMembers(){
+ private void removeMembers() {
- removeMember(measurementRangeEditor);
- if(null != titleHLayout) removeMember(titleHLayout);
- if(null != title) removeMember(title);
- if (null != graph) removeMember(graph);
+ removeMember(buttonBarDateTimeRangeEditor);
+ if (null != titleHLayout)
+ removeMember(titleHLayout);
+ if (null != title)
+ removeMember(title);
+ if (null != graph)
+ removeMember(graph);
+ }
+
+ @Override
+ public void redrawGraphs() {
+ drawGraph();
+ populateData();
+ markForRedraw();
}
private void drawGraph() {
Log.debug("drawGraph in CompositeGroupD3GraphListView for: " + definition + "," + definitionId);
- if(null != titleHLayout){
+ if (null != titleHLayout) {
removeMembers();
}
- addMember(measurementRangeEditor);
+ addMember(buttonBarDateTimeRangeEditor);
titleHLayout = new EnhancedHLayout();
@@ -294,11 +288,6 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
titleHLayout.setAutoHeight();
titleHLayout.setWidth100();
- if (null != resourceTitle) {
- resourceTitle.setWidth("*");
- titleHLayout.addMember(resourceTitle);
- }
-
addMember(titleHLayout);
title = new HTMLFlow("<b>" + definition.getDisplayName() + "</b> " + definition.getDescription());
@@ -369,10 +358,11 @@ public abstract class CompositeGroupD3GraphListView extends EnhancedVLayout impl
*/
public boolean shouldDisplayDayOfWeekInXAxisLabel() {
// because of asyncrony this is possible so default it
- if(null == measurementForEachResource || measurementForEachResource.isEmpty()){
- return true;
+ if (null == measurementForEachResource || measurementForEachResource.isEmpty()) {
+ return true;
}
- List<MeasurementDataNumericHighLowComposite> firstResourceMeasurementList = measurementForEachResource.get(0).getMeasurementData();
+ List<MeasurementDataNumericHighLowComposite> firstResourceMeasurementList = measurementForEachResource.get(0)
+ .getMeasurementData();
Long startTime = firstResourceMeasurementList.get(0).getTimestamp();
Long endTime = firstResourceMeasurementList.get(firstResourceMeasurementList.size() - 1).getTimestamp();
long timeThreshold = 24 * 60 * 60 * 1000; // 1 days
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 2437ab0..5bfb2af 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -113,7 +113,6 @@ public class D3GraphListView extends AbstractD3GraphListView {
}
private void commonConstructorSettings() {
- buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
setOverflow(Overflow.HIDDEN);
}
@@ -133,11 +132,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
if (showAvailabilityGraph) {
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resource.getId()));
- // first step in 2 step to create d3 chart
- // create a placeholder for avail graph
- availabilityGraph.createGraphMarker();
addMember(availabilityGraph);
-
}
vLayout = new VLayout();
commit 16e753bb77ae87008a5769e680ba71e3b4440e6e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 18 14:59:36 2013 -0700
Remove unused class.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java
deleted file mode 100644
index 6dd4db7..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.types.ExpansionMode;
-import com.smartgwt.client.types.SelectionStyle;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.CloseClickEvent;
-import com.smartgwt.client.widgets.events.CloseClickHandler;
-import com.smartgwt.client.widgets.grid.ListGrid;
-import com.smartgwt.client.widgets.grid.ListGridField;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-import com.smartgwt.client.widgets.grid.events.RecordExpandEvent;
-import com.smartgwt.client.widgets.grid.events.RecordExpandHandler;
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import org.rhq.core.domain.criteria.ResourceCriteria;
-import org.rhq.core.domain.measurement.MeasurementData;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.resource.composite.ResourceComposite;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.components.table.Table;
-import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3Graph;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * Views a resource's metrics in a tabular view with sparkline graph
- * and optional detailed graph .
- *
- * @author John Mazzitelli
- * @author Mike Thompson
- */
-public class MetricsTableView extends Table<MetricsTableDataSource> {
-
- private final int resourceId;
-
- public MetricsTableView(int resourceId) {
- super();
- this.resourceId = resourceId;
- setDataSource(new MetricsTableDataSource(resourceId));
- }
-
- /**
- * Creates this Table's list grid (called by onInit()). Subclasses can override this if they require a custom subclass
- * of ListGrid.
- *
- * @return this Table's list grid (must be an instance of ListGrid)
- */
- @Override
- protected ListGrid createListGrid() {
- return new MetricsTableListGrid();
- }
-
- protected void configureTable() {
- ArrayList<ListGridField> fields = getDataSource().getListGridFields();
- setListGridFields(fields.toArray(new ListGridField[0]));
- this.getListGrid().setCanExpandRecords(true);
- this.getListGrid().addRecordExpandHandler(new RecordExpandHandler() {
- @Override
- public void onRecordExpand(RecordExpandEvent recordExpandEvent) {
- Log.debug("Record Expanded: ");
-
- }
- });
-
- //addExtraWidget(new UserPreferencesMeasurementRangeEditor(), true);
- addTableAction(MSG.view_measureTable_getLive(), new TableAction() {
- @Override
- public boolean isEnabled(ListGridRecord[] selection) {
- return selection != null && selection.length > 0;
- }
-
- @Override
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- if (selection == null || selection.length == 0) {
- return;
- }
- // keyed on metric name - string[0] is the metric label, [1] is the units
- final HashMap<String, String[]> scheduleNamesAndUnits = new HashMap<String, String[]>();
- int[] definitionIds = new int[selection.length];
- int i = 0;
- for (ListGridRecord record : selection) {
- Integer defId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_METRIC_DEF_ID);
- definitionIds[i++] = defId;
-
- String name = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_NAME);
- String label = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_LABEL);
- String units = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_UNITS);
- if (units == null || units.length() < 1) {
- units = MeasurementUnits.NONE.name();
- }
-
- scheduleNamesAndUnits.put(name, new String[] { label, units });
- }
-
- // actually go out and ask the agents for the data
- GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId, definitionIds,
- new AsyncCallback<Set<MeasurementData>>() {
- @Override
- public void onSuccess(Set<MeasurementData> result) {
- if (result == null) {
- result = new HashSet<MeasurementData>(0);
- }
- ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
- for (MeasurementData data : result) {
- String[] nameAndUnits = scheduleNamesAndUnits.get(data.getName());
- if (nameAndUnits != null) {
- double doubleValue;
- if (data.getValue() instanceof Number) {
- doubleValue = ((Number) data.getValue()).doubleValue();
- } else {
- doubleValue = Double.parseDouble(data.getValue().toString());
- }
- String value = MeasurementConverterClient.formatToSignificantPrecision(
- new double[] { doubleValue }, MeasurementUnits.valueOf(nameAndUnits[1]), true)[0];
-
- ListGridRecord record = new ListGridRecord();
- record.setAttribute("name", nameAndUnits[0]);
- record.setAttribute("value", value);
- records.add(record);
- }
- }
- Collections.sort(records, new Comparator<ListGridRecord>() {
- public int compare(ListGridRecord o1, ListGridRecord o2) {
- return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
- }
- });
- showLiveData(records);
- }
-
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
- }
- });
- }
- });
-
- addTableAction(MSG.view_measureTable_addToDashboard(), new TableAction() {
-
- @Override
- public boolean isEnabled(ListGridRecord[] selection) {
- return selection != null && selection.length > 0;
- }
-
- @Override
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
-
- }
- });
-
- }
-
- private void showLiveData(ArrayList<ListGridRecord> records) {
- final Window liveDataWindow = new Window();
- liveDataWindow.setTitle(MSG.view_measureTable_live_title());
- liveDataWindow.setShowModalMask(true);
- liveDataWindow.setShowMinimizeButton(false);
- liveDataWindow.setShowMaximizeButton(true);
- liveDataWindow.setShowCloseButton(true);
- liveDataWindow.setShowResizer(true);
- liveDataWindow.setCanDragResize(true);
- liveDataWindow.setDismissOnEscape(true);
- liveDataWindow.setIsModal(true);
- liveDataWindow.setWidth(700);
- liveDataWindow.setHeight(425);
- liveDataWindow.setAutoCenter(true);
- liveDataWindow.centerInPage();
- liveDataWindow.addCloseClickHandler(new CloseClickHandler() {
- @Override
- public void onCloseClick(CloseClickEvent event) {
- liveDataWindow.destroy();
- refreshTableInfo();
- }
- });
-
- ListGrid liveDataGrid = new ListGrid();
- liveDataGrid.setShowAllRecords(true);
- liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
- liveDataGrid.setSelectionType(SelectionStyle.NONE);
- ListGridField name = new ListGridField("name", MSG.common_title_metric());
- ListGridField value = new ListGridField("value", MSG.common_title_value());
- liveDataGrid.setFields(name, value);
-
- liveDataWindow.addItem(liveDataGrid);
- liveDataWindow.show();
- }
-
- private class MetricsTableListGrid extends ListGrid {
- public MetricsTableListGrid() {
- super();
-
- setCanExpandRecords(true);
- setCanExpandMultipleRecords(true);
- setExpansionMode(ExpansionMode.RELATED);
- }
-
- @Override
- protected Canvas getExpansionComponent(final ListGridRecord record) {
- final Integer definitionId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_METRIC_DEF_ID);
- final Integer resourceId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_RESOURCE_ID);
- VLayout vLayout = new VLayout();
- vLayout.setPadding(5);
-
- final String chartId = "rChart" + resourceId + "-" + definitionId;
- HTMLFlow htmlFlow = new HTMLFlow(MetricD3Graph.createGraphMarkerTemplate(chartId, 200));
- vLayout.addMember(htmlFlow);
-
- //locate resource reference
- ResourceCriteria criteria = new ResourceCriteria();
- criteria.addFilterId(resourceId);
-
- //locate the resource
- GWTServiceLookup.getResourceService().findResourceCompositesByCriteria(criteria,
- new AsyncCallback<PageList<ResourceComposite>>() {
- @Override
- public void onFailure(Throwable caught) {
- Log.debug("Error retrieving resource resource composite for resource [" + resourceId + "]:"
- + caught.getMessage());
- }
-
- @Override
- public void onSuccess(PageList<ResourceComposite> results) {
- if (!results.isEmpty()) {
- final Resource resource = results.get(0).getResource();
- //D3GraphListView graphListView = D3GraphListView.createSingleGraph(resource, definitionId, false);
-
- // Load the fully fetched ResourceType.
- ResourceType resourceType = resource.getResourceType();
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(
- resourceType.getId(),
- EnumSet.of(ResourceTypeRepository.MetadataType.content,
- ResourceTypeRepository.MetadataType.operations,
- ResourceTypeRepository.MetadataType.measurements,
- ResourceTypeRepository.MetadataType.events,
- ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
- new ResourceTypeRepository.TypeLoadedCallback() {
- public void onTypesLoaded(ResourceType type) {
- resource.setResourceType(type);
- //metric definitions
- Set<MeasurementDefinition> definitions = type.getMetricDefinitions();
- final MeasurementDefinition measurementDefinition;
-
- //build id mapping for measurementDefinition instances Ex. Free Memory -> MeasurementDefinition[100071]
- final HashMap<String, MeasurementDefinition> measurementDefMap = new HashMap<String, MeasurementDefinition>();
- for (MeasurementDefinition definition : definitions) {
- measurementDefMap.put(definition.getDisplayName(), definition);
- if (definition.getId() == definitionId) {
- measurementDefinition = definition;
- break;
- }
- }
-
- int[] definitionArrayIds = new int[1];
- definitionArrayIds[0] = definitionId;
- GWTServiceLookup.getMeasurementDataService().findDataForResource(resourceId,
- definitionArrayIds, 1370156400, 1370446147, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- @Override
- public void onFailure(Throwable caught) {
- Log.debug("Error retrieving recent metrics charting data for resource ["
- + resourceId + "]:" + caught.getMessage());
- //setRefreshing(false);
- }
-
- @Override
- public void onSuccess(
- List<List<MeasurementDataNumericHighLowComposite>> results) {
- if (!results.isEmpty()) {
-
- //load the data results for the given metric definition
- List<MeasurementDataNumericHighLowComposite> data = results
- .get(0);
-
- //locate last and minimum values.
- double lastValue = -1;
- double minValue = Double.MAX_VALUE;//
- for (MeasurementDataNumericHighLowComposite d : data) {
- if ((!Double.isNaN(d.getValue()))
- && (!String.valueOf(d.getValue()).contains("NaN"))) {
- if (d.getValue() < minValue) {
- minValue = d.getValue();
- }
- lastValue = d.getValue();
- }
- }
-
- //@todo: OOB data
-// MetricGraphData metricGraphData = MetricGraphData
-// .createForResource(resourceId, resource.getName(),
-// measurementDefinition, data, null);
-//
-// StackedBarMetricGraphImpl graph = GWT
-// .create(StackedBarMetricGraphImpl.class);
-// graph.setMetricGraphData(metricGraphData);
-// MetricD3Graph graphView = new MetricD3Graph(graph);
-// graphView.drawJsniChart();
-
- } else {
-
- }
- //setRefreshing(false);
- }
- });
-
- }
- });
-
- }
- }
- });
-
- return vLayout;
-
- }
- }
-
-}
commit 18073c84b0d74a0541f3900fc1d28c9be67b43cd
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 18 10:29:54 2013 -0700
Fix group availability graph vertical spacing issue.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index ac8caf0..59737ac 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -81,6 +81,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
graphsVLayout = new VLayout();
graphsVLayout.setOverflow(Overflow.AUTO);
graphsVLayout.setWidth100();
+ graphsVLayout.setHeight100();
if (resourceGroup != null) {
buildGraphs();
commit 77df0d260ed11b8dac41ad1e57ea646ff445731c
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 18 09:43:04 2013 -0700
Undo changes for new screen that are not ready to be committed yet. Revert to working version.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index d47959b..a326145 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -44,7 +44,6 @@ import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.core.domain.resource.composite.ResourceComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.components.FullHTMLPane;
import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.components.table.Table;
import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
@@ -57,12 +56,9 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/**
* Views a resource's measurements in a tabular view.
- * @todo: this is TEMPORARY until the metric view is complete to replace it
*
- * @deprecated
* @author John Mazzitelli
*/
-@Deprecated
public class MeasurementTableView extends Table<MetricsTableDataSource> {
private final int resourceId;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java
index 2fa11da..318166d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java
@@ -44,7 +44,6 @@ public class MetricsTableDataSource extends RPCDataSource<MetricDisplaySummary,
public static final String FIELD_METRIC_SCHED_ID = "schedId";
public static final String FIELD_METRIC_UNITS = "units";
public static final String FIELD_METRIC_NAME = "name";
- public static final String FIELD_RESOURCE_ID = "resourceId";
private int resourceId;
@@ -65,23 +64,6 @@ public class MetricsTableDataSource extends RPCDataSource<MetricDisplaySummary,
nameField.setWidth("30%");
fields.add(nameField);
- nameField.setCellFormatter(new CellFormatter() {
- @Override
- public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
- if (value == null) {
- return "";
- }
- String commaDelimitedList = "5, 10, 20, 25";
- //String formattedValue = StringUtility.escapeHtml(value.toString());
- String contents= "<span id='sparkline_" + resourceId + "-"+ record.getAttributeAsInt("FIELD_METRIC_DEF_ID")
- + "' class='dynamicsparkline' width='0' " + "values='"
- + commaDelimitedList + "'>...</span>";
- return contents;
-
- }
- });
- BrowserUtility.graphSparkLines();
-
ListGridField alertsField = new ListGridField(FIELD_ALERT_COUNT, MSG.common_title_alerts());
alertsField.setWidth("10%");
fields.add(alertsField);
@@ -129,7 +111,6 @@ public class MetricsTableDataSource extends RPCDataSource<MetricDisplaySummary,
record.setAttribute(FIELD_METRIC_SCHED_ID, from.getScheduleId());
record.setAttribute(FIELD_METRIC_UNITS, from.getUnits());
record.setAttribute(FIELD_METRIC_NAME, from.getMetricName());
- record.setAttribute(FIELD_RESOURCE_ID, resourceId);
return record;
}
commit b08b0f4b1de15debc913d03b8be5133ddd1c447b
Merge: c3bcd68 31587f2
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 17 19:01:03 2013 -0700
Merge branch 'master' into mtho11/dual-slider-chart-control
commit c3bcd68c36c92150da334ea8216eaace5dfed876
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 17 15:18:19 2013 -0700
Fix time portion of Time range editor.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 229d652..ac2462c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -33,6 +33,7 @@ import com.smartgwt.client.widgets.events.CloseClickEvent;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.DateItem;
+import com.smartgwt.client.widgets.form.fields.DateTimeItem;
import com.smartgwt.client.widgets.form.fields.RowSpacerItem;
import com.smartgwt.client.widgets.form.fields.TimeItem;
import com.smartgwt.client.widgets.layout.HLayout;
@@ -303,8 +304,12 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
@Override
public void onClick(ClickEvent clickEvent) {
Log.debug("Saving Custom Date Range Window.");
- buttonBarDateTimeRangeEditor.saveDateRange(startDateItem.getValueAsDate().getTime(), endDateItem
- .getValueAsDate().getTime());
+ Date startTimeDate = (Date) startTimeItem.getValue();
+ Date endTimeDate = (Date) endTimeItem.getValue();
+
+ Date newStartDate = new Date(startDateItem.getValueAsDate().getYear(), startDateItem.getValueAsDate().getMonth(),startDateItem.getValueAsDate().getDate(), startTimeDate.getHours(), startTimeDate.getMinutes());
+ Date newEndDate = new Date(endDateItem.getValueAsDate().getYear(), endDateItem.getValueAsDate().getMonth(),endDateItem.getValueAsDate().getDate(), endTimeDate.getHours(), endTimeDate.getMinutes());
+ buttonBarDateTimeRangeEditor.saveDateRange(newStartDate.getTime(),newEndDate.getTime());
redrawGraphs();
updateDateTimeRangeDisplay(startDateItem.getValueAsDate(), endDateItem.getValueAsDate());
CustomDateRangeWindow.this.destroy();
commit 8d9a2e23d7253d58d0b849a49acb8f8608a9dbec
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 17 12:25:02 2013 -0700
i18n ButtonBar Date/Time Range editor.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 3f56aa5..229d652 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -63,14 +63,13 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
private AbstractD3GraphListView d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
private Label dateRangeLabel;
- //@todo: pull dateformat messages.properties
- private static final DateTimeFormat fmt = DateTimeFormat.getFormat("MM/dd/yyyy h:mm a");
+ private static final DateTimeFormat fmt = DateTimeFormat.getFormat(MSG.common_buttonbar_datetime_format());
private DateTimeButtonBarClickHandler dateTimeButtonBarClickHandler;
private AbstractMeasurementRangeEditor.MetricRangePreferences prefs;
final private ButtonBarDateTimeRangeEditor self;
public ButtonBarDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
- AbstractD3GraphListView d3GraphListView) {
+ AbstractD3GraphListView d3GraphListView) {
this.self = this;
this.measurementUserPreferences = measurementUserPrefs;
this.d3GraphListView = d3GraphListView;
@@ -78,12 +77,12 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
dateTimeButtonBarClickHandler = new DateTimeButtonBarClickHandler();
prefs = measurementUserPreferences.getMetricRangePreferences();
Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: " + new Date(prefs.begin) + " end Date: "
- + new Date(prefs.end));
+ + new Date(prefs.end));
createButtons();
}
- public void createButtons() {
+ private void createButtons() {
ToolStrip toolStrip = new ToolStrip();
toolStrip.setWidth100();
@@ -91,7 +90,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
toolStrip.addSpacer(10);
- for(DateTimeButton dateTimeButton : DateTimeButton.values()){
+ for (DateTimeButton dateTimeButton : DateTimeButton.values()) {
IButton oneHourButton = new IButton(dateTimeButton.label);
oneHourButton.setWidth(BUTTON_WIDTH);
oneHourButton.setActionType(SelectionType.RADIO);
@@ -101,15 +100,16 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
toolStrip.addMember(oneHourButton);
}
-
- IButton customButton = new IButton("Custom...");
+ IButton customButton = new IButton(MSG.common_buttonbar_custom());
customButton.setWidth(60);
customButton.setActionType(SelectionType.RADIO);
customButton.setRadioGroup(TIMERANGE);
customButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent clickEvent) {
- CustomDateRangeWindow customDateRangeWindow = new CustomDateRangeWindow("Date Range", "Custom", self, new Date(prefs.begin), new Date(prefs.end));
+ CustomDateRangeWindow customDateRangeWindow = new CustomDateRangeWindow(MSG
+ .common_buttonbar_custom_window_title(), MSG.common_buttonbar_custom_window_subtitle(), self,
+ new Date(prefs.begin), new Date(prefs.end));
customDateRangeWindow.show();
}
});
@@ -128,7 +128,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
addMember(toolStrip);
}
-
public void redrawGraphs() {
d3GraphListView.redrawGraphs();
}
@@ -145,7 +144,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
super.parentResized();
removeMembers(getMembers());
createButtons();
- //drawJsniChart();
}
public Label getDateRangeLabel() {
@@ -162,30 +160,20 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
public Date calculateStartDate(Date endDate, String dateTimeSelection) {
long dateTimeOffset = 0;
- for(DateTimeButton dateTimeButton : DateTimeButton.values()){
- if(dateTimeButton.label.equals(dateTimeSelection)){
+ for (DateTimeButton dateTimeButton : DateTimeButton.values()) {
+ if (dateTimeButton.label.equals(dateTimeSelection)) {
dateTimeOffset = dateTimeButton.timeSpanInSeconds * 1000;
break;
}
}
- Log.debug("DateTimeSelection: "+ dateTimeSelection + " = "+ dateTimeOffset);
+ Log.debug("DateTimeSelection: " + dateTimeSelection + " = " + dateTimeOffset);
return new Date(endDate.getTime() - dateTimeOffset);
}
- /**
- * Function meant to be called by the javascript inside the d3 charting javascript.
- * @param startDate double (as javascript doenst have long) representing unix date
- * @param endDate double
- */
- public void updateDateTimeRangeDisplayFromJavascript(double startDate, double endDate){
- updateDateTimeRangeDisplay(new Date((long)startDate), new Date((long)endDate));
- }
-
public void updateDateTimeRangeDisplay(Date startDate, Date endDate) {
String rangeString = fmt.format(startDate) + " - " + fmt.format(endDate);
dateRangeLabel.setContents(rangeString);
-
}
/**
@@ -215,7 +203,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
IButton button = (IButton) clickEvent.getSource();
String selectedDateTimeRange = button.getTitle();
Date calculatedStartDateTime = calculateStartDate(new Date(getEndTime()), selectedDateTimeRange);
- saveDateRange(calculatedStartDateTime.getTime(),new Date().getTime());
+ saveDateRange(calculatedStartDateTime.getTime(), new Date().getTime());
redrawGraphs();
updateDateTimeRangeDisplay(calculatedStartDateTime, new Date());
}
@@ -258,11 +246,13 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
public class CustomDateRangeWindow extends Window {
- public CustomDateRangeWindow(String title, String windowTitle, final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor) {
+ public CustomDateRangeWindow(String title, String windowTitle,
+ final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor) {
new CustomDateRangeWindow(title, windowTitle, buttonBarDateTimeRangeEditor, new Date(), new Date());
}
- public CustomDateRangeWindow(String title, String windowTitle, final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor, Date startTime, Date endTime) {
+ public CustomDateRangeWindow(String title, String windowTitle,
+ final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor, Date startTime, Date endTime) {
super();
setTitle(windowTitle + ": " + title);
setShowMinimizeButton(false);
@@ -284,37 +274,37 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
form.setWidth100();
form.setPadding(5);
form.setLayoutAlign(VerticalAlignment.BOTTOM);
- final DateItem startDateItem = new DateItem("startDate", "Start Date");
+ final DateItem startDateItem = new DateItem("startDate", MSG.common_buttonbar_start_date());
startDateItem.setValue(startTime);
- final TimeItem startTimeItem = new TimeItem("startTime", "Start Time");
+ final TimeItem startTimeItem = new TimeItem("startTime", MSG.common_buttonbar_start_time());
startTimeItem.setValue(startTime);
- final DateItem endDateItem = new DateItem("endDate", "End Date");
+ final DateItem endDateItem = new DateItem("endDate", MSG.common_buttonbar_end_date());
endDateItem.setValue(endTime);
- final TimeItem endTimeItem = new TimeItem("endTime", "End Time");
+ final TimeItem endTimeItem = new TimeItem("endTime", MSG.common_buttonbar_end_time());
endTimeItem.setValue(endTime);
- form.setFields(startDateItem, startTimeItem, new RowSpacerItem(), endDateItem, endTimeItem, new RowSpacerItem() );
+ form.setFields(startDateItem, startTimeItem, new RowSpacerItem(), endDateItem, endTimeItem,
+ new RowSpacerItem());
this.addItem(form);
HLayout buttonHLayout = new HLayout();
buttonHLayout.setMargin(15);
buttonHLayout.setMembersMargin(20);
- IButton cancelButton = new IButton("Cancel");
+ IButton cancelButton = new IButton(MSG.common_buttonbar_custom_cancel());
cancelButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent clickEvent) {
- Log.debug("Cancel Window.");
CustomDateRangeWindow.this.destroy();
}
});
buttonHLayout.addMember(cancelButton);
- IButton saveButton = new IButton("Save");
+ IButton saveButton = new IButton(MSG.common_buttonbar_custom_save());
saveButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent clickEvent) {
Log.debug("Saving Custom Date Range Window.");
- buttonBarDateTimeRangeEditor.saveDateRange(startDateItem.getValueAsDate().getTime(), endDateItem.getValueAsDate().getTime());
- //@todo: give feedback message that we saved changes
+ buttonBarDateTimeRangeEditor.saveDateRange(startDateItem.getValueAsDate().getTime(), endDateItem
+ .getValueAsDate().getTime());
redrawGraphs();
updateDateTimeRangeDisplay(startDateItem.getValueAsDate(), endDateItem.getValueAsDate());
CustomDateRangeWindow.this.destroy();
@@ -329,8 +319,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
public void onCloseClick(CloseClickEvent event) {
try {
CustomDateRangeWindow.this.destroy();
- }
- catch (Throwable e) {
+ } catch (Throwable e) {
Log.warn("Cannot destroy custom date range window.", e);
}
}
@@ -339,7 +328,4 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
}
}
-
-
-
}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index f545024..21e73e2 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -40,6 +40,16 @@ common_button_ack_all = Acknowledge All
common_button_add = Add
common_button_advanced = Advanced...
common_button_apply = Apply
+common_buttonbar_custom_window_title= Date Range
+common_buttonbar_custom_window_subtitle= Custom
+common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+common_buttonbar_end_date= End Date
+common_buttonbar_end_time= End Time
+common_buttonbar_start_date= End Date
+common_buttonbar_start_time= End Time
+common_buttonbar_custom = Custom...
+common_buttonbar_custom_cancel = Cancel
+common_buttonbar_custom_save = Save
common_button_cancel = Cancel
common_button_close = Close
common_button_compare = Compare
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 036257e..b9fbbdd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -63,6 +63,16 @@ common_button_ack_all = Potvrdit všechny
common_button_add = PÅidat
common_button_advanced = RozÅ¡ÃÅené...
common_button_apply = PouÅŸÃt
+##common_buttonbar_custom_window_title= Date Range
+##common_buttonbar_custom_window_subtitle= Custom
+##common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+##common_buttonbar_end_date= End Date
+##common_buttonbar_end_time= End Time
+##common_buttonbar_start_date= End Date
+##common_buttonbar_start_time= End Time
+##common_buttonbar_custom = Custom...
+##common_buttonbar_custom_cancel = Cancel
+##common_buttonbar_custom_save = Save
common_button_cancel = Storno
common_button_close = ZavÅÃt
common_button_compare = Porovnat
@@ -795,7 +805,7 @@ view_admin_systemSettings_EventPurge_name = Smazat události staršà neş
view_admin_systemSettings_JAASProvider_desc = MÄl by bÃœt LDAP pouÅŸit k urÄenà uÅŸivatelovi identity?
view_admin_systemSettings_JAASProvider_name = Povolit LDAP
view_admin_systemSettings_LDAPBaseDN_desc = Báze adresáÅového stromu urÄeného ke hledánà uÅŸivatelů a jejich hesel pÅi autentizaci, napÅ. ou=People,dc=redhat,dc=com
-view_admin_systemSettings_LDAPBaseDN_name = Báze pro hledánÃ
+view_admin_systemSettings_LDAPBaseDN_name = Báze pro hledánᅵ ᅵ
view_admin_systemSettings_LDAPBindDN_desc = UÅŸivatelské jméno, pod kterÃœm se pÅipojovat k LDAP serveru. Typicky se jedná o plnÄ urÄené jméno (DN) správce napÅ. cn=Manager,dc=redhat,dc=com
view_admin_systemSettings_LDAPBindDN_name = Uşivatelské jméno
view_admin_systemSettings_LDAPBindPW_desc = PÅihlaÅ¡ovacà údaje uÅŸivatele, kterÃœ poté dotazuje LDAP server.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 25e9267..04504bd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -38,6 +38,16 @@ common_button_ack_all = Alle bestÀtigen
common_button_add = HinzufÃŒgen
common_button_advanced = Erweitert...
common_button_apply = Anwenden
+##common_buttonbar_custom_window_title= Date Range
+##common_buttonbar_custom_window_subtitle= Custom
+##common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+##common_buttonbar_end_date= End Date
+##common_buttonbar_end_time= End Time
+##common_buttonbar_start_date= End Date
+##common_buttonbar_start_time= End Time
+##common_buttonbar_custom = Custom...
+##common_buttonbar_custom_cancel = Cancel
+##common_buttonbar_custom_save = Save
common_button_cancel = Abbrechen
common_button_close = SchlieÃen
common_button_compare = Vergleichen
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 68991d7..8eeb7c7 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -43,6 +43,16 @@ common_button_ack_all = ãã¹ãŠã確èª
common_button_add = è¿œå
common_button_advanced = é«åºŠãªèšå®...
common_button_apply = é©çš
+##common_buttonbar_custom_window_title= Date Range
+##common_buttonbar_custom_window_subtitle= Custom
+##common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+##common_buttonbar_end_date= End Date
+##common_buttonbar_end_time= End Time
+##common_buttonbar_start_date= End Date
+##common_buttonbar_start_time= End Time
+##common_buttonbar_custom = Custom...
+##common_buttonbar_custom_cancel = Cancel
+##common_buttonbar_custom_save = Save
common_button_cancel = ãã£ã³ã»ã«
common_button_close = éãã
common_button_compare = æ¯èŒ
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 1a42834..dac6fe7 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -41,6 +41,16 @@ common_button_ack_all = ì 첎 íìž
common_button_add = ì¶ê°
common_button_advanced = ê³ êž ì€ì ...
common_button_apply = ì ì©
+##common_buttonbar_custom_window_title= Date Range
+##common_buttonbar_custom_window_subtitle= Custom
+##common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+##common_buttonbar_end_date= End Date
+##common_buttonbar_end_time= End Time
+##common_buttonbar_start_date= End Date
+##common_buttonbar_start_time= End Time
+##common_buttonbar_custom = Custom...
+##common_buttonbar_custom_cancel = Cancel
+##common_buttonbar_custom_save = Save
common_button_cancel = ì·šì
common_button_close = ë«êž°
common_button_compare = ë¹êµ
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 5337ba9..829f1aa 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -40,6 +40,16 @@ common_button_ack_all = Confirmar Todos
common_button_add = Adicionar
common_button_advanced = Avan\u00E7ado...
common_button_apply = Aplicar
+##common_buttonbar_custom_window_title= Date Range
+##common_buttonbar_custom_window_subtitle= Custom
+##common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+##common_buttonbar_end_date= End Date
+##common_buttonbar_end_time= End Time
+##common_buttonbar_start_date= End Date
+##common_buttonbar_start_time= End Time
+##common_buttonbar_custom = Custom...
+##common_buttonbar_custom_cancel = Cancel
+##common_buttonbar_custom_save = Save
common_button_cancel = Cancelar
common_button_close = Fechar
common_button_compare = Comparar
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 9bebe12..f338f89 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -40,6 +40,16 @@
#common_button_add = Add
#common_button_advanced = Advanced...
#common_button_apply = Apply
+##common_buttonbar_custom_window_title= Date Range
+##common_buttonbar_custom_window_subtitle= Custom
+##common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+##common_buttonbar_end_date= End Date
+##common_buttonbar_end_time= End Time
+##common_buttonbar_start_date= End Date
+##common_buttonbar_start_time= End Time
+##common_buttonbar_custom = Custom...
+##common_buttonbar_custom_cancel = Cancel
+##common_buttonbar_custom_save = Save
#common_button_cancel = Cancel
#common_button_close = Close
#common_button_compare = Compare
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 794fe3f..a39505e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -40,6 +40,16 @@ common_button_ack_all = \u786e\u8ba4\u6240\u6709
common_button_add = \u6dfb\u52a0
common_button_advanced = \u9ad8\u7ea7...
common_button_apply = \u63a5\u53d7
+##common_buttonbar_custom_window_title= Date Range
+##common_buttonbar_custom_window_subtitle= Custom
+##common_buttonbar_datetime_format= MM/dd/yyyy h:mm a
+##common_buttonbar_end_date= End Date
+##common_buttonbar_end_time= End Time
+##common_buttonbar_start_date= End Date
+##common_buttonbar_start_time= End Time
+##common_buttonbar_custom = Custom...
+##common_buttonbar_custom_cancel = Cancel
+##common_buttonbar_custom_save = Save
common_button_cancel = \u53d6\u6d88
common_button_close = \u5173\u95ed
common_button_compare = \u5bf9\u6bd4
commit eb1216c7a465f0e76dd4c5e757b9398186fa9560
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 17 11:15:46 2013 -0700
Add Custom... Date Range to new dual slider date bar.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index af1ce17..3f56aa5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -21,11 +21,21 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
import java.util.Date;
import com.google.gwt.i18n.client.DateTimeFormat;
+import com.smartgwt.client.types.FormErrorOrientation;
import com.smartgwt.client.types.SelectionType;
+import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.events.CloseClickEvent;
+import com.smartgwt.client.widgets.events.CloseClickHandler;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.DateItem;
+import com.smartgwt.client.widgets.form.fields.RowSpacerItem;
+import com.smartgwt.client.widgets.form.fields.TimeItem;
+import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.toolbar.ToolStrip;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -57,18 +67,20 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
private static final DateTimeFormat fmt = DateTimeFormat.getFormat("MM/dd/yyyy h:mm a");
private DateTimeButtonBarClickHandler dateTimeButtonBarClickHandler;
private AbstractMeasurementRangeEditor.MetricRangePreferences prefs;
+ final private ButtonBarDateTimeRangeEditor self;
public ButtonBarDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
AbstractD3GraphListView d3GraphListView) {
+ this.self = this;
this.measurementUserPreferences = measurementUserPrefs;
this.d3GraphListView = d3GraphListView;
dateTimeButtonBarClickHandler = new DateTimeButtonBarClickHandler();
prefs = measurementUserPreferences.getMetricRangePreferences();
- Log.debug("ButtonBarDateTimeRangeEditor initialized with start: " + prefs.begin + " end: " + prefs.end);
Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: " + new Date(prefs.begin) + " end Date: "
+ new Date(prefs.end));
createButtons();
+
}
public void createButtons() {
@@ -92,10 +104,15 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
IButton customButton = new IButton("Custom...");
customButton.setWidth(60);
- customButton.disable();
customButton.setActionType(SelectionType.RADIO);
customButton.setRadioGroup(TIMERANGE);
- customButton.addClickHandler(dateTimeButtonBarClickHandler);
+ customButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ CustomDateRangeWindow customDateRangeWindow = new CustomDateRangeWindow("Date Range", "Custom", self, new Date(prefs.begin), new Date(prefs.end));
+ customDateRangeWindow.show();
+ }
+ });
toolStrip.addMember(customButton);
toolStrip.addSpacer(30);
@@ -108,11 +125,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
toolStrip.addSpacer(20);
-// IButton resetZoomButton = new IButton("Reset Manual Zoom");
-// resetZoomButton.setWidth(150);
-// resetZoomButton.disable();
-// toolStrip.addMember(resetZoomButton);
-
addMember(toolStrip);
}
@@ -244,4 +256,90 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
}
+ public class CustomDateRangeWindow extends Window {
+
+ public CustomDateRangeWindow(String title, String windowTitle, final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor) {
+ new CustomDateRangeWindow(title, windowTitle, buttonBarDateTimeRangeEditor, new Date(), new Date());
+ }
+
+ public CustomDateRangeWindow(String title, String windowTitle, final ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor, Date startTime, Date endTime) {
+ super();
+ setTitle(windowTitle + ": " + title);
+ setShowMinimizeButton(false);
+ setShowMaximizeButton(false);
+ setShowCloseButton(true);
+ setIsModal(true);
+ setShowModalMask(true);
+ setWidth(450);
+ setHeight(300);
+ setShowResizer(true);
+ setCanDragResize(true);
+ centerInPage();
+ DynamicForm form = new DynamicForm();
+ form.setMargin(25);
+ form.setAutoFocus(true);
+ form.setShowErrorText(true);
+ form.setErrorOrientation(FormErrorOrientation.BOTTOM);
+ form.setHeight100();
+ form.setWidth100();
+ form.setPadding(5);
+ form.setLayoutAlign(VerticalAlignment.BOTTOM);
+ final DateItem startDateItem = new DateItem("startDate", "Start Date");
+ startDateItem.setValue(startTime);
+ final TimeItem startTimeItem = new TimeItem("startTime", "Start Time");
+ startTimeItem.setValue(startTime);
+ final DateItem endDateItem = new DateItem("endDate", "End Date");
+ endDateItem.setValue(endTime);
+ final TimeItem endTimeItem = new TimeItem("endTime", "End Time");
+ endTimeItem.setValue(endTime);
+ form.setFields(startDateItem, startTimeItem, new RowSpacerItem(), endDateItem, endTimeItem, new RowSpacerItem() );
+ this.addItem(form);
+
+ HLayout buttonHLayout = new HLayout();
+ buttonHLayout.setMargin(15);
+ buttonHLayout.setMembersMargin(20);
+ IButton cancelButton = new IButton("Cancel");
+ cancelButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Cancel Window.");
+ CustomDateRangeWindow.this.destroy();
+ }
+ });
+ buttonHLayout.addMember(cancelButton);
+
+ IButton saveButton = new IButton("Save");
+ saveButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Saving Custom Date Range Window.");
+ buttonBarDateTimeRangeEditor.saveDateRange(startDateItem.getValueAsDate().getTime(), endDateItem.getValueAsDate().getTime());
+ //@todo: give feedback message that we saved changes
+ redrawGraphs();
+ updateDateTimeRangeDisplay(startDateItem.getValueAsDate(), endDateItem.getValueAsDate());
+ CustomDateRangeWindow.this.destroy();
+ }
+ });
+
+ buttonHLayout.addMember(saveButton);
+ addItem(buttonHLayout);
+
+ addCloseClickHandler(new CloseClickHandler() {
+ @Override
+ public void onCloseClick(CloseClickEvent event) {
+ try {
+ CustomDateRangeWindow.this.destroy();
+ }
+ catch (Throwable e) {
+ Log.warn("Cannot destroy custom date range window.", e);
+ }
+ }
+ });
+
+ }
+ }
+
+
+
+
}
commit 4f3f1939347513329015668204565966048c9d0f
Merge: df55bb6 e04e062
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jun 13 07:49:18 2013 -0700
Merge from master 6/11/2013
diff --cc modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index c1ab440,3d9d8f8..25e9267
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@@ -1542,10 -1554,9 +1554,10 @@@ view_login_registerUser = Benutzer Anle
view_measureRange_last = Letzte
view_measureRange_simple = Einfach...
view_measureRange_start = Zeitraum - Start
+##view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_chartMetricValues = Graphen fÌr ausgewÀhlte Metriken anzeigen
view_measureTable_getLive = Aktuellen Wert holen
- ##view_measureTable_startBeforeEnd = Start time should be before the end time.
+ view_measureTable_startBeforeEnd = Der Startzeitpunkt muss vor dem Endzeitpunkt sein
view_measure_nan = --keine Daten verfÃŒgbar--
view_measurementOob_title = VerdÀchtige Metriken
view_menuBar_logout = Ausloggen
commit df55bb695085c96973ee8898eacb1740dcadfd1e
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Wed Jun 12 10:55:00 2013 -0700
Fix double refresh issue and make refresh more robust by delaying the redraw a bit so that the code can keep up with the screen redraw (like we have done elsehwere).
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 5af0c0e..af1ce17 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -102,7 +102,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
dateRangeLabel = new Label();
dateRangeLabel.setWidth(400);
- dateRangeLabel.setID("dateRange");
dateRangeLabel.addStyleName("graphDateTimeRangeLabel");
updateDateTimeRangeDisplay(new Date(prefs.begin), new Date(prefs.end));
toolStrip.addMember(dateRangeLabel);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index 00f9b40..ac8caf0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -25,6 +25,7 @@ import java.util.EnumSet;
import java.util.List;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.layout.VLayout;
@@ -75,9 +76,6 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
addMember(buttonBarDateTimeRangeEditor);
if (showAvailabilityGraph) {
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
- // first step in 2 step to create d3 chart
- // create a placeholder for avail graph
- availabilityGraph.createGraphMarker();
addMember(availabilityGraph);
}
graphsVLayout = new VLayout();
@@ -93,7 +91,6 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
public void redrawGraphs() {
this.onDraw();
- availabilityGraph.drawJsniChart();
}
/**
@@ -151,7 +148,12 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
// There is a weird timing case when availabilityGraph can be null
if (availabilityGraph != null) {
availabilityGraph.setGroupAvailabilityList(groupAvailabilityList);
- availabilityGraph.drawJsniChart();
+ new Timer(){
+ @Override
+ public void run() {
+ availabilityGraph.drawJsniChart();
+ }
+ }.schedule(150);
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index d913bdc..2437ab0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.TreeSet;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
@@ -129,7 +130,6 @@ public class D3GraphListView extends AbstractD3GraphListView {
destroyMembers();
addMember(buttonBarDateTimeRangeEditor);
- buttonBarDateTimeRangeEditor.createButtons();
if (showAvailabilityGraph) {
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resource.getId()));
@@ -153,9 +153,6 @@ public class D3GraphListView extends AbstractD3GraphListView {
public void redrawGraphs() {
this.onDraw();
- if(null != availabilityGraph){
- availabilityGraph.drawJsniChart();
- }
}
@Override
@@ -257,7 +254,12 @@ public class D3GraphListView extends AbstractD3GraphListView {
// we only need the first metricData since we are only taking the
// availability data set in there for the dropdowns already
availabilityGraph.setAvailabilityList(availabilityList);
- availabilityGraph.drawJsniChart();
+ new Timer(){
+ @Override
+ public void run() {
+ availabilityGraph.drawJsniChart();
+ }
+ }.schedule(150);
}
}
commit 555502c03348621f8ea72d729d93069667b7cd70
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 11 18:43:57 2013 -0700
Show chart values for single points: Value: 7.99.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 9df89d3..5b4b408 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -630,6 +630,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
hoverString =
'<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel" >' + chartContext.timeLabel + ': </span>' + timeFormatter(date) +
'<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span>' + dateFormatter(date) + '</div>' +
+ '<div class="chartHoverAlignRight"><span id="chartHoverAvgValue" >' + chartContext.avgChartTitle + ': </span><span style="width:50px;">' + avgValue + '</span></div>' +
'</div>';
} else {
// regular bar hover for duration
commit 53cf9726f73b32585f1d427712d51acd6f402125
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue Jun 11 13:27:09 2013 -0700
Make the date range text box larger and dynamically calculate the what the range (difference) is. For instance '2 hours'.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 0858f5d..5af0c0e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -101,7 +101,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
toolStrip.addSpacer(30);
dateRangeLabel = new Label();
- dateRangeLabel.setWidth(260);
+ dateRangeLabel.setWidth(400);
dateRangeLabel.setID("dateRange");
dateRangeLabel.addStyleName("graphDateTimeRangeLabel");
updateDateTimeRangeDisplay(new Date(prefs.begin), new Date(prefs.end));
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index e3350c0..9df89d3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -595,7 +595,8 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
function updateDateRangeDisplay(startDate, endDate ) {
//@todo: i18n the date format
var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- $wnd.jQuery('.graphDateTimeRangeLabel').text(formattedDateRange);
+ var timeRange = endDate.from(startDate,true);
+ $wnd.jQuery('.graphDateTimeRangeLabel').text(formattedDateRange+'('+timeRange+')');
}
commit 1b8047b3e6376d7e8744af852f1aa0c7155c3932
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue Jun 11 12:15:25 2013 -0700
Fix date range label incorrect bug introduced by removing fully opened brushes at graph start.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index c5b688a..e3350c0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -589,8 +589,8 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::redrawGraphs()();
}
- brushstart();
- brushmove();
+ //brushstart();
+ //brushmove();
function updateDateRangeDisplay(startDate, endDate ) {
//@todo: i18n the date format
commit 6727c95b6fdf3545b78c1f3403071f2dab525dc2
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue Jun 11 11:48:52 2013 -0700
Make hover values for individual points (non-aggregate bars) different and not show duration, min, max, avg because it is not applicable.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index c279bbf..c5b688a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -624,9 +624,14 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
'</div>';
- }
- else {
- // regular bar hover
+ } else if (d.y === d.high && d.high === d.low ) {
+ // single point of data not a duration
+ hoverString =
+ '<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel" >' + chartContext.timeLabel + ': </span>' + timeFormatter(date) +
+ '<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span>' + dateFormatter(date) + '</div>' +
+ '</div>';
+ } else {
+ // regular bar hover for duration
hoverString =
'<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel">' + chartContext.timeLabel + ': </span><span style="width:50px;">' + timeFormatter(date) + '</span>' +
'<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span><span style="width:50px;">' + dateFormatter(date) + '</span></div>' +
commit 2fce129fb5a4c4c42e22fc338a9d5af7854cdcc9
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Mon Jun 10 22:08:51 2013 -0700
Get rid of handles on the resize path and allow hover layer to float above so that hovers can now be used in conjunction with chart sliders.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 9e120f0..c279bbf 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -566,8 +566,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
.attr("class", "brush")
.call(brush);
- brushg.selectAll(".resize").append("path")
- .attr("d", resizePath);
+ brushg.selectAll(".resize").append("path");
brushg.selectAll("rect")
.attr("height", height);
@@ -669,6 +668,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
createHeader(chartContext.chartTitle);
createYAxisGridLines();
+ createBrush();
createStackedBars();
createXandYAxes();
createAvgLines();
@@ -677,7 +677,6 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
createOOBLines();
}
createHovers(chartContext);
- createBrush();
}
}
}; // end public closure
commit 1db127de71ffc405520afe2ba05e0d0092081a92
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Mon Jun 10 20:13:31 2013 -0700
Eliminate the default chart slider covering the whole graph when first brought up. Only after you click and start dragging will the sliders appear.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 1700cbd..9e120f0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -556,9 +556,9 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
},
brush = $wnd.d3.svg.brush()
.x(timeScale)
- .extent($wnd.d3.extent(chartData, function (d) {
- return d.x;
- }))
+ //.extent($wnd.d3.extent(chartData, function (d) {
+ //return d.x;
+ //}))
.on("brushstart", brushstart)
.on("brush", brushmove)
.on("brushend", brushend),
commit c7635ab43f0eab7590d1c89f2636d584c693ca6e
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Mon Jun 10 14:47:33 2013 -0700
Make chart refresh work with chart sliders and persistent values set by sliders.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index dd05276..1700cbd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -583,12 +583,16 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
function brushend() {
var s = brush.extent();
+ var startTime = Math.round(s[0].getTime());
+ var endTime = Math.round(s[1].getTime() );
svg.classed("selecting", !$wnd.d3.event.target.empty());
- //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::saveDateRange(DD)($wnd.moment(s[0]).unix(),$wnd.moment(s[0]).unix());
- //$wnd.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView::redrawGraphs()();
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::saveDateRange(DD)(startTime, endTime);
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::redrawGraphs()();
}
+ brushstart();
+ brushmove();
+
function updateDateRangeDisplay(startDate, endDate ) {
//@todo: i18n the date format
var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
commit 7ced87e301c515c88a7cf505d2b4dcbdc4741aa6
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 10 13:06:15 2013 -0700
Add ability to call redrawGraphs from the javascript chart so it can refresh once we are done dragging a new time range.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
index 79da3f5..036253f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
@@ -28,6 +28,8 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
@@ -47,6 +49,12 @@ public abstract class AbstractMetricGraph extends VLayout implements HasD3Metric
private static final Messages MSG = CoreGUI.getMessages();
private MetricGraphData metricGraphData;
+ /**
+ * Just so we have a handle to the the topmost view to call redraw graphs on a view
+ * from this graph.
+ */
+ private AbstractD3GraphListView graphListView;
+
public MetricGraphData getMetricGraphData() {
return metricGraphData;
}
@@ -180,6 +188,9 @@ public abstract class AbstractMetricGraph extends VLayout implements HasD3Metric
return metricGraphData.getPortalId();
}
+ public void setGraphListView(AbstractD3GraphListView graphListView) {
+ this.graphListView = graphListView;
+ }
/**
* Whenever we make a change to the date range save it here so it gets propogated to
@@ -204,4 +215,8 @@ public abstract class AbstractMetricGraph extends VLayout implements HasD3Metric
}
}
+
+ public void redrawGraphs(){
+ graphListView.redrawGraphs();
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index f0b6a56..dd05276 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -586,6 +586,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
svg.classed("selecting", !$wnd.d3.event.target.empty());
//global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::saveDateRange(DD)($wnd.moment(s[0]).unix(),$wnd.moment(s[0]).unix());
//$wnd.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView::redrawGraphs()();
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::redrawGraphs()();
}
function updateDateRangeDisplay(startDate, endDate ) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index e5b219b..00f9b40 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -198,7 +198,8 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
graph.setMetricGraphData(metricGraphData);
- MetricD3Graph graphView = new MetricD3Graph(graph);
+ graph.setGraphListView(this);
+ MetricD3Graph graphView = new MetricD3Graph<D3GroupGraphListView>(graph, this);
graphView.setWidth("95%");
graphView.setHeight(MULTI_CHART_HEIGHT);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index b8ed0d0..d913bdc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -378,7 +378,8 @@ public class D3GraphListView extends AbstractD3GraphListView {
measurementDefinition, data, measurementOOBCompositeList );
StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
graph.setMetricGraphData(metricGraphData);
- MetricD3Graph graphView = new MetricD3Graph(graph);
+ graph.setGraphListView(this);
+ MetricD3Graph graphView = new MetricD3Graph<D3GraphListView>(graph, this);
graphView.setWidth("95%");
graphView.setHeight(height);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
index fe0c65f..3b4ec1f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
@@ -21,6 +21,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitori
import com.google.gwt.user.client.Timer;
import com.smartgwt.client.widgets.HTMLFlow;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -29,11 +30,12 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
* A D3 graph implementation for graphing Resource metrics.
* Just the graph only. No avail graph no buttons just he graph.
*/
-public class MetricD3Graph extends EnhancedVLayout {
+public class MetricD3Graph<T extends AbstractD3GraphListView> extends EnhancedVLayout {
protected StackedBarMetricGraphImpl graph;
private HTMLFlow graphDiv = null;
protected Timer refreshTimer;
+ private T d3GraphListView;
/**
* This constructor is for the use case in the Dashboard where we dont actually
@@ -43,9 +45,10 @@ public class MetricD3Graph extends EnhancedVLayout {
super();
}
- public MetricD3Graph(StackedBarMetricGraphImpl graph) {
+ public MetricD3Graph(StackedBarMetricGraphImpl graph, T graphListView) {
super();
this.graph = graph;
+ this.d3GraphListView = graphListView;
setHeight100();
setWidth100();
}
@@ -198,4 +201,11 @@ public class MetricD3Graph extends EnhancedVLayout {
super.hide();
}
+ /**
+ * Allow the graph to refresh the whole d3GraphListView.
+ */
+ public void redrawGraphs(){
+ d3GraphListView.redrawGraphs();
+ }
+
}
commit cca6f3c148eda6abd2f41d2adec71f0c26865715
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 10 11:44:35 2013 -0700
Persist the slider changes to user prefs when the user is finished dragging range across graph.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
index f681d64..79da3f5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
@@ -19,9 +19,18 @@
package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+import java.util.Date;
+
import com.smartgwt.client.widgets.layout.VLayout;
import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
/**
* Common Metric Graph capability used across multiple metric rendering graphs.
@@ -35,6 +44,7 @@ import org.rhq.core.domain.measurement.MeasurementDefinition;
*/
public abstract class AbstractMetricGraph extends VLayout implements HasD3MetricJsniChart {
+ private static final Messages MSG = CoreGUI.getMessages();
private MetricGraphData metricGraphData;
public MetricGraphData getMetricGraphData() {
@@ -171,4 +181,27 @@ public abstract class AbstractMetricGraph extends VLayout implements HasD3Metric
}
+ /**
+ * Whenever we make a change to the date range save it here so it gets propogated to
+ * the correct places.
+ *
+ * @param startTime double because JSNI doesnt support long
+ * @param endTime double because JSNI doesnt support long
+ */
+ public void saveDateRange(double startTime, double endTime) {
+ MeasurementUserPreferences measurementUserPrefs = new MeasurementUserPreferences(UserSessionManager.getUserPreferences());
+
+ Log.debug("Saving Date range: "+new Date((long)startTime) + " - "+ new Date((long)endTime));
+ final boolean advanced = true;
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPrefs.getMetricRangePreferences();
+ prefs.explicitBeginEnd = advanced;
+ prefs.begin = (long) startTime;
+ prefs.end = (long) endTime;
+ if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
+ CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
+ } else {
+ measurementUserPrefs.setMetricRangePreferences(prefs);
+ }
+
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 3938525..0858f5d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -98,7 +98,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
customButton.addClickHandler(dateTimeButtonBarClickHandler);
toolStrip.addMember(customButton);
- toolStrip.addSpacer(20);
+ toolStrip.addSpacer(30);
dateRangeLabel = new Label();
dateRangeLabel.setWidth(260);
@@ -186,8 +186,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
*/
public void saveDateRange(double startTime, double endTime) {
final boolean advanced = true;
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences
- .getMetricRangePreferences();
prefs.explicitBeginEnd = advanced;
prefs.begin = (long) startTime;
prefs.end = (long) endTime;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index b359a05..f0b6a56 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -86,7 +86,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
barOffset = 2,
chartData,
interpolation = "basis",
- avgRaw, avg, minRaw, min, peakRaw, peak,
+ avgFiltered, avg, minFiltered, min, peakFiltered, peak,
oobMax,
legendDefined,
lowBound,
@@ -128,28 +128,28 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
chartData = chartContext.data;
}
- avgRaw = chartContext.data.filter(function (d) {
+ avgFiltered = chartContext.data.filter(function (d) {
if (d.nodata !== 'true') {
return d.y;
}
});
- avg = $wnd.d3.mean(avgRaw.map(function (d) {
+ avg = $wnd.d3.mean(avgFiltered.map(function (d) {
return d.y;
}));
- peakRaw = chartContext.data.filter(function (d) {
+ peakFiltered = chartContext.data.filter(function (d) {
if (d.nodata !== 'true') {
return d.high;
}
});
- peak = $wnd.d3.max(peakRaw.map(function (d) {
+ peak = $wnd.d3.max(peakFiltered.map(function (d) {
return d.high;
}));
- minRaw = chartContext.data.filter(function (d) {
+ minFiltered = chartContext.data.filter(function (d) {
if (d.nodata !== 'true') {
return d.low;
}
});
- min = $wnd.d3.min(minRaw.map(function (d) {
+ min = $wnd.d3.min(minFiltered.map(function (d) {
return d.low;
}));
highBound = peak + ((peak - min) * 0.1);
@@ -572,9 +572,6 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
brushg.selectAll("rect")
.attr("height", height);
- brushstart();
- brushmove();
-
function brushstart() {
svg.classed("selecting", true);
}
@@ -587,7 +584,8 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
function brushend() {
var s = brush.extent();
svg.classed("selecting", !$wnd.d3.event.target.empty());
- updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::saveDateRange(DD)($wnd.moment(s[0]).unix(),$wnd.moment(s[0]).unix());
+ //$wnd.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView::redrawGraphs()();
}
function updateDateRangeDisplay(startDate, endDate ) {
commit 53364f672e806eee2028caa017a0bbeae340db4f
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 10 08:28:17 2013 -0700
Make date range text change as the slider over the graph changes.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 23d971d..3938525 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -46,7 +46,7 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPre
*/
public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
- static final String TIMERANGE = "timerange";
+ static final String TIMERANGE = "graphtimerange";
static final int BUTTON_WIDTH = 28;
private MeasurementUserPreferences measurementUserPreferences;
@@ -101,16 +101,18 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
toolStrip.addSpacer(20);
dateRangeLabel = new Label();
- updateDateTimeRangeDisplay(new Date(prefs.begin), new Date(prefs.end));
dateRangeLabel.setWidth(260);
+ dateRangeLabel.setID("dateRange");
+ dateRangeLabel.addStyleName("graphDateTimeRangeLabel");
+ updateDateTimeRangeDisplay(new Date(prefs.begin), new Date(prefs.end));
toolStrip.addMember(dateRangeLabel);
toolStrip.addSpacer(20);
- IButton resetZoomButton = new IButton("Reset Manual Zoom");
- resetZoomButton.setWidth(150);
- resetZoomButton.disable();
- toolStrip.addMember(resetZoomButton);
+// IButton resetZoomButton = new IButton("Reset Manual Zoom");
+// resetZoomButton.setWidth(150);
+// resetZoomButton.disable();
+// toolStrip.addMember(resetZoomButton);
addMember(toolStrip);
}
@@ -160,6 +162,15 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
return new Date(endDate.getTime() - dateTimeOffset);
}
+ /**
+ * Function meant to be called by the javascript inside the d3 charting javascript.
+ * @param startDate double (as javascript doenst have long) representing unix date
+ * @param endDate double
+ */
+ public void updateDateTimeRangeDisplayFromJavascript(double startDate, double endDate){
+ updateDateTimeRangeDisplay(new Date((long)startDate), new Date((long)endDate));
+ }
+
public void updateDateTimeRangeDisplay(Date startDate, Date endDate) {
String rangeString = fmt.format(startDate) + " - " + fmt.format(endDate);
dateRangeLabel.setContents(rangeString);
@@ -207,7 +218,8 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
*/
private enum DateTimeButton {
oneHour( "1h", 60 * 60 ),
- sixHour( "6h", 6 * 60 * 60 ),
+ fourHour( "4h", 4 * 60 * 60 ),
+ eightHour( "8h", 8 * 60 * 60 ),
twelveHour( "12h", 12 * 60 * 60 ),
oneDay("1d", 24 * 60 * 60 ),
fiveDay("5d", 5 * 24 * 60 * 60 ),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 3317bf6..b359a05 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -581,19 +581,19 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
function brushmove() {
var s = brush.extent();
-// updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
}
function brushend() {
var s = brush.extent();
svg.classed("selecting", !$wnd.d3.event.target.empty());
- //updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
}
function updateDateRangeDisplay(startDate, endDate ) {
//@todo: i18n the date format
var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- $wnd.jQuery('#dateRange').text(formattedDateRange);
+ $wnd.jQuery('.graphDateTimeRangeLabel').text(formattedDateRange);
}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 24fbe87..72184b1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -50,6 +50,7 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
+ <script src="/coregui/js/moment.min.js"/>
<script src="/coregui/js/rhq.js"/>
<!-- External javascript libraries -->
<!-- jquery.sparkline requires jquery.
commit 559f502715d1af67b5890bc2e65ac468f17af19c
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jun 10 07:10:48 2013 -0700
Remove d3 consolidated graph view.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index b619fab..a6adc83 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -65,12 +65,10 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.PluginConfigurationHistoryListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.ResourceAgentView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.CalltimeView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3ConsolidatedGraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.ResourceAvailabilityView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.schedules.ResourceSchedulesView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MeasurementTableView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MetricsTableView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.traits.TraitsView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.history.ResourceOperationHistoryListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.schedule.ResourceOperationScheduleListView;
@@ -133,7 +131,6 @@ public class ResourceDetailView extends
private SubTab summaryTimeline;
private SubTab monitorNewGraphs;
private SubTab monitorTables;
- private SubTab metricsTables;
private SubTab monitorTraits;
private SubTab monitorAvail;
private SubTab monitorSched;
@@ -202,13 +199,12 @@ public class ResourceDetailView extends
monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
monitorTables = new SubTab(monitoringTab, new ViewName("Tables", "Tables"), null);
- metricsTables = new SubTab(monitoringTab, new ViewName("Metrics", MSG.view_tabs_common_metrics()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
monitorAvail = new SubTab(monitoringTab, new ViewName("Availability", MSG.view_tabs_common_availability()),
null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- monitoringTab.registerSubTabs(monitorTables, metricsTables, monitorNewGraphs, monitorTraits, monitorAvail,
+ monitoringTab.registerSubTabs(monitorTables, monitorNewGraphs, monitorTraits, monitorAvail,
monitorSched, monitorCallTime);
tabs.add(monitoringTab);
@@ -264,10 +260,7 @@ public class ResourceDetailView extends
return graphListView;
}
- protected D3GraphListView createD3ConsolidatedGraphListView() {
- graphListView = D3ConsolidatedGraphListView.createSparklineGraphs(resourceComposite.getResource());
- return graphListView;
- }
+
@Override
protected void updateTabContent(ResourceComposite resourceComposite, boolean isRefresh) {
@@ -414,13 +407,6 @@ public class ResourceDetailView extends
viewFactory = (!visible) ? null : new ViewFactory() {
@Override
public Canvas createView() {
- return createD3ConsolidatedGraphListView();
- }
- };
- updateSubTab(this.monitoringTab, this.metricsTables, visible, true, viewFactory);
- viewFactory = (!visible) ? null : new ViewFactory() {
- @Override
- public Canvas createView() {
return new MeasurementTableView(resource.getId());
}
};
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
deleted file mode 100644
index 52271c5..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import org.rhq.core.domain.common.EntityContext;
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.DataType;
-import org.rhq.core.domain.measurement.DisplayType;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.measurement.composite.MeasurementOOBComposite;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MetricsTableView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.async.Command;
-import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
-
-/**
- * Build the View that shows the individual graph views for multi-graph
- * views if just a resource is provided and single graph view if resource
- * and measurement definitionId are provided.
- *
- * @author Mike Thompson
- */
-public class D3ConsolidatedGraphListView extends D3GraphListView {
-
- private static int NUM_ASYNC_CALLS = 2; // wait for X async calls in Latch
-
- private Resource resource;
- private Set<Integer> definitionIds = null;
- private boolean useSummaryData = false;
- private PageList<MeasurementOOBComposite> measurementOOBCompositeList;
- private List<List<MeasurementDataNumericHighLowComposite>> metricsDataList;
- private VLayout vLayout;
- private MetricsTableView metricsTableView;
-
- public static D3ConsolidatedGraphListView createSparklineGraphs(Resource resource) {
- return new D3ConsolidatedGraphListView(resource, true);
- }
-
- private D3ConsolidatedGraphListView(Resource resource, boolean showAvailabilityGraph) {
- super(resource, showAvailabilityGraph);
- this.resource = resource;
- this.showAvailabilityGraph = showAvailabilityGraph;
- //commonConstructorSettings();
- useSummaryData = true;
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- Log.debug("D3ConsolidatedGraphListView.onDraw() for: " + resource.getName());
- destroyMembers();
-
- addMember(buttonBarDateTimeRangeEditor);
-
- availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(
- new AvailabilityOverUnderGraphType(resource.getId()));
- // first step in 2 step to create d3 chart
- // create a placeholder for avail graph
- availabilityGraph.createGraphMarker();
- addMember(availabilityGraph);
-
- vLayout = new VLayout();
- vLayout.setOverflow(Overflow.AUTO);
- vLayout.setWidth100();
- vLayout.setHeight100();
-
- if (resource != null) {
- queryAndBuildGraphs();
- metricsTableView = new MetricsTableView(resource.getId());
- vLayout.addMember(metricsTableView);
- }
- addMember(vLayout);
- }
-
- public void redrawGraphs() {
- this.onDraw();
- availabilityGraph.drawJsniChart();
- }
-
- @Override
- protected void queryAvailability(final EntityContext context, Long startTime, Long endTime,
- final CountDownLatch countDownLatch) {
-
- final long timerStart = System.currentTimeMillis();
-
- // now return the availability
- GWTServiceLookup.getAvailabilityService().getAvailabilitiesForResource(context.getResourceId(), startTime,
- endTime, new AsyncCallback<List<Availability>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_availability_loadFailed(), caught);
- if (countDownLatch != null) {
- countDownLatch.countDown();
- }
- }
-
- @Override
- public void onSuccess(List<Availability> availList) {
- Log.debug("\nSuccessfully queried availability in: " + (System.currentTimeMillis() - timerStart)
- + " ms.");
- availabilityList = availList;
- if (countDownLatch != null) {
- countDownLatch.countDown();
- }
- }
- });
- }
-
- /**
- * Build whatever graph (summary or not) by grabbing the MeasurementDefinitions
- * that are defined for the resource and then querying the metric and availability data.
- */
- private void queryAndBuildGraphs() {
- final long startTimer = System.currentTimeMillis();
-
- if (null != availabilityGraph) {
- queryAvailability(EntityContext.forResource(resource.getId()), buttonBarDateTimeRangeEditor.getStartTime(),
- buttonBarDateTimeRangeEditor.getEndTime(), null);
- }
-
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(),
- EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
- new ResourceTypeRepository.TypeLoadedCallback() {
- public void onTypesLoaded(final ResourceType type) {
-
- final ArrayList<MeasurementDefinition> measurementDefinitions = new ArrayList<MeasurementDefinition>();
- final ArrayList<MeasurementDefinition> summaryMeasurementDefinitions = new ArrayList<MeasurementDefinition>();
-
- for (MeasurementDefinition def : type.getMetricDefinitions()) {
- if (def.getDataType() == DataType.MEASUREMENT && def.getDisplayType() == DisplayType.SUMMARY) {
- summaryMeasurementDefinitions.add(def);
- }
- measurementDefinitions.add(def);
- }
-
- Collections.sort(measurementDefinitions, new Comparator<MeasurementDefinition>() {
- @Override
- public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
- return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder());
- }
- });
- Collections.sort(summaryMeasurementDefinitions, new Comparator<MeasurementDefinition>() {
- @Override
- public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
- return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder());
- }
- });
-
- int[] measDefIdArray = new int[measurementDefinitions.size()];
- for (int i = 0; i < measDefIdArray.length; i++) {
- measDefIdArray[i] = measurementDefinitions.get(i).getId();
- }
-
- // setting up a deferred Command to execute after all resource queries have completed (successfully or unsuccessfully)
- // we know there are exactly 2 resources
- final CountDownLatch countDownLatch = CountDownLatch.create(NUM_ASYNC_CALLS, new Command() {
- @Override
- /**
- * Satisfied only after ALL of the metric queries AND availability have completed
- */
- public void execute() {
- Log.debug("Total Time for async metrics/avail query: "
- + (System.currentTimeMillis() - startTimer));
- if (null == metricsDataList || metricsDataList.isEmpty()) {
- loadingLabel.setContents(MSG.view_resource_monitor_graphs_noneAvailable());
- } else {
- loadingLabel.hide();
- if (useSummaryData) {
- buildSummaryGraphs(metricsDataList, summaryMeasurementDefinitions,
- measurementDefinitions);
- } else {
- determineGraphsToBuild(metricsDataList, measurementDefinitions, definitionIds);
- }
- // There is a weird timing case when availabilityGraph can be null
- if (null != availabilityGraph) {
- // we only need the first metricData since we are only taking the
- // availability data set in there for the dropdowns already
- availabilityGraph.setAvailabilityList(availabilityList);
- new Timer() {
- /**
- * This method will be called when a timer fires. Override it to implement the timer's logic.
- */
- @Override
- public void run() {
- availabilityGraph.drawJsniChart();
- }
- }.schedule(200);
- }
- }
-
- }
- });
-
- queryMetricData(measDefIdArray, countDownLatch);
- queryOOBMetrics(resource, countDownLatch);
- // now the countDown latch will run sometime asynchronously
-
- }
-
- private void queryMetricData(final int[] measDefIdArray, final CountDownLatch countDownLatch) {
- GWTServiceLookup.getMeasurementDataService().findDataForResource(resource.getId(), measDefIdArray,
- buttonBarDateTimeRangeEditor.getStartTime(), buttonBarDateTimeRangeEditor.getEndTime(), 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_loadFailed(),
- caught);
- loadingLabel.setContents(MSG.view_resource_monitor_graphs_loadFailed());
- countDownLatch.countDown();
- }
-
- @Override
- public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> metrics) {
- metricsDataList = metrics;
- Log.debug("Regular Metric graph data queried in: "
- + (System.currentTimeMillis() - startTimer + " ms."));
- countDownLatch.countDown();
-
- }
- });
- }
-
- private void queryOOBMetrics(final Resource resource, final CountDownLatch countDownLatch) {
-
- final long startTime = System.currentTimeMillis();
-
- GWTServiceLookup.getMeasurementDataService().getHighestNOOBsForResource(resource.getId(), 60,
-
- new AsyncCallback<PageList<MeasurementOOBComposite>>() {
- @Override
- public void onSuccess(PageList<MeasurementOOBComposite> measurementOOBComposites) {
-
- measurementOOBCompositeList = measurementOOBComposites;
- Log.debug("\nSuccessfully queried " + measurementOOBCompositeList.size()
- + " OOB records in: " + (System.currentTimeMillis() - startTime) + " ms.");
- countDownLatch.countDown();
- }
-
- @Override
- public void onFailure(Throwable caught) {
- Log.debug("Error retrieving out of bound metrics for resource [" + resource.getId() + "]:"
- + caught.getMessage());
- countDownLatch.countDown();
- }
- });
-
- }
-
- /**
- * Spin through the measurement definitions (in order) checking to see if they are in the
- * summary measurement definition set and if so build a graph.
- * @param measurementData
- * @param summaryMeasurementDefinitions
- * @param measurementDefinitions
- */
- private void buildSummaryGraphs(List<List<MeasurementDataNumericHighLowComposite>> measurementData,
- List<MeasurementDefinition> summaryMeasurementDefinitions,
- List<MeasurementDefinition> measurementDefinitions) {
- Set<Integer> summaryIds = new TreeSet<Integer>();
- for (MeasurementDefinition summaryMeasurementDefinition : summaryMeasurementDefinitions) {
- summaryIds.add(summaryMeasurementDefinition.getId());
- }
-
- int i = 0;
- for (MeasurementDefinition measurementDefinition : measurementDefinitions) {
- if (summaryIds.contains(measurementDefinition.getId())) {
- buildSingleGraph(measurementOOBCompositeList, measurementDefinition,
- measurementData.get(i), MULTI_CHART_HEIGHT);
- }
- i++;
- }
-
- }
-
- private void determineGraphsToBuild(List<List<MeasurementDataNumericHighLowComposite>> measurementData,
- List<MeasurementDefinition> measurementDefinitions, Set<Integer> definitionIds) {
- int i = 0;
- for (List<MeasurementDataNumericHighLowComposite> metric : measurementData) {
-
- for (Integer selectedDefinitionId : definitionIds) {
- final MeasurementDefinition measurementDefinition = measurementDefinitions.get(i);
- final int measurementId = measurementDefinition.getId();
-
- if (null != selectedDefinitionId) {
- // single graph case
- if (measurementId == selectedDefinitionId) {
- buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric,
- SINGLE_CHART_HEIGHT);
- }
- } else {
- // multiple graph case
- buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric,
- MULTI_CHART_HEIGHT);
- }
- }
- i++;
- }
- }
- });
-
- }
-
- private void buildSingleGraph(PageList<MeasurementOOBComposite> measurementOOBCompositeList,
- MeasurementDefinition measurementDefinition, List<MeasurementDataNumericHighLowComposite> data, int height) {
-
- MetricGraphData metricGraphData = MetricGraphData.createForResource(resource.getId(), resource.getName(),
- measurementDefinition, data, measurementOOBCompositeList);
- StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
- graph.setMetricGraphData(metricGraphData);
- MetricD3Graph graphView = new MetricD3Graph(graph);
-
- graphView.setWidth("95%");
- graphView.setHeight(height);
-
- vLayout.addMember(graphView);
- }
-
-}
commit 0cbaf79ddf1975c322241997f78807560f5a8739
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Sun Jun 9 12:24:38 2013 -0700
Documentation and cleanup of code for new button bar date range editor.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index b0e3009..9ceb5f8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -29,7 +29,7 @@ import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.AutoRefreshUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -48,13 +48,13 @@ public abstract class AbstractD3GraphListView extends EnhancedVLayout implements
protected AvailabilityD3GraphView availabilityGraph;
protected MeasurementUserPreferences measurementUserPrefs;
protected boolean showAvailabilityGraph = false;
- protected ButtonBarDateTimeRangeEditor2 buttonBarDateTimeRangeEditor;
+ protected ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor;
protected Timer refreshTimer;
public AbstractD3GraphListView() {
super();
measurementUserPrefs = new MeasurementUserPreferences(UserSessionManager.getUserPreferences());
- buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor2(measurementUserPrefs,this);
+ buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
startRefreshCycle();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
new file mode 100644
index 0000000..23d971d
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -0,0 +1,238 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import java.util.Date;
+
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.smartgwt.client.types.SelectionType;
+import com.smartgwt.client.widgets.IButton;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.toolbar.ToolStrip;
+
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+
+/**
+ * Component to allow selection of Date/Time range for graphs using a radio button group.
+ * The DateTimeButton enum defines the button labels and time ranges change this if you
+ * wish to add/delete custom time ranges.
+ *
+ * @author Mike Thompson
+ */
+public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
+
+ static final String TIMERANGE = "timerange";
+ static final int BUTTON_WIDTH = 28;
+
+ private MeasurementUserPreferences measurementUserPreferences;
+ private AbstractD3GraphListView d3GraphListView;
+ private static final Messages MSG = CoreGUI.getMessages();
+ private Label dateRangeLabel;
+ //@todo: pull dateformat messages.properties
+ private static final DateTimeFormat fmt = DateTimeFormat.getFormat("MM/dd/yyyy h:mm a");
+ private DateTimeButtonBarClickHandler dateTimeButtonBarClickHandler;
+ private AbstractMeasurementRangeEditor.MetricRangePreferences prefs;
+
+ public ButtonBarDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
+ AbstractD3GraphListView d3GraphListView) {
+ this.measurementUserPreferences = measurementUserPrefs;
+ this.d3GraphListView = d3GraphListView;
+
+ dateTimeButtonBarClickHandler = new DateTimeButtonBarClickHandler();
+ prefs = measurementUserPreferences.getMetricRangePreferences();
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start: " + prefs.begin + " end: " + prefs.end);
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: " + new Date(prefs.begin) + " end Date: "
+ + new Date(prefs.end));
+ createButtons();
+ }
+
+ public void createButtons() {
+
+ ToolStrip toolStrip = new ToolStrip();
+ toolStrip.setWidth100();
+ toolStrip.setHeight(24);
+
+ toolStrip.addSpacer(10);
+
+ for(DateTimeButton dateTimeButton : DateTimeButton.values()){
+ IButton oneHourButton = new IButton(dateTimeButton.label);
+ oneHourButton.setWidth(BUTTON_WIDTH);
+ oneHourButton.setActionType(SelectionType.RADIO);
+ oneHourButton.setRadioGroup(TIMERANGE);
+ oneHourButton.addClickHandler(dateTimeButtonBarClickHandler);
+
+ toolStrip.addMember(oneHourButton);
+ }
+
+
+ IButton customButton = new IButton("Custom...");
+ customButton.setWidth(60);
+ customButton.disable();
+ customButton.setActionType(SelectionType.RADIO);
+ customButton.setRadioGroup(TIMERANGE);
+ customButton.addClickHandler(dateTimeButtonBarClickHandler);
+ toolStrip.addMember(customButton);
+
+ toolStrip.addSpacer(20);
+
+ dateRangeLabel = new Label();
+ updateDateTimeRangeDisplay(new Date(prefs.begin), new Date(prefs.end));
+ dateRangeLabel.setWidth(260);
+ toolStrip.addMember(dateRangeLabel);
+
+ toolStrip.addSpacer(20);
+
+ IButton resetZoomButton = new IButton("Reset Manual Zoom");
+ resetZoomButton.setWidth(150);
+ resetZoomButton.disable();
+ toolStrip.addMember(resetZoomButton);
+
+ addMember(toolStrip);
+ }
+
+
+ public void redrawGraphs() {
+ d3GraphListView.redrawGraphs();
+ }
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ removeMembers(getMembers());
+ createButtons();
+ }
+
+ @Override
+ public void parentResized() {
+ super.parentResized();
+ removeMembers(getMembers());
+ createButtons();
+ //drawJsniChart();
+ }
+
+ public Label getDateRangeLabel() {
+ return dateRangeLabel;
+ }
+
+ public Long getStartTime() {
+ return measurementUserPreferences.getMetricRangePreferences().begin;
+ }
+
+ public Long getEndTime() {
+ return measurementUserPreferences.getMetricRangePreferences().end;
+ }
+
+ public Date calculateStartDate(Date endDate, String dateTimeSelection) {
+ long dateTimeOffset = 0;
+ for(DateTimeButton dateTimeButton : DateTimeButton.values()){
+ if(dateTimeButton.label.equals(dateTimeSelection)){
+ dateTimeOffset = dateTimeButton.timeSpanInSeconds * 1000;
+ break;
+ }
+ }
+
+ Log.debug("DateTimeSelection: "+ dateTimeSelection + " = "+ dateTimeOffset);
+ return new Date(endDate.getTime() - dateTimeOffset);
+ }
+
+ public void updateDateTimeRangeDisplay(Date startDate, Date endDate) {
+ String rangeString = fmt.format(startDate) + " - " + fmt.format(endDate);
+ dateRangeLabel.setContents(rangeString);
+
+ }
+
+ /**
+ * Whenever we make a change to the date range save it here so it gets propogated to
+ * the correct places.
+ *
+ * @param startTime double because JSNI doesnt support long
+ * @param endTime double because JSNI doesnt support long
+ */
+ public void saveDateRange(double startTime, double endTime) {
+ final boolean advanced = true;
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences
+ .getMetricRangePreferences();
+ prefs.explicitBeginEnd = advanced;
+ prefs.begin = (long) startTime;
+ prefs.end = (long) endTime;
+ if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
+ CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
+ } else {
+ measurementUserPreferences.setMetricRangePreferences(prefs);
+ }
+
+ }
+
+ private class DateTimeButtonBarClickHandler implements ClickHandler {
+
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ IButton button = (IButton) clickEvent.getSource();
+ String selectedDateTimeRange = button.getTitle();
+ Date calculatedStartDateTime = calculateStartDate(new Date(getEndTime()), selectedDateTimeRange);
+ saveDateRange(calculatedStartDateTime.getTime(),new Date().getTime());
+ redrawGraphs();
+ updateDateTimeRangeDisplay(calculatedStartDateTime, new Date());
+ }
+ }
+
+ @SuppressWarnings("GwtInconsistentSerializableClass")
+ /**
+ * This enum defines the button labels and time ranges used in the toolbar.
+ */
+ private enum DateTimeButton {
+ oneHour( "1h", 60 * 60 ),
+ sixHour( "6h", 6 * 60 * 60 ),
+ twelveHour( "12h", 12 * 60 * 60 ),
+ oneDay("1d", 24 * 60 * 60 ),
+ fiveDay("5d", 5 * 24 * 60 * 60 ),
+ oneMonth("1m", 30 * 24 * 60 * 60 ),
+ threeMonth("3m", 3 * 30 * 24 * 60 * 60 ),
+ sixMonth("6m", 6 * 30 * 24 * 60 * 60 );
+
+ private final String label;
+ private final long timeSpanInSeconds;
+ private final ClickHandler clickHandler;
+
+ DateTimeButton(String label, long timeSpanInSeconds) {
+ this.label = label;
+ this.timeSpanInSeconds = timeSpanInSeconds;
+ this.clickHandler = new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ IButton button = (IButton) clickEvent.getSource();
+ Log.debug("Button pressed for: " + button.getTitle());
+
+ }
+ };
+
+ }
+
+ }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
deleted file mode 100644
index 63585a7..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
-
-import java.util.Date;
-
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.smartgwt.client.types.SelectionType;
-import com.smartgwt.client.widgets.IButton;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-import com.smartgwt.client.widgets.toolbar.ToolStrip;
-
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
-
-/**
- * Component to allow selection of Date/Time range for graphs using a button group from bootstrap.
- *
- * @author Mike Thompson
- */
-public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
-
- static final String TIMERANGE = "timerange";
- static final int BUTTON_WIDTH = 28;
-
- private MeasurementUserPreferences measurementUserPreferences;
- private AbstractD3GraphListView d3GraphListView;
- private static final Messages MSG = CoreGUI.getMessages();
- private Label dateRangeLabel;
- //@todo: pull dateformat messages.properties
- private static final DateTimeFormat fmt = DateTimeFormat.getFormat("MM/dd/yyyy h:mm a");
- private DateTimeButtonBarClickHandler dateTimeButtonBarClickHandler;
- private AbstractMeasurementRangeEditor.MetricRangePreferences prefs;
-
- public ButtonBarDateTimeRangeEditor2(MeasurementUserPreferences measurementUserPrefs,
- AbstractD3GraphListView d3GraphListView) {
- this.measurementUserPreferences = measurementUserPrefs;
- this.d3GraphListView = d3GraphListView;
-
- dateTimeButtonBarClickHandler = new DateTimeButtonBarClickHandler();
- prefs = measurementUserPreferences.getMetricRangePreferences();
- Log.debug("ButtonBarDateTimeRangeEditor initialized with start: " + prefs.begin + " end: " + prefs.end);
- Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: " + new Date(prefs.begin) + " end Date: "
- + new Date(prefs.end));
- createButtons();
- }
-
- public void createButtons() {
-
- ToolStrip toolStrip = new ToolStrip();
- toolStrip.setWidth100();
- toolStrip.setHeight(24);
-
- toolStrip.addSpacer(10);
-
- for(DateTimeButton dateTimeButton : DateTimeButton.values()){
- IButton oneHourButton = new IButton(dateTimeButton.label);
- oneHourButton.setWidth(BUTTON_WIDTH);
- oneHourButton.setActionType(SelectionType.RADIO);
- oneHourButton.setRadioGroup(TIMERANGE);
- oneHourButton.addClickHandler(dateTimeButtonBarClickHandler);
-
- toolStrip.addMember(oneHourButton);
- }
-
-
- IButton customButton = new IButton("Custom...");
- customButton.setWidth(60);
- customButton.disable();
- customButton.setActionType(SelectionType.RADIO);
- customButton.setRadioGroup(TIMERANGE);
- customButton.addClickHandler(dateTimeButtonBarClickHandler);
- toolStrip.addMember(customButton);
-
- toolStrip.addSpacer(20);
-
- dateRangeLabel = new Label();
- updateDateTimeRangeDisplay(new Date(prefs.begin), new Date(prefs.end));
- dateRangeLabel.setWidth(260);
- toolStrip.addMember(dateRangeLabel);
-
- toolStrip.addSpacer(20);
-
- IButton resetZoomButton = new IButton("Reset Manual Zoom");
- resetZoomButton.setWidth(150);
- resetZoomButton.disable();
- toolStrip.addMember(resetZoomButton);
-
- addMember(toolStrip);
- }
-
-
- public void redrawGraphs() {
- d3GraphListView.redrawGraphs();
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- removeMembers(getMembers());
- createButtons();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- createButtons();
- //drawJsniChart();
- }
-
- public Label getDateRangeLabel() {
- return dateRangeLabel;
- }
-
- public Long getStartTime() {
- return measurementUserPreferences.getMetricRangePreferences().begin;
- }
-
- public Long getEndTime() {
- return measurementUserPreferences.getMetricRangePreferences().end;
- }
-
- public Date calculateStartDate(Date endDate, String dateTimeSelection) {
- long dateTimeOffset = 0;
- for(DateTimeButton dateTimeButton : DateTimeButton.values()){
- if(dateTimeButton.label.equals(dateTimeSelection)){
- dateTimeOffset = dateTimeButton.timeSpanInSeconds * 1000;
- break;
- }
- }
-
- Log.debug("DateTimeSelection: "+ dateTimeSelection + " = "+ dateTimeOffset);
- return new Date(endDate.getTime() - dateTimeOffset);
- }
-
- public void updateDateTimeRangeDisplay(Date startDate, Date endDate) {
- String rangeString = fmt.format(startDate) + " - " + fmt.format(endDate);
- dateRangeLabel.setContents(rangeString);
-
- }
-
- /**
- * Whenever we make a change to the date range save it here so it gets propogated to
- * the correct places.
- *
- * @param startTime double because JSNI doesnt support long
- * @param endTime double because JSNI doesnt support long
- */
- public void saveDateRange(double startTime, double endTime) {
-
- //@todo: uncomment when ready
- final boolean advanced = true;
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences
- .getMetricRangePreferences();
- prefs.explicitBeginEnd = advanced;
- prefs.begin = (long) startTime;
- prefs.end = (long) endTime;
- ///prefs.setPreference(PREF_METRIC_RANGE, Arrays.asList(prefs.begin, prefs.end));
- if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
- CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
- } else {
- measurementUserPreferences.setMetricRangePreferences(prefs);
- }
-
- }
-
- private class DateTimeButtonBarClickHandler implements ClickHandler {
-
- @Override
- public void onClick(ClickEvent clickEvent) {
- IButton button = (IButton) clickEvent.getSource();
- String selectedDateTimeRange = button.getTitle();
- Date calculatedStartDateTime = calculateStartDate(new Date(getEndTime()), selectedDateTimeRange);
- saveDateRange(calculatedStartDateTime.getTime(),new Date().getTime());
- redrawGraphs();
- updateDateTimeRangeDisplay(calculatedStartDateTime, new Date());
- }
- }
-
- @SuppressWarnings("GwtInconsistentSerializableClass")
- private enum DateTimeButton {
- oneHour( "1h", 60 * 60 ),
- sixHour( "6h", 6 * 60 * 60 ),
- twelveHour( "12h", 12 * 60 * 60 ),
- oneDay("1d", 24 * 60 * 60 ),
- fiveDay("5d", 5 * 24 * 60 * 60 ),
- oneMonth("1m", 30 * 24 * 60 * 60 ),
- threeMonth("3m", 3 * 30 * 24 * 60 * 60 ),
- sixMonth("6m", 6 * 30 * 24 * 60 * 60 );
-
- private final String label;
- private final long timeSpanInSeconds;
- private final ClickHandler clickHandler;
-
- DateTimeButton(String label, long timeSpanInSeconds) {
- this.label = label;
- this.timeSpanInSeconds = timeSpanInSeconds;
- this.clickHandler = new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- IButton button = (IButton) clickEvent.getSource();
- Log.debug("Button pressed for: " + button.getTitle());
-
- }
- };
-
- }
-
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 1873dfb..b8ed0d0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -45,7 +45,7 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
@@ -112,7 +112,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
}
private void commonConstructorSettings() {
- buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor2(measurementUserPrefs,this);
+ buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
setOverflow(Overflow.HIDDEN);
}
commit 46967c43dfd59ca4cab212e41b845e64ae840ac1
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Sun Jun 9 10:06:40 2013 -0700
Save new date selection range to max 6 months from 1 year value as it is too large to save to DB (in ms)
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index 12de8d7..b0e3009 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -41,7 +41,7 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPre
*/
public abstract class AbstractD3GraphListView extends EnhancedVLayout implements AutoRefresh {
protected final static int SINGLE_CHART_HEIGHT = 225;
- protected final static int MULTI_CHART_HEIGHT = 195;
+ protected final static int MULTI_CHART_HEIGHT = 210;
protected static Label loadingLabel = new Label(MSG.common_msg_loading());
protected List<Availability> availabilityList;
protected List<ResourceGroupAvailability> groupAvailabilityList;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
index a0acc4e..63585a7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
@@ -195,7 +195,6 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
public void onClick(ClickEvent clickEvent) {
IButton button = (IButton) clickEvent.getSource();
String selectedDateTimeRange = button.getTitle();
- Log.info("Button pressed for: " + selectedDateTimeRange);
Date calculatedStartDateTime = calculateStartDate(new Date(getEndTime()), selectedDateTimeRange);
saveDateRange(calculatedStartDateTime.getTime(),new Date().getTime());
redrawGraphs();
@@ -212,7 +211,7 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
fiveDay("5d", 5 * 24 * 60 * 60 ),
oneMonth("1m", 30 * 24 * 60 * 60 ),
threeMonth("3m", 3 * 30 * 24 * 60 * 60 ),
- oneYear("1y",365 * 24 * 60 * 60 );
+ sixMonth("6m", 6 * 30 * 24 * 60 * 60 );
private final String label;
private final long timeSpanInSeconds;
commit fb2ac6b977008e4cb69f6d8eb50b273e0203c23b
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Sun Jun 9 09:08:06 2013 -0700
Save new date selection range to user preferences.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
index cf42e2f..a0acc4e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
@@ -197,8 +197,9 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
String selectedDateTimeRange = button.getTitle();
Log.info("Button pressed for: " + selectedDateTimeRange);
Date calculatedStartDateTime = calculateStartDate(new Date(getEndTime()), selectedDateTimeRange);
- updateDateTimeRangeDisplay(calculatedStartDateTime, new Date());
+ saveDateRange(calculatedStartDateTime.getTime(),new Date().getTime());
redrawGraphs();
+ updateDateTimeRangeDisplay(calculatedStartDateTime, new Date());
}
}
commit e3a68183560a1cb6d63beebd10ceb177fa93240e
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Sun Jun 9 08:08:05 2013 -0700
Add smartgwt buttonbar for date range selection.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index f6eb007..12de8d7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -29,7 +29,6 @@ import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.AutoRefreshUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
@@ -43,10 +42,10 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPre
public abstract class AbstractD3GraphListView extends EnhancedVLayout implements AutoRefresh {
protected final static int SINGLE_CHART_HEIGHT = 225;
protected final static int MULTI_CHART_HEIGHT = 195;
+ protected static Label loadingLabel = new Label(MSG.common_msg_loading());
protected List<Availability> availabilityList;
protected List<ResourceGroupAvailability> groupAvailabilityList;
protected AvailabilityD3GraphView availabilityGraph;
- protected static Label loadingLabel = new Label(MSG.common_msg_loading());
protected MeasurementUserPreferences measurementUserPrefs;
protected boolean showAvailabilityGraph = false;
protected ButtonBarDateTimeRangeEditor2 buttonBarDateTimeRangeEditor;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
deleted file mode 100644
index 8bbb053..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-
-import com.google.gwt.user.client.Timer;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.UserPreferenceNames;
-
-/**
- * Component to allow selection of Date/Time range for graphs using a button group from bootstrap.
- *
- * @author Mike Thompson
- */
-@Deprecated
-public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
-
- private MeasurementUserPreferences measurementUserPreferences;
- private AbstractD3GraphListView d3GraphListView;
- private static final Messages MSG = CoreGUI.getMessages();
-
-
- public ButtonBarDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
- AbstractD3GraphListView d3GraphListView) {
- this.measurementUserPreferences = measurementUserPrefs;
- this.d3GraphListView = d3GraphListView;
-
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
- Log.debug("ButtonBarDateTimeRangeEditor initialized with start: "+ prefs.begin +" end: "+prefs.end);
- Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: "+ new Date(prefs.begin) +" end Date: "+new Date(prefs.end));
- }
-
- /**
- * Setup the page elements especially the div and svg elements that serve as
- * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
- * Later the drawJsniGraph() is called to actually fill in the div/svg element
- * created here with the actual svg element.
- * NOTE: auxiliary javascript functions in rhq.js
- *
- */
- public void createDateSliderMarker() {
- Log.debug("drawGraph marker for: buttonBarDateTimeRangeEditor" );
-
- // append the bootstrap buttongroup since smartGWT doesn't have one
- StringBuilder buttonBarDiv = new StringBuilder();
- buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
- "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
- " <div class=\"accordion-group\">" +
- " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
- " <div class=\"accordion-inner\">" +
- " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
- " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
- " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
- " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
- " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
- " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
- " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
- " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
- " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
- " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
- " </span>" +
- " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
- " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
- " </div>" +
- " </div>" +
- " </div>" +
- " </div>");
- HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
- buttonBarDivFlow.setWidth100();
- buttonBarDivFlow.setHeight(50);
- addMember(buttonBarDivFlow);
- new Timer(){
- @Override
- public void run() {
- attachGraphDateRangeEditorButtonGroupHandlers();
- }
- }.schedule(200);
- }
-
- public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
- console.log("Draw GraphDateTimeRangeEditor");
- var global = this;
-
- function updateDateDisplay(startDate, endDate ) {
- var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- $wnd.jQuery('#dateRange').text(formattedDateRange);
- }
-
- function saveDateRange(startDate, endDate){
- var start = startDate | 0, end = endDate | 0;
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor::changeDateRange(DD)(start,end);
- //@todo: fixme
- //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
- }
-
- var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
-
- $wnd.jQuery("#radio1h").bind('click', function (event) {
- console.log("1h selected");
- graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio6h").bind('click', function (event) {
- console.log(" 6h selected");
- graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio12h").bind('click', function (event) {
- console.log("12h selected");
- graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio1d").bind('click', function (event) {
- console.log("1d selected");
- graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio5d").bind('click', function (event) {
- console.log("5d selected");
- graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio1m").bind('click', function (event) {
- console.log("1m selected");
- graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio3m").bind('click', function (event) {
- console.log("3m selected");
- graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio1y").bind('click', function (event) {
- console.log("1y selected");
- graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radioCustom").bind('click', function (event) {
- console.log("Custom Range selected");
- graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- });
-
-
- // initially populate with default click
- $wnd.jQuery("#radio12h").click();
-
- }-*/;
-
- public native void refreshGraphs() /*-{
- console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
- this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor::redrawGraphs()();
- }-*/;
-
-
-
- public void redrawGraphs(){
- d3GraphListView.redrawGraphs();
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- removeMembers(getMembers());
- createDateSliderMarker();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- createDateSliderMarker();
- //drawJsniChart();
- }
-
-
- public Long getStartTime() {
- return measurementUserPreferences.getMetricRangePreferences().begin;
- }
-
- public Long getEndTime() {
- return measurementUserPreferences.getMetricRangePreferences().end;
- }
- /**
- * Whenever we make a change to the date range save it here so it gets propogated to
- * the correct places.
- * @param startTime double because JSNI doesnt support long
- * @param endTime double because JSNI doesnt support long
- */
- public void changeDateRange(double startTime, double endTime){
-
- //@todo: uncomment when ready
- final boolean advanced = true;
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
- prefs.explicitBeginEnd = advanced;
- prefs.begin = (long) startTime;
- prefs.end = (long) endTime;
- ///prefs.setPreference(PREF_METRIC_RANGE, Arrays.asList(prefs.begin, prefs.end));
- if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
- CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
- } else {
- measurementUserPreferences.setMetricRangePreferences(prefs);
- }
-
- }
-
-
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
index b066bad..cf42e2f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
@@ -20,6 +20,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
import java.util.Date;
+import com.google.gwt.i18n.client.DateTimeFormat;
import com.smartgwt.client.types.SelectionType;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Label;
@@ -49,19 +50,22 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
private MeasurementUserPreferences measurementUserPreferences;
private AbstractD3GraphListView d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
- private String dateTimeSelection;
private Label dateRangeLabel;
+ //@todo: pull dateformat messages.properties
+ private static final DateTimeFormat fmt = DateTimeFormat.getFormat("MM/dd/yyyy h:mm a");
+ private DateTimeButtonBarClickHandler dateTimeButtonBarClickHandler;
+ private AbstractMeasurementRangeEditor.MetricRangePreferences prefs;
public ButtonBarDateTimeRangeEditor2(MeasurementUserPreferences measurementUserPrefs,
- AbstractD3GraphListView d3GraphListView) {
+ AbstractD3GraphListView d3GraphListView) {
this.measurementUserPreferences = measurementUserPrefs;
this.d3GraphListView = d3GraphListView;
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences
- .getMetricRangePreferences();
+ dateTimeButtonBarClickHandler = new DateTimeButtonBarClickHandler();
+ prefs = measurementUserPreferences.getMetricRangePreferences();
Log.debug("ButtonBarDateTimeRangeEditor initialized with start: " + prefs.begin + " end: " + prefs.end);
Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: " + new Date(prefs.begin) + " end Date: "
- + new Date(prefs.end));
+ + new Date(prefs.end));
createButtons();
}
@@ -73,270 +77,42 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
toolStrip.addSpacer(10);
- IButton oneHourButton = new IButton("1h");
- oneHourButton.setWidth(BUTTON_WIDTH);
- oneHourButton.setActionType(SelectionType.RADIO);
- oneHourButton.setRadioGroup(TIMERANGE);
- oneHourButton.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- Log.debug("Pressed 1h button");
- dateTimeSelection = "1h";
- }
- });
- toolStrip.addMember(oneHourButton);
-
- IButton sixHourButton = new IButton("6h");
- sixHourButton.setWidth(BUTTON_WIDTH);
- sixHourButton.setActionType(SelectionType.RADIO);
- sixHourButton.setRadioGroup(TIMERANGE);
- sixHourButton.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- Log.debug("Pressed 6h button");
- dateTimeSelection = "6h";
- }
- });
- toolStrip.addMember(sixHourButton);
-
- IButton twelveHourButton = new IButton("12h");
- twelveHourButton.setWidth(BUTTON_WIDTH);
- twelveHourButton.setActionType(SelectionType.RADIO);
- twelveHourButton.setRadioGroup(TIMERANGE);
- twelveHourButton.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- Log.debug("Pressed 12h button");
- dateTimeSelection = "12h";
- }
- });
- toolStrip.addMember(twelveHourButton);
-
- IButton oneDayButton = new IButton("1d");
- oneDayButton.setWidth(BUTTON_WIDTH);
- oneDayButton.setActionType(SelectionType.RADIO);
- oneDayButton.setRadioGroup(TIMERANGE);
- oneDayButton.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- Log.debug("Pressed 1d button");
- dateTimeSelection = "1d";
- }
- });
- toolStrip.addMember(oneDayButton);
-
- IButton fiveDayButton = new IButton("5d");
- fiveDayButton.setWidth(BUTTON_WIDTH);
- fiveDayButton.setActionType(SelectionType.RADIO);
- fiveDayButton.setRadioGroup(TIMERANGE);
- fiveDayButton.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- Log.debug("Pressed 5d button");
- dateTimeSelection = "5d";
- }
- });
- toolStrip.addMember(fiveDayButton);
-
- IButton oneMonthButton = new IButton("1m");
- oneMonthButton.setWidth(BUTTON_WIDTH);
- oneMonthButton.setActionType(SelectionType.RADIO);
- oneMonthButton.setRadioGroup(TIMERANGE);
- oneMonthButton.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- Log.debug("Pressed 1m button");
- dateTimeSelection = "1m";
- }
- });
- toolStrip.addMember(oneMonthButton);
-
- IButton threeMonthButton = new IButton("3m");
- threeMonthButton.setWidth(BUTTON_WIDTH);
- threeMonthButton.disable();
- threeMonthButton.setActionType(SelectionType.RADIO);
- threeMonthButton.setRadioGroup(TIMERANGE);
- toolStrip.addMember(threeMonthButton);
-
- IButton oneYearButton = new IButton("1y");
- oneYearButton.setWidth(BUTTON_WIDTH);
- oneYearButton.disable();
- oneYearButton.setActionType(SelectionType.RADIO);
- oneYearButton.setRadioGroup(TIMERANGE);
- toolStrip.addMember(oneYearButton);
+ for(DateTimeButton dateTimeButton : DateTimeButton.values()){
+ IButton oneHourButton = new IButton(dateTimeButton.label);
+ oneHourButton.setWidth(BUTTON_WIDTH);
+ oneHourButton.setActionType(SelectionType.RADIO);
+ oneHourButton.setRadioGroup(TIMERANGE);
+ oneHourButton.addClickHandler(dateTimeButtonBarClickHandler);
+
+ toolStrip.addMember(oneHourButton);
+ }
+
IButton customButton = new IButton("Custom...");
customButton.setWidth(60);
customButton.disable();
customButton.setActionType(SelectionType.RADIO);
customButton.setRadioGroup(TIMERANGE);
- oneMonthButton.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent clickEvent) {
- Log.debug("Pressed custom button");
- dateTimeSelection = "custom";
- }
- });
+ customButton.addClickHandler(dateTimeButtonBarClickHandler);
toolStrip.addMember(customButton);
toolStrip.addSpacer(20);
dateRangeLabel = new Label();
- dateRangeLabel.setContents("Range: ...");
- dateRangeLabel.setWidth(150);
+ updateDateTimeRangeDisplay(new Date(prefs.begin), new Date(prefs.end));
+ dateRangeLabel.setWidth(260);
toolStrip.addMember(dateRangeLabel);
toolStrip.addSpacer(20);
IButton resetZoomButton = new IButton("Reset Manual Zoom");
- resetZoomButton.setWidth(120);
+ resetZoomButton.setWidth(150);
+ resetZoomButton.disable();
toolStrip.addMember(resetZoomButton);
- //@todo: static button factory
-
addMember(toolStrip);
}
- /**
- * Setup the page elements especially the div and svg elements that serve as
- * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
- * Later the drawJsniGraph() is called to actually fill in the div/svg element
- * created here with the actual svg element.
- * NOTE: auxiliary javascript functions in rhq.js
- *
- */
- // public void createDateSliderMarker() {
- // Log.debug("drawGraph marker for: buttonBarDateTimeRangeEditor" );
- //
- // // append the bootstrap buttongroup since smartGWT doesn't have one
- // StringBuilder buttonBarDiv = new StringBuilder();
- // buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
- // "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
- // " <div class=\"accordion-group\">" +
- // " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
- // " <div class=\"accordion-inner\">" +
- // " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
- // " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
- // " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
- // " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
- // " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
- // " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
- // " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
- // " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
- // " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
- // " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
- // " </span>" +
- // " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
- // " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
- // " </div>" +
- // " </div>" +
- // " </div>" +
- // " </div>");
- // HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
- // buttonBarDivFlow.setWidth100();
- // buttonBarDivFlow.setHeight(50);
- // addMember(buttonBarDivFlow);
- // new Timer(){
- // @Override
- // public void run() {
- // attachGraphDateRangeEditorButtonGroupHandlers();
- // }
- // }.schedule(200);
- // }
-
- // public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
- // console.log("Draw GraphDateTimeRangeEditor");
- // var global = this;
- //
- // function updateDateDisplay(startDate, endDate ) {
- // var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- // $wnd.jQuery('#dateRange').text(formattedDateRange);
- // }
- //
- // function saveDateRange(startDate, endDate){
- // var start = startDate | 0, end = endDate | 0;
- // global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::changeDateRange(DD)(start,end);
- // //@todo: fixme
- // //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
- // }
- //
- // var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
- //
- // $wnd.jQuery("#radio1h").bind('click', function (event) {
- // console.log("1h selected");
- // graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radio6h").bind('click', function (event) {
- // console.log(" 6h selected");
- // graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radio12h").bind('click', function (event) {
- // console.log("12h selected");
- // graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radio1d").bind('click', function (event) {
- // console.log("1d selected");
- // graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radio5d").bind('click', function (event) {
- // console.log("5d selected");
- // graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radio1m").bind('click', function (event) {
- // console.log("1m selected");
- // graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radio3m").bind('click', function (event) {
- // console.log("3m selected");
- // graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radio1y").bind('click', function (event) {
- // console.log("1y selected");
- // graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- // $wnd.jQuery("#radioCustom").bind('click', function (event) {
- // console.log("Custom Range selected");
- // graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
- // graphDateContext.endDate = $wnd.moment();
- // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- // });
- //
- //
- // // initially populate with default click
- // $wnd.jQuery("#radio12h").click();
- //
- // }-*/;
- //
- // public native void refreshGraphs() /*-{
- // console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
- // this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::redrawGraphs()();
- // }-*/;
- //
public void redrawGraphs() {
d3GraphListView.redrawGraphs();
@@ -357,10 +133,6 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
//drawJsniChart();
}
- public String getDateTimeSelection() {
- return dateTimeSelection;
- }
-
public Label getDateRangeLabel() {
return dateRangeLabel;
}
@@ -373,18 +145,38 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
return measurementUserPreferences.getMetricRangePreferences().end;
}
+ public Date calculateStartDate(Date endDate, String dateTimeSelection) {
+ long dateTimeOffset = 0;
+ for(DateTimeButton dateTimeButton : DateTimeButton.values()){
+ if(dateTimeButton.label.equals(dateTimeSelection)){
+ dateTimeOffset = dateTimeButton.timeSpanInSeconds * 1000;
+ break;
+ }
+ }
+
+ Log.debug("DateTimeSelection: "+ dateTimeSelection + " = "+ dateTimeOffset);
+ return new Date(endDate.getTime() - dateTimeOffset);
+ }
+
+ public void updateDateTimeRangeDisplay(Date startDate, Date endDate) {
+ String rangeString = fmt.format(startDate) + " - " + fmt.format(endDate);
+ dateRangeLabel.setContents(rangeString);
+
+ }
+
/**
* Whenever we make a change to the date range save it here so it gets propogated to
* the correct places.
+ *
* @param startTime double because JSNI doesnt support long
- * @param endTime double because JSNI doesnt support long
+ * @param endTime double because JSNI doesnt support long
*/
- public void changeDateRange(double startTime, double endTime) {
+ public void saveDateRange(double startTime, double endTime) {
//@todo: uncomment when ready
final boolean advanced = true;
AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences
- .getMetricRangePreferences();
+ .getMetricRangePreferences();
prefs.explicitBeginEnd = advanced;
prefs.begin = (long) startTime;
prefs.end = (long) endTime;
@@ -397,4 +189,48 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
}
+ private class DateTimeButtonBarClickHandler implements ClickHandler {
+
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ IButton button = (IButton) clickEvent.getSource();
+ String selectedDateTimeRange = button.getTitle();
+ Log.info("Button pressed for: " + selectedDateTimeRange);
+ Date calculatedStartDateTime = calculateStartDate(new Date(getEndTime()), selectedDateTimeRange);
+ updateDateTimeRangeDisplay(calculatedStartDateTime, new Date());
+ redrawGraphs();
+ }
+ }
+
+ @SuppressWarnings("GwtInconsistentSerializableClass")
+ private enum DateTimeButton {
+ oneHour( "1h", 60 * 60 ),
+ sixHour( "6h", 6 * 60 * 60 ),
+ twelveHour( "12h", 12 * 60 * 60 ),
+ oneDay("1d", 24 * 60 * 60 ),
+ fiveDay("5d", 5 * 24 * 60 * 60 ),
+ oneMonth("1m", 30 * 24 * 60 * 60 ),
+ threeMonth("3m", 3 * 30 * 24 * 60 * 60 ),
+ oneYear("1y",365 * 24 * 60 * 60 );
+
+ private final String label;
+ private final long timeSpanInSeconds;
+ private final ClickHandler clickHandler;
+
+ DateTimeButton(String label, long timeSpanInSeconds) {
+ this.label = label;
+ this.timeSpanInSeconds = timeSpanInSeconds;
+ this.clickHandler = new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ IButton button = (IButton) clickEvent.getSource();
+ Log.debug("Button pressed for: " + button.getTitle());
+
+ }
+ };
+
+ }
+
+ }
+
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index cfe837b..3317bf6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -581,13 +581,13 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
function brushmove() {
var s = brush.extent();
- updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+// updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
}
function brushend() {
var s = brush.extent();
svg.classed("selecting", !$wnd.d3.event.target.empty());
- updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ //updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
}
function updateDateRangeDisplay(startDate, endDate ) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index 6aaa3f4..b619fab 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -208,7 +208,7 @@ public class ResourceDetailView extends
null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- i monitoringTab.registerSubTabs(monitorTables, metricsTables, monitorNewGraphs, monitorTraits, monitorAvail,
+ monitoringTab.registerSubTabs(monitorTables, metricsTables, monitorNewGraphs, monitorTraits, monitorAvail,
monitorSched, monitorCallTime);
tabs.add(monitoringTab);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 21fcfba..1873dfb 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -47,7 +47,6 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
commit ac63cf537d00d1f95d7599e7ce1859fd1524b02b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Sat Jun 8 10:50:53 2013 -0700
Add MeaseaurementTableView back in and remove bootstrap js classes.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
index 0f92456..b066bad 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
@@ -20,11 +20,9 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
import java.util.Date;
-import com.google.gwt.user.client.Timer;
import com.smartgwt.client.types.SelectionType;
-import com.smartgwt.client.widgets.HTMLFlow;
import com.smartgwt.client.widgets.IButton;
-import com.smartgwt.client.widgets.ImgButton;
+import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.toolbar.ToolStrip;
@@ -45,50 +43,157 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPre
*/
public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
+ static final String TIMERANGE = "timerange";
+ static final int BUTTON_WIDTH = 28;
+
private MeasurementUserPreferences measurementUserPreferences;
private AbstractD3GraphListView d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
-
+ private String dateTimeSelection;
+ private Label dateRangeLabel;
public ButtonBarDateTimeRangeEditor2(MeasurementUserPreferences measurementUserPrefs,
- AbstractD3GraphListView d3GraphListView) {
+ AbstractD3GraphListView d3GraphListView) {
this.measurementUserPreferences = measurementUserPrefs;
this.d3GraphListView = d3GraphListView;
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
- Log.debug("ButtonBarDateTimeRangeEditor initialized with start: "+ prefs.begin +" end: "+prefs.end);
- Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: "+ new Date(prefs.begin) +" end Date: "+new Date(prefs.end));
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences
+ .getMetricRangePreferences();
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start: " + prefs.begin + " end: " + prefs.end);
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: " + new Date(prefs.begin) + " end Date: "
+ + new Date(prefs.end));
createButtons();
}
-
- public void createButtons(){
-
- final String timerange = "timerange";
+ public void createButtons() {
ToolStrip toolStrip = new ToolStrip();
toolStrip.setWidth100();
toolStrip.setHeight(24);
- IButton iButton = new IButton("Hello");
- iButton.setActionType(SelectionType.RADIO);
- iButton.setRadioGroup(timerange);
- toolStrip.addMember(iButton);
-
- ImgButton alignCenterButton = new ImgButton();
- alignCenterButton.setSize(24);
- alignCenterButton.setShowRollOver(false);
- alignCenterButton.setSrc("icons/24/text_align_center.png");
- alignCenterButton.setActionType(SelectionType.RADIO);
- alignCenterButton.setRadioGroup(timerange);
- alignCenterButton.addClickHandler(new ClickHandler() {
+ toolStrip.addSpacer(10);
+
+ IButton oneHourButton = new IButton("1h");
+ oneHourButton.setWidth(BUTTON_WIDTH);
+ oneHourButton.setActionType(SelectionType.RADIO);
+ oneHourButton.setRadioGroup(TIMERANGE);
+ oneHourButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Pressed 1h button");
+ dateTimeSelection = "1h";
+ }
+ });
+ toolStrip.addMember(oneHourButton);
+
+ IButton sixHourButton = new IButton("6h");
+ sixHourButton.setWidth(BUTTON_WIDTH);
+ sixHourButton.setActionType(SelectionType.RADIO);
+ sixHourButton.setRadioGroup(TIMERANGE);
+ sixHourButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Pressed 6h button");
+ dateTimeSelection = "6h";
+ }
+ });
+ toolStrip.addMember(sixHourButton);
+
+ IButton twelveHourButton = new IButton("12h");
+ twelveHourButton.setWidth(BUTTON_WIDTH);
+ twelveHourButton.setActionType(SelectionType.RADIO);
+ twelveHourButton.setRadioGroup(TIMERANGE);
+ twelveHourButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Pressed 12h button");
+ dateTimeSelection = "12h";
+ }
+ });
+ toolStrip.addMember(twelveHourButton);
+
+ IButton oneDayButton = new IButton("1d");
+ oneDayButton.setWidth(BUTTON_WIDTH);
+ oneDayButton.setActionType(SelectionType.RADIO);
+ oneDayButton.setRadioGroup(TIMERANGE);
+ oneDayButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Pressed 1d button");
+ dateTimeSelection = "1d";
+ }
+ });
+ toolStrip.addMember(oneDayButton);
+
+ IButton fiveDayButton = new IButton("5d");
+ fiveDayButton.setWidth(BUTTON_WIDTH);
+ fiveDayButton.setActionType(SelectionType.RADIO);
+ fiveDayButton.setRadioGroup(TIMERANGE);
+ fiveDayButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent clickEvent) {
- Log.debug("Yo");
+ Log.debug("Pressed 5d button");
+ dateTimeSelection = "5d";
}
});
+ toolStrip.addMember(fiveDayButton);
+
+ IButton oneMonthButton = new IButton("1m");
+ oneMonthButton.setWidth(BUTTON_WIDTH);
+ oneMonthButton.setActionType(SelectionType.RADIO);
+ oneMonthButton.setRadioGroup(TIMERANGE);
+ oneMonthButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Pressed 1m button");
+ dateTimeSelection = "1m";
+ }
+ });
+ toolStrip.addMember(oneMonthButton);
+
+ IButton threeMonthButton = new IButton("3m");
+ threeMonthButton.setWidth(BUTTON_WIDTH);
+ threeMonthButton.disable();
+ threeMonthButton.setActionType(SelectionType.RADIO);
+ threeMonthButton.setRadioGroup(TIMERANGE);
+ toolStrip.addMember(threeMonthButton);
+
+ IButton oneYearButton = new IButton("1y");
+ oneYearButton.setWidth(BUTTON_WIDTH);
+ oneYearButton.disable();
+ oneYearButton.setActionType(SelectionType.RADIO);
+ oneYearButton.setRadioGroup(TIMERANGE);
+ toolStrip.addMember(oneYearButton);
+
+ IButton customButton = new IButton("Custom...");
+ customButton.setWidth(60);
+ customButton.disable();
+ customButton.setActionType(SelectionType.RADIO);
+ customButton.setRadioGroup(TIMERANGE);
+ oneMonthButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Pressed custom button");
+ dateTimeSelection = "custom";
+ }
+ });
+ toolStrip.addMember(customButton);
+
+ toolStrip.addSpacer(20);
+
+ dateRangeLabel = new Label();
+ dateRangeLabel.setContents("Range: ...");
+ dateRangeLabel.setWidth(150);
+ toolStrip.addMember(dateRangeLabel);
+
+ toolStrip.addSpacer(20);
+
+ IButton resetZoomButton = new IButton("Reset Manual Zoom");
+ resetZoomButton.setWidth(120);
+ toolStrip.addMember(resetZoomButton);
+
+ //@todo: static button factory
- toolStrip.addMember(alignCenterButton);
addMember(toolStrip);
}
@@ -100,141 +205,140 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
* NOTE: auxiliary javascript functions in rhq.js
*
*/
-// public void createDateSliderMarker() {
-// Log.debug("drawGraph marker for: buttonBarDateTimeRangeEditor" );
-//
-// // append the bootstrap buttongroup since smartGWT doesn't have one
-// StringBuilder buttonBarDiv = new StringBuilder();
-// buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
-// "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
-// " <div class=\"accordion-group\">" +
-// " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
-// " <div class=\"accordion-inner\">" +
-// " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
-// " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
-// " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
-// " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
-// " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
-// " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
-// " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
-// " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
-// " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
-// " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
-// " </span>" +
-// " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
-// " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
-// " </div>" +
-// " </div>" +
-// " </div>" +
-// " </div>");
-// HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
-// buttonBarDivFlow.setWidth100();
-// buttonBarDivFlow.setHeight(50);
-// addMember(buttonBarDivFlow);
-// new Timer(){
-// @Override
-// public void run() {
-// attachGraphDateRangeEditorButtonGroupHandlers();
-// }
-// }.schedule(200);
-// }
-
-// public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
-// console.log("Draw GraphDateTimeRangeEditor");
-// var global = this;
-//
-// function updateDateDisplay(startDate, endDate ) {
-// var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
-// $wnd.jQuery('#dateRange').text(formattedDateRange);
-// }
-//
-// function saveDateRange(startDate, endDate){
-// var start = startDate | 0, end = endDate | 0;
-// global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::changeDateRange(DD)(start,end);
-// //@todo: fixme
-// //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
-// }
-//
-// var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
-//
-// $wnd.jQuery("#radio1h").bind('click', function (event) {
-// console.log("1h selected");
-// graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radio6h").bind('click', function (event) {
-// console.log(" 6h selected");
-// graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radio12h").bind('click', function (event) {
-// console.log("12h selected");
-// graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radio1d").bind('click', function (event) {
-// console.log("1d selected");
-// graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radio5d").bind('click', function (event) {
-// console.log("5d selected");
-// graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radio1m").bind('click', function (event) {
-// console.log("1m selected");
-// graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radio3m").bind('click', function (event) {
-// console.log("3m selected");
-// graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radio1y").bind('click', function (event) {
-// console.log("1y selected");
-// graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-// $wnd.jQuery("#radioCustom").bind('click', function (event) {
-// console.log("Custom Range selected");
-// graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
-// graphDateContext.endDate = $wnd.moment();
-// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
-// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
-// });
-//
-//
-// // initially populate with default click
-// $wnd.jQuery("#radio12h").click();
-//
-// }-*/;
-//
-// public native void refreshGraphs() /*-{
-// console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
-// this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::redrawGraphs()();
-// }-*/;
-//
-
-
- public void redrawGraphs(){
+ // public void createDateSliderMarker() {
+ // Log.debug("drawGraph marker for: buttonBarDateTimeRangeEditor" );
+ //
+ // // append the bootstrap buttongroup since smartGWT doesn't have one
+ // StringBuilder buttonBarDiv = new StringBuilder();
+ // buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
+ // "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
+ // " <div class=\"accordion-group\">" +
+ // " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
+ // " <div class=\"accordion-inner\">" +
+ // " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
+ // " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
+ // " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
+ // " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
+ // " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
+ // " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
+ // " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
+ // " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
+ // " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
+ // " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
+ // " </span>" +
+ // " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
+ // " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
+ // " </div>" +
+ // " </div>" +
+ // " </div>" +
+ // " </div>");
+ // HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
+ // buttonBarDivFlow.setWidth100();
+ // buttonBarDivFlow.setHeight(50);
+ // addMember(buttonBarDivFlow);
+ // new Timer(){
+ // @Override
+ // public void run() {
+ // attachGraphDateRangeEditorButtonGroupHandlers();
+ // }
+ // }.schedule(200);
+ // }
+
+ // public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
+ // console.log("Draw GraphDateTimeRangeEditor");
+ // var global = this;
+ //
+ // function updateDateDisplay(startDate, endDate ) {
+ // var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ // $wnd.jQuery('#dateRange').text(formattedDateRange);
+ // }
+ //
+ // function saveDateRange(startDate, endDate){
+ // var start = startDate | 0, end = endDate | 0;
+ // global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::changeDateRange(DD)(start,end);
+ // //@todo: fixme
+ // //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
+ // }
+ //
+ // var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
+ //
+ // $wnd.jQuery("#radio1h").bind('click', function (event) {
+ // console.log("1h selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radio6h").bind('click', function (event) {
+ // console.log(" 6h selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radio12h").bind('click', function (event) {
+ // console.log("12h selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radio1d").bind('click', function (event) {
+ // console.log("1d selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radio5d").bind('click', function (event) {
+ // console.log("5d selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radio1m").bind('click', function (event) {
+ // console.log("1m selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radio3m").bind('click', function (event) {
+ // console.log("3m selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radio1y").bind('click', function (event) {
+ // console.log("1y selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ // $wnd.jQuery("#radioCustom").bind('click', function (event) {
+ // console.log("Custom Range selected");
+ // graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
+ // graphDateContext.endDate = $wnd.moment();
+ // updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ // saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ // });
+ //
+ //
+ // // initially populate with default click
+ // $wnd.jQuery("#radio12h").click();
+ //
+ // }-*/;
+ //
+ // public native void refreshGraphs() /*-{
+ // console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
+ // this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::redrawGraphs()();
+ // }-*/;
+ //
+
+ public void redrawGraphs() {
d3GraphListView.redrawGraphs();
}
@@ -253,6 +357,13 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
//drawJsniChart();
}
+ public String getDateTimeSelection() {
+ return dateTimeSelection;
+ }
+
+ public Label getDateRangeLabel() {
+ return dateRangeLabel;
+ }
public Long getStartTime() {
return measurementUserPreferences.getMetricRangePreferences().begin;
@@ -261,17 +372,19 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
public Long getEndTime() {
return measurementUserPreferences.getMetricRangePreferences().end;
}
+
/**
* Whenever we make a change to the date range save it here so it gets propogated to
* the correct places.
* @param startTime double because JSNI doesnt support long
* @param endTime double because JSNI doesnt support long
*/
- public void changeDateRange(double startTime, double endTime){
+ public void changeDateRange(double startTime, double endTime) {
//@todo: uncomment when ready
final boolean advanced = true;
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences
+ .getMetricRangePreferences();
prefs.explicitBeginEnd = advanced;
prefs.begin = (long) startTime;
prefs.end = (long) endTime;
@@ -284,6 +397,4 @@ public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
}
-
-
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index ea55c74..6aaa3f4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -69,6 +69,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitorin
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.ResourceAvailabilityView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.schedules.ResourceSchedulesView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MeasurementTableView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MetricsTableView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.traits.TraitsView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.history.ResourceOperationHistoryListView;
@@ -131,6 +132,7 @@ public class ResourceDetailView extends
private SubTab summaryActivity;
private SubTab summaryTimeline;
private SubTab monitorNewGraphs;
+ private SubTab monitorTables;
private SubTab metricsTables;
private SubTab monitorTraits;
private SubTab monitorAvail;
@@ -199,13 +201,14 @@ public class ResourceDetailView extends
monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
+ monitorTables = new SubTab(monitoringTab, new ViewName("Tables", "Tables"), null);
metricsTables = new SubTab(monitoringTab, new ViewName("Metrics", MSG.view_tabs_common_metrics()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
monitorAvail = new SubTab(monitoringTab, new ViewName("Availability", MSG.view_tabs_common_availability()),
null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- monitoringTab.registerSubTabs(metricsTables, monitorNewGraphs, monitorTraits, monitorAvail,
+ i monitoringTab.registerSubTabs(monitorTables, metricsTables, monitorNewGraphs, monitorTraits, monitorAvail,
monitorSched, monitorCallTime);
tabs.add(monitoringTab);
@@ -411,11 +414,17 @@ public class ResourceDetailView extends
viewFactory = (!visible) ? null : new ViewFactory() {
@Override
public Canvas createView() {
- //return new MetricsTableView(resource.getId());
return createD3ConsolidatedGraphListView();
}
};
updateSubTab(this.monitoringTab, this.metricsTables, visible, true, viewFactory);
+ viewFactory = (!visible) ? null : new ViewFactory() {
+ @Override
+ public Canvas createView() {
+ return new MeasurementTableView(resource.getId());
+ }
+ };
+ updateSubTab(this.monitoringTab, this.monitorTables, visible, true, viewFactory);
visible = hasMetricsOfType(this.resourceComposite, DataType.TRAIT);
viewFactory = (!visible) ? null : new ViewFactory() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
index ccd7fb8..52271c5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
@@ -92,7 +92,6 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
destroyMembers();
addMember(buttonBarDateTimeRangeEditor);
- buttonBarDateTimeRangeEditor.createButtons();
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(
new AvailabilityOverUnderGraphType(resource.getId()));
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
new file mode 100644
index 0000000..d47959b
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -0,0 +1,248 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.SelectionStyle;
+import com.smartgwt.client.widgets.Window;
+import com.smartgwt.client.widgets.events.CloseClickEvent;
+import com.smartgwt.client.widgets.events.CloseClickHandler;
+import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
+import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.composite.ResourceComposite;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.FullHTMLPane;
+import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.components.table.Table;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.InventoryView;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.summary.AbstractActivityView.ChartViewWindow;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+
+/**
+ * Views a resource's measurements in a tabular view.
+ * @todo: this is TEMPORARY until the metric view is complete to replace it
+ *
+ * @deprecated
+ * @author John Mazzitelli
+ */
+@Deprecated
+public class MeasurementTableView extends Table<MetricsTableDataSource> {
+
+ private final int resourceId;
+
+ public MeasurementTableView(int resourceId) {
+ super();
+ this.resourceId = resourceId;
+ setDataSource(new MetricsTableDataSource(resourceId));
+ }
+
+ protected void configureTable() {
+ ArrayList<ListGridField> fields = getDataSource().getListGridFields();
+ setListGridFields(fields.toArray(new ListGridField[0]));
+ addExtraWidget(new UserPreferencesMeasurementRangeEditor(), true);
+ addTableAction(MSG.view_measureTable_getLive(), new TableAction() {
+ @Override
+ public boolean isEnabled(ListGridRecord[] selection) {
+ return selection != null && selection.length > 0;
+ }
+
+ @Override
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ if (selection == null || selection.length == 0) {
+ return;
+ }
+ // keyed on metric name - string[0] is the metric label, [1] is the units
+ final HashMap<String, String[]> scheduleNamesAndUnits = new HashMap<String, String[]>();
+ int[] definitionIds = new int[selection.length];
+ int i = 0;
+ for (ListGridRecord record : selection) {
+ Integer defId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_METRIC_DEF_ID);
+ definitionIds[i++] = defId.intValue();
+
+ String name = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_NAME);
+ String label = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_LABEL);
+ String units = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_UNITS);
+ if (units == null || units.length() < 1) {
+ units = MeasurementUnits.NONE.name();
+ }
+
+ scheduleNamesAndUnits.put(name, new String[] { label, units });
+ }
+
+ // actually go out and ask the agents for the data
+ GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId, definitionIds,
+ new AsyncCallback<Set<MeasurementData>>() {
+ @Override
+ public void onSuccess(Set<MeasurementData> result) {
+ if (result == null) {
+ result = new HashSet<MeasurementData>(0);
+ }
+ ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+ for (MeasurementData data : result) {
+ String[] nameAndUnits = scheduleNamesAndUnits.get(data.getName());
+ if (nameAndUnits != null) {
+ double doubleValue;
+ if (data.getValue() instanceof Number) {
+ doubleValue = ((Number) data.getValue()).doubleValue();
+ } else {
+ doubleValue = Double.parseDouble(data.getValue().toString());
+ }
+ String value = MeasurementConverterClient.formatToSignificantPrecision(
+ new double[] { doubleValue }, MeasurementUnits.valueOf(nameAndUnits[1]), true)[0];
+
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute("name", nameAndUnits[0]);
+ record.setAttribute("value", value);
+ records.add(record);
+ }
+ }
+ Collections.sort(records, new Comparator<ListGridRecord>() {
+ public int compare(ListGridRecord o1, ListGridRecord o2) {
+ return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+ }
+ });
+ showLiveData(records);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+ }
+ });
+ }
+ });
+
+
+ addTableAction(MSG.view_measureTable_chartMetricValues(), new TableAction() {
+ @Override
+ public boolean isEnabled(ListGridRecord[] selection) {
+ return selection != null && selection.length > 0;
+ }
+
+ @Override
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ if (selection == null || selection.length == 0) {
+ return;
+ }
+ final TreeSet<Integer> definitionIds = new TreeSet<Integer>();
+ for (ListGridRecord record : selection) {
+ Integer defId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_METRIC_DEF_ID);
+ definitionIds.add(defId);
+ }
+
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterId(resourceId);
+ criteria.fetchSchedules(true);
+ GWTServiceLookup.getResourceService().findResourceCompositesByCriteria(criteria,
+ new AsyncCallback<PageList<ResourceComposite>>() {
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_inventory_resource_loadFailed(String.valueOf(resourceId)),
+ Message.Severity.Warning));
+
+ CoreGUI.goToView(InventoryView.VIEW_ID.getName());
+ }
+
+ @Override
+ public void onSuccess(PageList<ResourceComposite> result) {
+ if (result.isEmpty()) {
+ onFailure(new Exception(MSG.view_inventory_resource_loadFailed(String
+ .valueOf(resourceId))));
+ } else {
+ final ResourceComposite resourceComposite = result.get(0);
+
+ ChartViewWindow window = new ChartViewWindow("");
+ final D3GraphListView graphListView = D3GraphListView.createMultipleGraphs(
+ resourceComposite.getResource(), definitionIds, true);
+ graphListView.addSetButtonClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ graphListView.redrawGraphs();
+ }
+ });
+ window.addItem(graphListView);
+ window.show();
+ refreshTableInfo();
+
+ }
+ }
+ });
+
+ }
+ });
+ }
+
+ private void showLiveData(ArrayList<ListGridRecord> records) {
+ final Window liveDataWindow = new Window();
+ liveDataWindow.setTitle(MSG.view_measureTable_live_title());
+ liveDataWindow.setShowModalMask(true);
+ liveDataWindow.setShowMinimizeButton(false);
+ liveDataWindow.setShowMaximizeButton(true);
+ liveDataWindow.setShowCloseButton(true);
+ liveDataWindow.setShowResizer(true);
+ liveDataWindow.setCanDragResize(true);
+ liveDataWindow.setDismissOnEscape(true);
+ liveDataWindow.setIsModal(true);
+ liveDataWindow.setWidth(700);
+ liveDataWindow.setHeight(425);
+ liveDataWindow.setAutoCenter(true);
+ liveDataWindow.centerInPage();
+ liveDataWindow.addCloseClickHandler(new CloseClickHandler() {
+ @Override
+ public void onCloseClick(CloseClickEvent event) {
+ liveDataWindow.destroy();
+ refreshTableInfo();
+ }
+ });
+
+ ListGrid liveDataGrid = new ListGrid();
+ liveDataGrid.setShowAllRecords(true);
+ liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
+ liveDataGrid.setSelectionType(SelectionStyle.NONE);
+ ListGridField name = new ListGridField("name", MSG.common_title_metric());
+ ListGridField value = new ListGridField("value", MSG.common_title_value());
+ liveDataGrid.setFields(name, value);
+
+ liveDataWindow.addItem(liveDataGrid);
+ liveDataWindow.show();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index f576ca1..24fbe87 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -50,7 +50,6 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
- <script src="/coregui/js/moment.min.js"/>
<script src="/coregui/js/rhq.js"/>
<!-- External javascript libraries -->
<!-- jquery.sparkline requires jquery.
@@ -61,9 +60,6 @@
<script src="/coregui/js/nv.d3.js"/>
<script src="/coregui/js/jquery.tipsy.js"/>
- <!-- for d3 dual slider control only -->
- <script src="/coregui/js/bootstrap.min.js" />
-
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 47700bf..96e50de 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -16,9 +16,6 @@
<link rel="stylesheet" href="css/tipsy.css">
<link rel="stylesheet" href="css/charts.css">
- <!-- for d3 dual slider control -->
- <link rel="stylesheet" href="css/bootstrap.min.css" >
-
<script type="text/javascript">
var search = location.search;
// only do this if you have not specified locale as query param
commit fe44dc75e2f91558e1780ac108f17d87c27f7ef9
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri Jun 7 13:54:16 2013 -0700
Remove live graph D3 chart.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
deleted file mode 100644
index c77b68b..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.Iterator;
-import java.util.Set;
-
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.CloseClickEvent;
-import com.smartgwt.client.widgets.events.CloseClickHandler;
-
-import org.rhq.core.domain.measurement.MeasurementData;
-import org.rhq.core.domain.measurement.MeasurementDataNumeric;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.gwt.MeasurementDataGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.util.BoundedLinkedList;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-
-/**
- * @author Greg Hinkle
- * @author Mike Thompson
- * @deprecated
- */
-@Deprecated
-public class LiveGraphD3View extends EnhancedVLayout {
-
- private static final int MAX_BARS_TO_KEEP = 60;
- private static final int DATA_REFRESH_TIME = 2 * 1000;
- private int resourceId;
- private MeasurementDefinition definition;
- private BoundedLinkedList<MeasurementData> data;
-
- private Timer dataLoaderTimer;
-
- public LiveGraphD3View(int resourceId, MeasurementDefinition def) {
- super();
- this.resourceId = resourceId;
- this.definition = def;
- setHeight100();
- setWidth100();
- // create a sliding window of MAX_BARS_TO_KEEP to live graph
- data = new BoundedLinkedList<MeasurementData>(MAX_BARS_TO_KEEP);
- }
-
- public String getChartId() {
- return resourceId + "-" + definition.getId();
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
-
- for (Canvas c : getChildren()) {
- c.destroy();
- }
-
- drawGraph();
- }
-
- @Override
- protected void onDetach() {
- super.onDetach();
- }
-
- @Override
- protected void onUnload() {
- super.onUnload();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- onDraw();
- }
-
- private void drawGraph() {
-
- if (definition != null) {
-
- HTMLFlow title = new HTMLFlow("<b>" + definition.getDisplayName() + "</b> " + definition.getDescription());
- addMember(title);
-
- }
- HTMLFlow graph = new HTMLFlow("<div id=\"liveChart-" + getChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:100%;\"></svg></div>");
- graph.setWidth100();
- graph.setHeight100();
- addMember(graph);
- loadData();
-
- }
-
- private void loadData() {
- final MeasurementDataGWTServiceAsync dataService = GWTServiceLookup.getMeasurementDataService();
-
- dataLoaderTimer = new Timer() {
- @Override
- public void run() {
- dataService.findLiveData(resourceId, new int[] { definition.getId() },
- new AsyncCallback<Set<MeasurementData>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler()
- .handleError(MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- @Override
- public void onSuccess(Set<MeasurementData> result) {
- Iterator<MeasurementData> i = result.iterator();
- if (!i.hasNext()) {
- return;
- }
-
- MeasurementDataNumeric measurementDataNumeric = (MeasurementDataNumeric) i.next();
- data.addLast(measurementDataNumeric);
-
- drawJsniCharts();
-
- }
- });
- }
- };
-
- dataLoaderTimer.scheduleRepeating(DATA_REFRESH_TIME);
- }
-
- /**
- * Live Graphs are no longer available.
- * @param resourceId
- * @param def
- */
- public static void displayAsDialog(int resourceId, MeasurementDefinition def) {
- final LiveGraphD3View graph = new LiveGraphD3View(resourceId, def);
- final Window graphPopup = new Window();
- graphPopup.setTitle(MSG.view_resource_monitor_detailed_graph_label());
- graphPopup.setWidth(800);
- graphPopup.setHeight(400);
- graphPopup.setIsModal(true);
- graphPopup.setShowModalMask(true);
- graphPopup.setCanDragResize(true);
- graphPopup.centerInPage();
- graphPopup.addItem(graph);
- graphPopup.show();
-
- graphPopup.addCloseClickHandler(new CloseClickHandler() {
- public void onCloseClick(CloseClickEvent closeClientEvent) {
- graphPopup.destroy();
- }
- });
- }
-
- protected void stop() {
- dataLoaderTimer.cancel();
- }
-
- @Override
- protected void onDestroy() {
- stop();
- super.onDestroy();
- }
-
- public String getYAxisTitle() {
- return definition.getName();
- }
-
- public String getYAxisUnits() {
- return definition.getUnits().getName();
- }
-
- public String getXAxisTitle() {
- //@todo: i18n
- return "Time";
- }
-
- public String getJsonMetrics() {
- //Log.debug("getJsonMetrics size: "+data.size());
- StringBuilder sb = new StringBuilder("[");
- for (MeasurementData measurement : data) {
- sb.append("{ x:" + measurement.getTimestamp() + ",");
- sb.append(" y:" + measurement.getValue() + "},");
- }
- sb.setLength(sb.length() - 1); // delete the last ','
- sb.append("]");
- return sb.toString();
- }
-
- public native void drawJsniCharts() /*-{
- var chartId = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getChartId()(),
- chartHandle = "#liveChart-" + chartId,
- chartSelection = chartHandle + " svg",
- yAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getYAxisTitle()(),
- yAxisUnits = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getYAxisUnits()(),
- xAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getXAxisTitle()(),
- json = eval(this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getJsonMetrics()()),
- data = function () {
- return [
- {
- values: json,
- key: yAxisLabel,
- color: '#ff7f0e'
- }
- ];
- };
-
- $wnd.nv.addGraph(function () {
- var chart = $wnd.nv.models.multiBarChart()
- .showControls(false)
- .tooltips(true);
-
- chart.xAxis.axisLabel(xAxisLabel)
- .tickFormat(function (d) {
- return $wnd.d3.time.format('%X')(new Date(d))
- });
-
- chart.yAxis
- .axisLabel(yAxisUnits)
- .tickFormat($wnd.d3.format('.02f'));
-
- $wnd.d3.select(chartSelection)
- .datum(data())
- .transition().duration(100)
- .call(chart);
-
- $wnd.nv.utils.windowResize(chart.update);
-
- return chart;
- });
-
- }-*/;
-}
commit d9cb2cf237f125efc127be7944b6104b132306c8
Merge: 25b0ebf b59d5e6
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri Jun 7 13:07:16 2013 -0700
Merge branch 'master' into mtho11/dual-slider-chart-control
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 5f43d42,0000000..cfe837b
mode 100644,000000..100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@@ -1,691 -1,0 +1,689 @@@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph;
+
+/**
+ * Contains the javascript chart definition for a d3 Stacked Bar graph chart.
+ * The purpose of this class is the fill the div element with id: '#rChart-[resourceId]-[metricId]'.
+ * with SVG instructions to draw a d3 graph (in this case a stacked bar graph).
+ *
+ * @author Mike Thompson
+ */
+public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
+
+ /**
+ * GWT constructor for GWT.create() deferred instantiation.
+ */
+ public StackedBarMetricGraphImpl() {
+ super();
+ }
+
+
+ /**
+ * The magic JSNI to draw the charts with $wnd.d3.js
+ */
+ @Override
+ public native void drawJsniChart() /*-{
+ console.log("Draw Stacked Bar jsni chart");
+ var global = this,
+
+ // create a chartContext object (from rhq.js) with the data required to render to a chart
+ // this same data could be passed to different chart types
+ // This way, we are decoupled from the dependency on globals and JSNI and kept all the java interaction right here.
+ chartContext = new $wnd.ChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHeight()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getJsonMetrics()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getXAxisTitle()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitle()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getYAxisUnits()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitleMinLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitleAvgLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitlePeakLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartDownLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartUnknownLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartNoDataLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverEndLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverPeriodLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::isPortalGraph()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getPortalId()()
+ );
+
+
+ // Define the Stacked Bar Graph function using the module pattern
+ var metricStackedBarGraph = function () {
+ "use strict";
+ // privates
+ var margin = {top: 10, right: 5, bottom: 5, left: 40},
+ width = 750 - margin.left - margin.right,
+ adjustedChartHeight = chartContext.chartHeight - 50,
+ height = adjustedChartHeight - margin.top - margin.bottom,
+ smallChartThresholdInPixels = 600,
+ titleHeight = 30, titleSpace = 10,
+ barOffset = 2,
+ chartData,
+ interpolation = "basis",
- avg, min, peak,
++ avgRaw, avg, minRaw, min, peakRaw, peak,
+ oobMax,
- determineLowBound,
++ legendDefined,
+ lowBound,
+ highBound,
+ calcBarWidth,
+ yScale,
+ yAxis,
+ timeScale,
+ xAxis,
+ chart,
+ svg;
+
+
+ function getChartWidth() {
+ return $wnd.jQuery("#" + chartContext.chartHandle).width();
+ }
+
+ function useSmallCharts() {
+ return getChartWidth() <= smallChartThresholdInPixels;
+ }
+
+ function determineScale() {
+ var xTicks, xTickSubDivide, numberOfBarsForSmallGraph = 20;
+ if (chartContext.data.length > 0) {
+
+ // if window is too small server up small chart
+ if (useSmallCharts()) {
+ console.log("Using Small Charts Profile for width: "+getChartWidth());
+ width = 250;
+ xTicks = 3;
+ xTickSubDivide = 2;
+ chartData = chartContext.data.slice(chartContext.data.length - numberOfBarsForSmallGraph, chartContext.data.length - 1);
+ }
+ else {
+ console.log("Using Large Charts Profile");
+ // we use the width already defined above
+ xTicks = 8;
+ xTickSubDivide = 5;
+ chartData = chartContext.data;
+ }
+
- avg = $wnd.d3.mean(chartContext.data.map(function (d) {
++ avgRaw = chartContext.data.filter(function (d) {
++ if (d.nodata !== 'true') {
++ return d.y;
++ }
++ });
++ avg = $wnd.d3.mean(avgRaw.map(function (d) {
+ return d.y;
+ }));
- peak = $wnd.d3.max(chartContext.data.map(function (d) {
- if (d.high != undefined) {
++ peakRaw = chartContext.data.filter(function (d) {
++ if (d.nodata !== 'true') {
+ return d.high;
+ }
- else {
- return 0;
- }
++ });
++ peak = $wnd.d3.max(peakRaw.map(function (d) {
++ return d.high;
+ }));
- min = $wnd.d3.min(chartContext.data.map(function (d) {
- if (d.low != undefined) {
++ minRaw = chartContext.data.filter(function (d) {
++ if (d.nodata !== 'true') {
+ return d.low;
+ }
- else {
- return Number.MAX_VALUE;
- }
++ });
++ min = $wnd.d3.min(minRaw.map(function (d) {
++ return d.low;
+ }));
- // adjust the min scale so blue low line is not in axis
- determineLowBound = function (min, peak) {
- var newLow = min - ((peak - min) * 0.1);
- if (newLow < 0) {
- return 0;
- }
- else {
- return newLow;
- }
- };
- lowBound = determineLowBound(min, peak);
+ highBound = peak + ((peak - min) * 0.1);
+ oobMax = $wnd.d3.max(chartContext.data.map(function (d) {
+ if (d.baselineMax == undefined) {
+ return 0;
+ }
+ else {
+ return +d.baselineMax;
+ }
+ }));
+ calcBarWidth = function () {
+ return (width / chartData.length - barOffset )
+ };
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
- .domain([lowBound, highBound]);
++ .domain([$wnd.d3.min(chartContext.data, function(d) {return d.low;}),$wnd.d3.max(chartContext.data, function(d) {return d.high;})]);
++
+ yAxis = $wnd.d3.svg.axis()
+ .scale(yScale)
+ .tickSubdivide(1)
+ .ticks(5)
+ .tickSize(4, 4, 0)
+ .orient("left");
+
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain($wnd.d3.extent(chartData, function (d) {
+ return d.x;
+ }));
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(xTicks)
+ .tickSubdivide(xTickSubDivide)
+ .tickSize(4, 4, 0)
+ .orient("bottom");
+
+ // create the actual chart group
+ chart = $wnd.d3.select("#" + chartContext.chartSelection);
+
+ svg = chart.append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top - titleHeight - titleSpace + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + (+titleHeight + titleSpace + margin.top) + ")");
+
- if (!useSmallCharts()) {
++ legendDefined = (typeof min !== "undefined") || (typeof avg !== "undefined") || (typeof peak !== "undefined");
++ if (!useSmallCharts() && legendDefined) {
+ createMinAvgPeakSidePanel(chartContext.minChartTitle, min, chartContext.avgChartTitle, avg, chartContext.peakChartTitle, peak, chartContext.yAxisUnits);
+ }
+ }
+
+ }
+
+
+ function createMinAvgPeakSidePanel(minLabel, minValue, avgLabel, avgValue, highLabel, highValue, uom) {
+ var xLabel = 772,
+ xValue = 820,
+ yBase = 100,
+ yInc = 25,
+ decimalPlaces = 0;
+
+ // title/header
+ chart.append("g").append("rect")
+ .attr("class", "rightSidePanel")
+ .attr("x", xLabel - 10)
+ .attr("y", margin.top + 70)
+ .attr("rx", 10)
+ .attr("ry", 10)
+ .attr("height", 80)
+ .attr("width", 135)
+ .attr("opacity", "0.3")
+ .attr("fill", "#E8E8E8");
+
+ // high
+ chart.append("text")
+ .attr("class", "highLabel")
+ .attr("x", xLabel)
+ .attr("y", yBase)
+ .text(highLabel + " - ");
+
+ chart.append("text")
+ .attr("class", "highText")
+ .attr("x", xValue)
+ .attr("y", yBase)
+ .text(highValue.toFixed(decimalPlaces) + " " + uom);
+
+
+ //avg
+ chart.append("text")
+ .attr("class", "avgLabel")
+ .attr("x", xLabel)
+ .attr("y", yBase + yInc)
+ .text(avgLabel + " - ");
+
+ chart.append("text")
+ .attr("class", "avgText")
+ .attr("x", xValue)
+ .attr("y", yBase + yInc)
+ .text(avgValue.toFixed(decimalPlaces) + " " + uom);
+
+ // min
+ chart.append("text")
+ .attr("class", "minLabel")
+ .attr("x", xLabel)
+ .attr("y", yBase + 2 * yInc)
+ .text(minLabel + " - ");
+
+ chart.append("text")
+ .attr("class", "minText")
+ .attr("x", xValue)
+ .attr("y", yBase + 2 * yInc)
+ .text(minValue.toFixed(decimalPlaces) + " " + uom);
+
+
+ }
+
+ function createHeader(titleName) {
+ var title = chart.append("g").append("rect")
+ .attr("class", "title")
+ .attr("x", 10)
+ .attr("y", margin.top)
+ .attr("height", titleHeight)
+ .attr("width", width + 30 + margin.left)
+ .attr("fill", "none");
+
+ chart.append("text")
+ .attr("class", "titleName")
+ .attr("x", 40)
+ .attr("y", 37)
+ .attr("font-size", "12")
+ .attr("font-weight", "bold")
+ .attr("text-anchor", "left")
+ .text(titleName)
+ .attr("fill", "#003168");
+
+ return title;
+
+ }
+
+ function createStackedBars() {
+
+ var pixelsOffHeight = 0;
+
+ // The gray bars at the bottom leading up
+ svg.selectAll("rect.leaderBar")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "leaderBar")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return yScale(highBound);
+ }
+ else {
+ return yScale(d.low);
+ }
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(highBound) - pixelsOffHeight;
+ }
+ else {
+ return height - yScale(d.low) - pixelsOffHeight;
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return "url(#noDataStripes)";
+ }
+ else {
+ return "#d3d3d6";
+ }
+ });
+
+
+ // upper portion representing avg to high
+ svg.selectAll("rect.high")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "high")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ return isNaN(d.high) ? yScale(lowBound) : yScale(d.high);
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(lowBound);
+ }
+ else {
+ return yScale(d.y) - yScale(d.high);
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+ .attr("data-rhq-value", function (d) {
+ return d.y;
+ })
+ .attr("opacity", 0.9);
+
+
+ // lower portion representing avg to low
+ svg.selectAll("rect.low")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "low")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ return isNaN(d.y) ? height : yScale(d.y);
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(lowBound);
+ }
+ else {
+ return yScale(d.low) - yScale(d.y);
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+ .attr("opacity", 0.9);
+
+ // if high == low put a "cap" on the bar to show non-aggregated bar
+ svg.selectAll("rect.singleValue")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "singleValue")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ return isNaN(d.y) ? height : yScale(d.y) - 2;
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(lowBound);
+ }
+ else {
+ if (d.low === d.high) {
+ return yScale(d.low) - yScale(d.y) + 2;
+ }
+ else {
+ return yScale(d.low) - yScale(d.y);
+ }
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+ .attr("opacity", 0.9)
+ .attr("fill", function (d) {
+ if (d.low === d.high) {
+ return "#50505a";
+ }
+ else {
+ return "#70c4e2";
+ }
+ });
+ }
+
+ function createYAxisGridLines() {
+ // create the y axis grid lines
+ svg.append("g").classed("grid y_grid", true)
+ .call($wnd.d3.svg.axis()
+ .scale(yScale)
+ .orient("left")
+ .ticks(10)
+ .tickSize(-width, 0, 0)
+ .tickFormat("")
+ );
+ }
+
+ function createXandYAxes() {
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+
+ // create y-axis
+ svg.append("g")
+ .attr("class", "y axis")
+ .call(yAxis)
+ .append("text")
+ .attr("transform", "rotate(-90),translate( -60,0)")
+ .attr("y", -30)
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .text(chartContext.yAxisUnits === "NONE" ? "" : chartContext.yAxisUnits);
+
+ }
+
+ function createAvgLines() {
+ var showBarAvgTrendline =
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::showBarAvgTrendLine()(),
+ barAvgLine = $wnd.d3.svg.line()
+ .interpolate("linear")
+ .defined(function (d) {
+ return !d.nodata;
+ })
+ .x(function (d) {
+ return timeScale(d.x) + (calcBarWidth() / 2);
+ })
+ .y(function (d) {
+ if (showBarAvgTrendline) {
+ return yScale(d.y);
+ }
+ else {
+ return NaN;
+ }
+ });
+
+ // Bar avg line
+ svg.append("path")
+ .datum(chartData)
+ .attr("class", "barAvgLine")
+ .attr("fill", "none")
+ .attr("stroke", "#2e376a")
+ .attr("stroke-width", "1.5")
+ .attr("stroke-opacity", ".7")
+ .attr("d", barAvgLine);
+
+ }
+
+ function createOOBLines() {
+
+ var minBaselineLine = $wnd.d3.svg.line()
+ .interpolate(interpolation)
+ .x(function (d) {
+ return timeScale(d.x);
+ })
+ .y(function (d) {
+ return yScale(d.baselineMin);
+ }),
+ maxBaselineLine = $wnd.d3.svg.line()
+ .interpolate(interpolation)
+ .x(function (d) {
+ return timeScale(d.x);
+ })
+ .y(function (d) {
+ return yScale(d.baselineMax);
+ });
+
+ // min baseline Line
+ svg.append("path")
+ .datum(chartData)
+ .attr("class", "minBaselineLine")
+ .attr("fill", "none")
+ .attr("stroke", "purple")
+ .attr("stroke-width", "1")
+ .attr("stroke-dasharray", "20,10,5,5,5,10")
+ .attr("stroke-opacity", ".9")
+ .attr("d", minBaselineLine);
+
+ // max baseline Line
+ svg.append("path")
+ .datum(chartData)
+ .attr("class", "maxBaselineLine")
+ .attr("fill", "none")
+ .attr("stroke", "orange")
+ .attr("stroke-width", "1")
+ .attr("stroke-dasharray", "20,10,5,5,5,10")
+ .attr("stroke-opacity", ".7")
+ .attr("d", maxBaselineLine);
+
+ }
+
+ function createBrush(){
+ // slightly modified but originally from crossfilter (http://square.github.com/crossfilter/)
+ var resizePath = function (d) {
+ var e1 = +(d === "e"),
+ e = e1 ? 1 : 0 ,
+ x = e ? 1 : -1,
+ y = height / 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);
+ },
+ brush = $wnd.d3.svg.brush()
+ .x(timeScale)
+ .extent($wnd.d3.extent(chartData, function (d) {
+ return d.x;
+ }))
+ .on("brushstart", brushstart)
+ .on("brush", brushmove)
+ .on("brushend", brushend),
+ brushg = svg.append("g")
+ .attr("class", "brush")
+ .call(brush);
+
+ brushg.selectAll(".resize").append("path")
+ .attr("d", resizePath);
+
+ brushg.selectAll("rect")
+ .attr("height", height);
+
+ brushstart();
+ brushmove();
+
+ function brushstart() {
+ svg.classed("selecting", true);
+ }
+
+ function brushmove() {
+ var s = brush.extent();
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ }
+
+ function brushend() {
+ var s = brush.extent();
+ svg.classed("selecting", !$wnd.d3.event.target.empty());
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ }
+
+ function updateDateRangeDisplay(startDate, endDate ) {
+ //@todo: i18n the date format
+ var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ $wnd.jQuery('#dateRange').text(formattedDateRange);
+ }
+
+
+ }
+
+ function formatHovers(chartContext, d) {
+ var hoverString,
+ xValue = (d.x == undefined) ? 0 : +d.x,
+ date = new Date(+xValue),
+ barDuration = d.barDuration,
+ timeFormatter = $wnd.d3.time.format(chartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(chartContext.chartHoverDateFormat),
+ highValue = d.high.toFixed(2),
+ lowValue = d.low.toFixed(2),
+ avgValue = d.y.toFixed(2);
+
+
+ // our special condition to indicate no data because avg lines dont like discontinuous data
+ if (d.y === 0 && d.high === 0 && d.low === 0) {
+ // no data
+ hoverString =
+ '<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel" >' + chartContext.timeLabel + ': </span>' + timeFormatter(date) +
+ '<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span>' + dateFormatter(date) + '</div>' +
+ '<hr class="chartHoverDivider" ></hr>' +
+ '<div class="chartHoverAlignRight"><span class="chartHoverLabelSpan">' + chartContext.noDataLabel + '</span></div>' +
+ '</div>';
+
+
+ }
+ else {
+ // regular bar hover
+ hoverString =
+ '<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel">' + chartContext.timeLabel + ': </span><span style="width:50px;">' + timeFormatter(date) + '</span>' +
+ '<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span><span style="width:50px;">' + dateFormatter(date) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span class="chartHoverLabelSpan">' + chartContext.hoverBarLabel + ": " + barDuration + '</span></div>' +
+ '<hr class="chartHoverDivider"></hr>' +
+ '<div class="chartHoverAlignRight"><span id="chartHoverPeakValue" >' + chartContext.peakChartTitle + ': </span><span style="width:50px;">' + highValue + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span id="chartHoverAvgValue" >' + chartContext.avgChartTitle + ': </span><span style="width:50px;">' + avgValue + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span id="chartHoverLowValue" >' + chartContext.minChartTitle + ': </span><span style="width:50px;">' + lowValue + '</span></div>' +
+ '</div>';
+ }
+ return hoverString;
+
+ }
+
+ function createHovers(chartContext) {
+ $wnd.jQuery('svg rect.leaderBar, svg rect.high, svg rect.low, svg rect.singleValue').tipsy({
+ gravity: 'w',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(chartContext, d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ return {
+ // Public API
+ draw: function (chartContext) {
+ "use strict";
+ // Guard condition that can occur when a portlet has not been configured yet
+ if (chartContext.data.length > 0) {
+ console.log("Creating Chart: "+ chartContext.chartSelection + " --> "+ chartContext.chartTitle);
+
+ determineScale();
+ createHeader(chartContext.chartTitle);
+
+ createYAxisGridLines();
+ createStackedBars();
+ createXandYAxes();
+ createAvgLines();
+ if (oobMax > 0) {
+ console.log("OOB Data Exists!");
+ createOOBLines();
+ }
+ createHovers(chartContext);
+ createBrush();
+ }
+ }
+ }; // end public closure
+ }();
+
- metricStackedBarGraph.draw(chartContext);
++ if(chartContext.data !== undefined && chartContext.data.length > 0){
++ metricStackedBarGraph.draw(chartContext);
++ }
+
+ }-*/;
+
+}
commit 25b0ebf9df73f9c81171730f5eca4a39d58ab3e4
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri Jun 7 13:06:42 2013 -0700
Reverting javascript date controls to smartgwt date controls.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index b5e12e9..f6eb007 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -30,6 +30,7 @@ import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.AutoRefreshUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -48,13 +49,13 @@ public abstract class AbstractD3GraphListView extends EnhancedVLayout implements
protected static Label loadingLabel = new Label(MSG.common_msg_loading());
protected MeasurementUserPreferences measurementUserPrefs;
protected boolean showAvailabilityGraph = false;
- protected ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor;
+ protected ButtonBarDateTimeRangeEditor2 buttonBarDateTimeRangeEditor;
protected Timer refreshTimer;
public AbstractD3GraphListView() {
super();
measurementUserPrefs = new MeasurementUserPreferences(UserSessionManager.getUserPreferences());
- buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
+ buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor2(measurementUserPrefs,this);
startRefreshCycle();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 12cbc38..8bbb053 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -19,6 +19,7 @@
package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import com.google.gwt.user.client.Timer;
@@ -39,6 +40,7 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.UserPreferenceName
*
* @author Mike Thompson
*/
+@Deprecated
public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
private MeasurementUserPreferences measurementUserPreferences;
@@ -53,6 +55,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
Log.debug("ButtonBarDateTimeRangeEditor initialized with start: "+ prefs.begin +" end: "+prefs.end);
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: "+ new Date(prefs.begin) +" end Date: "+new Date(prefs.end));
}
/**
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
new file mode 100644
index 0000000..0f92456
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor2.java
@@ -0,0 +1,289 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import java.util.Date;
+
+import com.google.gwt.user.client.Timer;
+import com.smartgwt.client.types.SelectionType;
+import com.smartgwt.client.widgets.HTMLFlow;
+import com.smartgwt.client.widgets.IButton;
+import com.smartgwt.client.widgets.ImgButton;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.toolbar.ToolStrip;
+
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+
+/**
+ * Component to allow selection of Date/Time range for graphs using a button group from bootstrap.
+ *
+ * @author Mike Thompson
+ */
+public class ButtonBarDateTimeRangeEditor2 extends EnhancedVLayout {
+
+ private MeasurementUserPreferences measurementUserPreferences;
+ private AbstractD3GraphListView d3GraphListView;
+ private static final Messages MSG = CoreGUI.getMessages();
+
+
+ public ButtonBarDateTimeRangeEditor2(MeasurementUserPreferences measurementUserPrefs,
+ AbstractD3GraphListView d3GraphListView) {
+ this.measurementUserPreferences = measurementUserPrefs;
+ this.d3GraphListView = d3GraphListView;
+
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start: "+ prefs.begin +" end: "+prefs.end);
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start Date: "+ new Date(prefs.begin) +" end Date: "+new Date(prefs.end));
+ createButtons();
+ }
+
+
+ public void createButtons(){
+
+ final String timerange = "timerange";
+
+ ToolStrip toolStrip = new ToolStrip();
+ toolStrip.setWidth100();
+ toolStrip.setHeight(24);
+
+ IButton iButton = new IButton("Hello");
+ iButton.setActionType(SelectionType.RADIO);
+ iButton.setRadioGroup(timerange);
+ toolStrip.addMember(iButton);
+
+ ImgButton alignCenterButton = new ImgButton();
+ alignCenterButton.setSize(24);
+ alignCenterButton.setShowRollOver(false);
+ alignCenterButton.setSrc("icons/24/text_align_center.png");
+ alignCenterButton.setActionType(SelectionType.RADIO);
+ alignCenterButton.setRadioGroup(timerange);
+ alignCenterButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent clickEvent) {
+ Log.debug("Yo");
+ }
+ });
+
+ toolStrip.addMember(alignCenterButton);
+ addMember(toolStrip);
+ }
+
+ /**
+ * Setup the page elements especially the div and svg elements that serve as
+ * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
+ * Later the drawJsniGraph() is called to actually fill in the div/svg element
+ * created here with the actual svg element.
+ * NOTE: auxiliary javascript functions in rhq.js
+ *
+ */
+// public void createDateSliderMarker() {
+// Log.debug("drawGraph marker for: buttonBarDateTimeRangeEditor" );
+//
+// // append the bootstrap buttongroup since smartGWT doesn't have one
+// StringBuilder buttonBarDiv = new StringBuilder();
+// buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
+// "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
+// " <div class=\"accordion-group\">" +
+// " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
+// " <div class=\"accordion-inner\">" +
+// " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
+// " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
+// " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
+// " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
+// " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
+// " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
+// " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
+// " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
+// " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
+// " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
+// " </span>" +
+// " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
+// " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
+// " </div>" +
+// " </div>" +
+// " </div>" +
+// " </div>");
+// HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
+// buttonBarDivFlow.setWidth100();
+// buttonBarDivFlow.setHeight(50);
+// addMember(buttonBarDivFlow);
+// new Timer(){
+// @Override
+// public void run() {
+// attachGraphDateRangeEditorButtonGroupHandlers();
+// }
+// }.schedule(200);
+// }
+
+// public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
+// console.log("Draw GraphDateTimeRangeEditor");
+// var global = this;
+//
+// function updateDateDisplay(startDate, endDate ) {
+// var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+// $wnd.jQuery('#dateRange').text(formattedDateRange);
+// }
+//
+// function saveDateRange(startDate, endDate){
+// var start = startDate | 0, end = endDate | 0;
+// global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::changeDateRange(DD)(start,end);
+// //@todo: fixme
+// //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
+// }
+//
+// var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
+//
+// $wnd.jQuery("#radio1h").bind('click', function (event) {
+// console.log("1h selected");
+// graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radio6h").bind('click', function (event) {
+// console.log(" 6h selected");
+// graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radio12h").bind('click', function (event) {
+// console.log("12h selected");
+// graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radio1d").bind('click', function (event) {
+// console.log("1d selected");
+// graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radio5d").bind('click', function (event) {
+// console.log("5d selected");
+// graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radio1m").bind('click', function (event) {
+// console.log("1m selected");
+// graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radio3m").bind('click', function (event) {
+// console.log("3m selected");
+// graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radio1y").bind('click', function (event) {
+// console.log("1y selected");
+// graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+// $wnd.jQuery("#radioCustom").bind('click', function (event) {
+// console.log("Custom Range selected");
+// graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
+// graphDateContext.endDate = $wnd.moment();
+// updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+// saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+// });
+//
+//
+// // initially populate with default click
+// $wnd.jQuery("#radio12h").click();
+//
+// }-*/;
+//
+// public native void refreshGraphs() /*-{
+// console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
+// this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2::redrawGraphs()();
+// }-*/;
+//
+
+
+ public void redrawGraphs(){
+ d3GraphListView.redrawGraphs();
+ }
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ removeMembers(getMembers());
+ createButtons();
+ }
+
+ @Override
+ public void parentResized() {
+ super.parentResized();
+ removeMembers(getMembers());
+ createButtons();
+ //drawJsniChart();
+ }
+
+
+ public Long getStartTime() {
+ return measurementUserPreferences.getMetricRangePreferences().begin;
+ }
+
+ public Long getEndTime() {
+ return measurementUserPreferences.getMetricRangePreferences().end;
+ }
+ /**
+ * Whenever we make a change to the date range save it here so it gets propogated to
+ * the correct places.
+ * @param startTime double because JSNI doesnt support long
+ * @param endTime double because JSNI doesnt support long
+ */
+ public void changeDateRange(double startTime, double endTime){
+
+ //@todo: uncomment when ready
+ final boolean advanced = true;
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+ prefs.explicitBeginEnd = advanced;
+ prefs.begin = (long) startTime;
+ prefs.end = (long) endTime;
+ ///prefs.setPreference(PREF_METRIC_RANGE, Arrays.asList(prefs.begin, prefs.end));
+ if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
+ CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
+ } else {
+ measurementUserPreferences.setMetricRangePreferences(prefs);
+ }
+
+ }
+
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index fc5f4bb..ea55c74 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -262,8 +262,7 @@ public class ResourceDetailView extends
}
protected D3GraphListView createD3ConsolidatedGraphListView() {
- //@todo: remove hard coding
- graphListView = D3ConsolidatedGraphListView.createSparklineGraphs(resourceComposite.getResource(), 1001);
+ graphListView = D3ConsolidatedGraphListView.createSparklineGraphs(resourceComposite.getResource());
return graphListView;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
index 6c98987..ccd7fb8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
@@ -30,7 +30,6 @@ import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.layout.VLayout;
import org.rhq.core.domain.common.EntityContext;
@@ -45,7 +44,6 @@ import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
@@ -75,38 +73,8 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
private VLayout vLayout;
private MetricsTableView metricsTableView;
-// public static D3ConsolidatedGraphListView createMultipleGraphs(Resource resource, Set<Integer> definitionIds,
-// boolean showAvailabilityGraph) {
-//
-// return new D3ConsolidatedGraphListView(resource, definitionIds, showAvailabilityGraph);
-// }
-//
-// public static D3ConsolidatedGraphListView createSummaryMultipleGraphs(Resource resource, boolean monitorDetailView) {
-// return new D3ConsolidatedGraphListView(resource, monitorDetailView);
-// }
-//
- public static D3ConsolidatedGraphListView createSingleGraph(Resource resource, Integer measurementId,
- boolean showAvailabilityGraph) {
- TreeSet<Integer> definitionIds = new TreeSet<Integer>();
- definitionIds.add(measurementId);
- return new D3ConsolidatedGraphListView(resource, definitionIds, showAvailabilityGraph);
-
- }
-//
-// public static D3ConsolidatedGraphListView createSingleGraphNoAvail(Resource resource, Integer measurementId) {
-// return D3ConsolidatedGraphListView.createSingleGraph(resource, measurementId, false);
-// }
-
- public static D3ConsolidatedGraphListView createSparklineGraphs(Resource resource, Integer measurementId) {
- return D3ConsolidatedGraphListView.createSingleGraph(resource, measurementId, false);
- }
-
- private D3ConsolidatedGraphListView(Resource resource, Set<Integer> definitionIds, boolean showAvailabilityGraph) {
- super(resource, definitionIds,showAvailabilityGraph);
- this.resource = resource;
- //commonConstructorSettings();
- this.definitionIds = definitionIds;
- this.showAvailabilityGraph = showAvailabilityGraph;
+ public static D3ConsolidatedGraphListView createSparklineGraphs(Resource resource) {
+ return new D3ConsolidatedGraphListView(resource, true);
}
private D3ConsolidatedGraphListView(Resource resource, boolean showAvailabilityGraph) {
@@ -117,17 +85,6 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
useSummaryData = true;
}
-// private void commonConstructorSettings() {
-// buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
-// setOverflow(Overflow.HIDDEN);
-// }
-
- @Deprecated
- public void addSetButtonClickHandler(ClickHandler clickHandler) {
- Log.debug("measurementRangeEditor " + buttonBarDateTimeRangeEditor);
- // graphDateTimeRangeEditor.getSetButton().addClickHandler(clickHandler);
- }
-
@Override
protected void onDraw() {
super.onDraw();
@@ -135,14 +92,14 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
destroyMembers();
addMember(buttonBarDateTimeRangeEditor);
- buttonBarDateTimeRangeEditor.createDateSliderMarker();
-
- availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resource.getId()));
- // first step in 2 step to create d3 chart
- // create a placeholder for avail graph
- availabilityGraph.createGraphMarker();
- addMember(availabilityGraph);
+ buttonBarDateTimeRangeEditor.createButtons();
+ availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(
+ new AvailabilityOverUnderGraphType(resource.getId()));
+ // first step in 2 step to create d3 chart
+ // create a placeholder for avail graph
+ availabilityGraph.createGraphMarker();
+ addMember(availabilityGraph);
vLayout = new VLayout();
vLayout.setOverflow(Overflow.AUTO);
@@ -159,7 +116,7 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
public void redrawGraphs() {
this.onDraw();
- availabilityGraph.drawJsniChart();
+ availabilityGraph.drawJsniChart();
}
@Override
@@ -181,8 +138,8 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
@Override
public void onSuccess(List<Availability> availList) {
- Log.debug("\nSuccessfully queried availability in: "
- + (System.currentTimeMillis() - timerStart) + " ms.");
+ Log.debug("\nSuccessfully queried availability in: " + (System.currentTimeMillis() - timerStart)
+ + " ms.");
availabilityList = availList;
if (countDownLatch != null) {
countDownLatch.countDown();
@@ -198,7 +155,7 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
private void queryAndBuildGraphs() {
final long startTimer = System.currentTimeMillis();
- if(null != availabilityGraph){
+ if (null != availabilityGraph) {
queryAvailability(EntityContext.forResource(resource.getId()), buttonBarDateTimeRangeEditor.getStartTime(),
buttonBarDateTimeRangeEditor.getEndTime(), null);
}
@@ -261,7 +218,7 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
// we only need the first metricData since we are only taking the
// availability data set in there for the dropdowns already
availabilityGraph.setAvailabilityList(availabilityList);
- new Timer(){
+ new Timer() {
/**
* This method will be called when a timer fires. Override it to implement the timer's logic.
*/
@@ -284,7 +241,7 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
private void queryMetricData(final int[] measDefIdArray, final CountDownLatch countDownLatch) {
GWTServiceLookup.getMeasurementDataService().findDataForResource(resource.getId(), measDefIdArray,
- buttonBarDateTimeRangeEditor.getStartTime(), buttonBarDateTimeRangeEditor.getEndTime(), 60,
+ buttonBarDateTimeRangeEditor.getStartTime(), buttonBarDateTimeRangeEditor.getEndTime(), 60,
new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
@Override
public void onFailure(Throwable caught) {
@@ -316,8 +273,8 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
public void onSuccess(PageList<MeasurementOOBComposite> measurementOOBComposites) {
measurementOOBCompositeList = measurementOOBComposites;
- Log.debug("\nSuccessfully queried "+measurementOOBCompositeList.size() +" OOB records in: " + (System.currentTimeMillis() - startTime)
- + " ms.");
+ Log.debug("\nSuccessfully queried " + measurementOOBCompositeList.size()
+ + " OOB records in: " + (System.currentTimeMillis() - startTime) + " ms.");
countDownLatch.countDown();
}
@@ -369,11 +326,13 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
if (null != selectedDefinitionId) {
// single graph case
if (measurementId == selectedDefinitionId) {
- buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric, SINGLE_CHART_HEIGHT);
+ buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric,
+ SINGLE_CHART_HEIGHT);
}
} else {
// multiple graph case
- buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric, MULTI_CHART_HEIGHT);
+ buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric,
+ MULTI_CHART_HEIGHT);
}
}
i++;
@@ -387,7 +346,7 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
MeasurementDefinition measurementDefinition, List<MeasurementDataNumericHighLowComposite> data, int height) {
MetricGraphData metricGraphData = MetricGraphData.createForResource(resource.getId(), resource.getName(),
- measurementDefinition, data, measurementOOBCompositeList );
+ measurementDefinition, data, measurementOOBCompositeList);
StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
graph.setMetricGraphData(metricGraphData);
MetricD3Graph graphView = new MetricD3Graph(graph);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index e9ab04a..21fcfba 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -45,6 +45,7 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor2;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
@@ -112,7 +113,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
}
private void commonConstructorSettings() {
- buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
+ buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor2(measurementUserPrefs,this);
setOverflow(Overflow.HIDDEN);
}
@@ -125,11 +126,11 @@ public class D3GraphListView extends AbstractD3GraphListView {
@Override
protected void onDraw() {
super.onDraw();
- Log.debug("D3GraphListView.onDraw() for: " + resource.getName());
+ Log.debug("D3GraphListView.onDraw() for: " + resource.getName()+ " id: "+ resource.getId());
destroyMembers();
addMember(buttonBarDateTimeRangeEditor);
- buttonBarDateTimeRangeEditor.createDateSliderMarker();
+ buttonBarDateTimeRangeEditor.createButtons();
if (showAvailabilityGraph) {
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resource.getId()));
commit 39ed437f447519e2424d7b5d4c0c88537a1ba778
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jun 6 16:53:02 2013 -0700
Saving date ranges for graphs to user preferences.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
index 3957d9f..12cbc38 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -18,6 +18,7 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+import java.util.Arrays;
import java.util.List;
import com.google.gwt.user.client.Timer;
@@ -29,7 +30,9 @@ import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeas
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.UserPreferenceNames;
/**
* Component to allow selection of Date/Time range for graphs using a button group from bootstrap.
@@ -41,8 +44,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
private MeasurementUserPreferences measurementUserPreferences;
private AbstractD3GraphListView d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
- private Long startDateTime;
- private Long endDateTime;
public ButtonBarDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
@@ -50,13 +51,8 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
this.measurementUserPreferences = measurementUserPrefs;
this.d3GraphListView = d3GraphListView;
-
AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
-
- // initialize with saved begin/end times
- List<Long> beginEndTimes = prefs.getBeginEndTimes();
- startDateTime = beginEndTimes.get(0);
- endDateTime = beginEndTimes.get(1);
+ Log.debug("ButtonBarDateTimeRangeEditor initialized with start: "+ prefs.begin +" end: "+prefs.end);
}
/**
@@ -68,7 +64,7 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
*
*/
public void createDateSliderMarker() {
- Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
+ Log.debug("drawGraph marker for: buttonBarDateTimeRangeEditor" );
// append the bootstrap buttongroup since smartGWT doesn't have one
StringBuilder buttonBarDiv = new StringBuilder();
@@ -101,8 +97,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
new Timer(){
@Override
public void run() {
- changeDateRange(getStartTime(), getEndTime());
- //drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
attachGraphDateRangeEditorButtonGroupHandlers();
}
}.schedule(200);
@@ -132,7 +126,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radio6h").bind('click', function (event) {
console.log(" 6h selected");
@@ -140,7 +133,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radio12h").bind('click', function (event) {
console.log("12h selected");
@@ -148,7 +140,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radio1d").bind('click', function (event) {
console.log("1d selected");
@@ -156,7 +147,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radio5d").bind('click', function (event) {
console.log("5d selected");
@@ -164,7 +154,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radio1m").bind('click', function (event) {
console.log("1m selected");
@@ -172,7 +161,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radio3m").bind('click', function (event) {
console.log("3m selected");
@@ -180,7 +168,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radio1y").bind('click', function (event) {
console.log("1y selected");
@@ -188,7 +175,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioCustom").bind('click', function (event) {
console.log("Custom Range selected");
@@ -196,7 +182,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
@@ -211,13 +196,6 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
}-*/;
-// public void drawJsniDateSlider(){
-// dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
-// }
-//
-// public void drawJsniDateSlider(Long startTime, Long endTime){
-// dateSliderGraphType.drawJsniChart(startTime, endTime);
-// }
public void redrawGraphs(){
d3GraphListView.redrawGraphs();
@@ -254,20 +232,18 @@ public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
*/
public void changeDateRange(double startTime, double endTime){
- startDateTime = (long)startTime;
- endDateTime = (long)endTime;
-
//@todo: uncomment when ready
-// final boolean advanced = true;
-// AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
-// prefs.explicitBeginEnd = advanced;
-// prefs.begin = (long) startTime;
-// prefs.end = (long) endTime;
-// if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
-// CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
-// } else {
-// measurementUserPreferences.setMetricRangePreferences(prefs);
-// }
+ final boolean advanced = true;
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+ prefs.explicitBeginEnd = advanced;
+ prefs.begin = (long) startTime;
+ prefs.end = (long) endTime;
+ ///prefs.setPreference(PREF_METRIC_RANGE, Arrays.asList(prefs.begin, prefs.end));
+ if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
+ CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
+ } else {
+ measurementUserPreferences.setMetricRangePreferences(prefs);
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index ad26edc..5f43d42 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -678,7 +678,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
createOOBLines();
}
createHovers(chartContext);
- //createBrush();
+ createBrush();
}
}
}; // end public closure
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
index f9c3790..6c98987 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
@@ -246,7 +246,7 @@ public class D3ConsolidatedGraphListView extends D3GraphListView {
public void execute() {
Log.debug("Total Time for async metrics/avail query: "
+ (System.currentTimeMillis() - startTimer));
- if (metricsDataList.isEmpty()) {
+ if (null == metricsDataList || metricsDataList.isEmpty()) {
loadingLabel.setContents(MSG.view_resource_monitor_graphs_noneAvailable());
} else {
loadingLabel.hide();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 40316af..e9ab04a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -242,7 +242,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
public void execute() {
Log.debug("Total Time for async metrics/avail query: "
+ (System.currentTimeMillis() - startTimer));
- if (metricsDataList.isEmpty()) {
+ if (null == metricsDataList || metricsDataList.isEmpty()) {
loadingLabel.setContents(MSG.view_resource_monitor_graphs_noneAvailable());
} else {
loadingLabel.hide();
commit 3410a2f56d3285bc75ed3ca5e0d3f87668a644d0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jun 6 13:09:50 2013 -0700
Get availability working in new Consolidated metrics view.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index be4409a..fc5f4bb 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -65,6 +65,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.PluginConfigurationHistoryListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.ResourceAgentView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.CalltimeView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3ConsolidatedGraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.ResourceAvailabilityView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.schedules.ResourceSchedulesView;
@@ -260,6 +261,12 @@ public class ResourceDetailView extends
return graphListView;
}
+ protected D3GraphListView createD3ConsolidatedGraphListView() {
+ //@todo: remove hard coding
+ graphListView = D3ConsolidatedGraphListView.createSparklineGraphs(resourceComposite.getResource(), 1001);
+ return graphListView;
+ }
+
@Override
protected void updateTabContent(ResourceComposite resourceComposite, boolean isRefresh) {
super.updateTabContent(resourceComposite, isRefresh);
@@ -405,7 +412,8 @@ public class ResourceDetailView extends
viewFactory = (!visible) ? null : new ViewFactory() {
@Override
public Canvas createView() {
- return new MetricsTableView(resource.getId());
+ //return new MetricsTableView(resource.getId());
+ return createD3ConsolidatedGraphListView();
}
};
updateSubTab(this.monitoringTab, this.metricsTables, visible, true, viewFactory);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
new file mode 100644
index 0000000..f9c3790
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3ConsolidatedGraphListView.java
@@ -0,0 +1,401 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.Overflow;
+import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+import org.rhq.core.domain.common.EntityContext;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
+import org.rhq.core.domain.measurement.composite.MeasurementOOBComposite;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MetricsTableView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.async.Command;
+import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
+
+/**
+ * Build the View that shows the individual graph views for multi-graph
+ * views if just a resource is provided and single graph view if resource
+ * and measurement definitionId are provided.
+ *
+ * @author Mike Thompson
+ */
+public class D3ConsolidatedGraphListView extends D3GraphListView {
+
+ private static int NUM_ASYNC_CALLS = 2; // wait for X async calls in Latch
+
+ private Resource resource;
+ private Set<Integer> definitionIds = null;
+ private boolean useSummaryData = false;
+ private PageList<MeasurementOOBComposite> measurementOOBCompositeList;
+ private List<List<MeasurementDataNumericHighLowComposite>> metricsDataList;
+ private VLayout vLayout;
+ private MetricsTableView metricsTableView;
+
+// public static D3ConsolidatedGraphListView createMultipleGraphs(Resource resource, Set<Integer> definitionIds,
+// boolean showAvailabilityGraph) {
+//
+// return new D3ConsolidatedGraphListView(resource, definitionIds, showAvailabilityGraph);
+// }
+//
+// public static D3ConsolidatedGraphListView createSummaryMultipleGraphs(Resource resource, boolean monitorDetailView) {
+// return new D3ConsolidatedGraphListView(resource, monitorDetailView);
+// }
+//
+ public static D3ConsolidatedGraphListView createSingleGraph(Resource resource, Integer measurementId,
+ boolean showAvailabilityGraph) {
+ TreeSet<Integer> definitionIds = new TreeSet<Integer>();
+ definitionIds.add(measurementId);
+ return new D3ConsolidatedGraphListView(resource, definitionIds, showAvailabilityGraph);
+
+ }
+//
+// public static D3ConsolidatedGraphListView createSingleGraphNoAvail(Resource resource, Integer measurementId) {
+// return D3ConsolidatedGraphListView.createSingleGraph(resource, measurementId, false);
+// }
+
+ public static D3ConsolidatedGraphListView createSparklineGraphs(Resource resource, Integer measurementId) {
+ return D3ConsolidatedGraphListView.createSingleGraph(resource, measurementId, false);
+ }
+
+ private D3ConsolidatedGraphListView(Resource resource, Set<Integer> definitionIds, boolean showAvailabilityGraph) {
+ super(resource, definitionIds,showAvailabilityGraph);
+ this.resource = resource;
+ //commonConstructorSettings();
+ this.definitionIds = definitionIds;
+ this.showAvailabilityGraph = showAvailabilityGraph;
+ }
+
+ private D3ConsolidatedGraphListView(Resource resource, boolean showAvailabilityGraph) {
+ super(resource, showAvailabilityGraph);
+ this.resource = resource;
+ this.showAvailabilityGraph = showAvailabilityGraph;
+ //commonConstructorSettings();
+ useSummaryData = true;
+ }
+
+// private void commonConstructorSettings() {
+// buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
+// setOverflow(Overflow.HIDDEN);
+// }
+
+ @Deprecated
+ public void addSetButtonClickHandler(ClickHandler clickHandler) {
+ Log.debug("measurementRangeEditor " + buttonBarDateTimeRangeEditor);
+ // graphDateTimeRangeEditor.getSetButton().addClickHandler(clickHandler);
+ }
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ Log.debug("D3ConsolidatedGraphListView.onDraw() for: " + resource.getName());
+ destroyMembers();
+
+ addMember(buttonBarDateTimeRangeEditor);
+ buttonBarDateTimeRangeEditor.createDateSliderMarker();
+
+ availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resource.getId()));
+ // first step in 2 step to create d3 chart
+ // create a placeholder for avail graph
+ availabilityGraph.createGraphMarker();
+ addMember(availabilityGraph);
+
+
+ vLayout = new VLayout();
+ vLayout.setOverflow(Overflow.AUTO);
+ vLayout.setWidth100();
+ vLayout.setHeight100();
+
+ if (resource != null) {
+ queryAndBuildGraphs();
+ metricsTableView = new MetricsTableView(resource.getId());
+ vLayout.addMember(metricsTableView);
+ }
+ addMember(vLayout);
+ }
+
+ public void redrawGraphs() {
+ this.onDraw();
+ availabilityGraph.drawJsniChart();
+ }
+
+ @Override
+ protected void queryAvailability(final EntityContext context, Long startTime, Long endTime,
+ final CountDownLatch countDownLatch) {
+
+ final long timerStart = System.currentTimeMillis();
+
+ // now return the availability
+ GWTServiceLookup.getAvailabilityService().getAvailabilitiesForResource(context.getResourceId(), startTime,
+ endTime, new AsyncCallback<List<Availability>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_availability_loadFailed(), caught);
+ if (countDownLatch != null) {
+ countDownLatch.countDown();
+ }
+ }
+
+ @Override
+ public void onSuccess(List<Availability> availList) {
+ Log.debug("\nSuccessfully queried availability in: "
+ + (System.currentTimeMillis() - timerStart) + " ms.");
+ availabilityList = availList;
+ if (countDownLatch != null) {
+ countDownLatch.countDown();
+ }
+ }
+ });
+ }
+
+ /**
+ * Build whatever graph (summary or not) by grabbing the MeasurementDefinitions
+ * that are defined for the resource and then querying the metric and availability data.
+ */
+ private void queryAndBuildGraphs() {
+ final long startTimer = System.currentTimeMillis();
+
+ if(null != availabilityGraph){
+ queryAvailability(EntityContext.forResource(resource.getId()), buttonBarDateTimeRangeEditor.getStartTime(),
+ buttonBarDateTimeRangeEditor.getEndTime(), null);
+ }
+
+ ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(),
+ EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
+ new ResourceTypeRepository.TypeLoadedCallback() {
+ public void onTypesLoaded(final ResourceType type) {
+
+ final ArrayList<MeasurementDefinition> measurementDefinitions = new ArrayList<MeasurementDefinition>();
+ final ArrayList<MeasurementDefinition> summaryMeasurementDefinitions = new ArrayList<MeasurementDefinition>();
+
+ for (MeasurementDefinition def : type.getMetricDefinitions()) {
+ if (def.getDataType() == DataType.MEASUREMENT && def.getDisplayType() == DisplayType.SUMMARY) {
+ summaryMeasurementDefinitions.add(def);
+ }
+ measurementDefinitions.add(def);
+ }
+
+ Collections.sort(measurementDefinitions, new Comparator<MeasurementDefinition>() {
+ @Override
+ public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
+ return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder());
+ }
+ });
+ Collections.sort(summaryMeasurementDefinitions, new Comparator<MeasurementDefinition>() {
+ @Override
+ public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
+ return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder());
+ }
+ });
+
+ int[] measDefIdArray = new int[measurementDefinitions.size()];
+ for (int i = 0; i < measDefIdArray.length; i++) {
+ measDefIdArray[i] = measurementDefinitions.get(i).getId();
+ }
+
+ // setting up a deferred Command to execute after all resource queries have completed (successfully or unsuccessfully)
+ // we know there are exactly 2 resources
+ final CountDownLatch countDownLatch = CountDownLatch.create(NUM_ASYNC_CALLS, new Command() {
+ @Override
+ /**
+ * Satisfied only after ALL of the metric queries AND availability have completed
+ */
+ public void execute() {
+ Log.debug("Total Time for async metrics/avail query: "
+ + (System.currentTimeMillis() - startTimer));
+ if (metricsDataList.isEmpty()) {
+ loadingLabel.setContents(MSG.view_resource_monitor_graphs_noneAvailable());
+ } else {
+ loadingLabel.hide();
+ if (useSummaryData) {
+ buildSummaryGraphs(metricsDataList, summaryMeasurementDefinitions,
+ measurementDefinitions);
+ } else {
+ determineGraphsToBuild(metricsDataList, measurementDefinitions, definitionIds);
+ }
+ // There is a weird timing case when availabilityGraph can be null
+ if (null != availabilityGraph) {
+ // we only need the first metricData since we are only taking the
+ // availability data set in there for the dropdowns already
+ availabilityGraph.setAvailabilityList(availabilityList);
+ new Timer(){
+ /**
+ * This method will be called when a timer fires. Override it to implement the timer's logic.
+ */
+ @Override
+ public void run() {
+ availabilityGraph.drawJsniChart();
+ }
+ }.schedule(200);
+ }
+ }
+
+ }
+ });
+
+ queryMetricData(measDefIdArray, countDownLatch);
+ queryOOBMetrics(resource, countDownLatch);
+ // now the countDown latch will run sometime asynchronously
+
+ }
+
+ private void queryMetricData(final int[] measDefIdArray, final CountDownLatch countDownLatch) {
+ GWTServiceLookup.getMeasurementDataService().findDataForResource(resource.getId(), measDefIdArray,
+ buttonBarDateTimeRangeEditor.getStartTime(), buttonBarDateTimeRangeEditor.getEndTime(), 60,
+ new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_loadFailed(),
+ caught);
+ loadingLabel.setContents(MSG.view_resource_monitor_graphs_loadFailed());
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> metrics) {
+ metricsDataList = metrics;
+ Log.debug("Regular Metric graph data queried in: "
+ + (System.currentTimeMillis() - startTimer + " ms."));
+ countDownLatch.countDown();
+
+ }
+ });
+ }
+
+ private void queryOOBMetrics(final Resource resource, final CountDownLatch countDownLatch) {
+
+ final long startTime = System.currentTimeMillis();
+
+ GWTServiceLookup.getMeasurementDataService().getHighestNOOBsForResource(resource.getId(), 60,
+
+ new AsyncCallback<PageList<MeasurementOOBComposite>>() {
+ @Override
+ public void onSuccess(PageList<MeasurementOOBComposite> measurementOOBComposites) {
+
+ measurementOOBCompositeList = measurementOOBComposites;
+ Log.debug("\nSuccessfully queried "+measurementOOBCompositeList.size() +" OOB records in: " + (System.currentTimeMillis() - startTime)
+ + " ms.");
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.debug("Error retrieving out of bound metrics for resource [" + resource.getId() + "]:"
+ + caught.getMessage());
+ countDownLatch.countDown();
+ }
+ });
+
+ }
+
+ /**
+ * Spin through the measurement definitions (in order) checking to see if they are in the
+ * summary measurement definition set and if so build a graph.
+ * @param measurementData
+ * @param summaryMeasurementDefinitions
+ * @param measurementDefinitions
+ */
+ private void buildSummaryGraphs(List<List<MeasurementDataNumericHighLowComposite>> measurementData,
+ List<MeasurementDefinition> summaryMeasurementDefinitions,
+ List<MeasurementDefinition> measurementDefinitions) {
+ Set<Integer> summaryIds = new TreeSet<Integer>();
+ for (MeasurementDefinition summaryMeasurementDefinition : summaryMeasurementDefinitions) {
+ summaryIds.add(summaryMeasurementDefinition.getId());
+ }
+
+ int i = 0;
+ for (MeasurementDefinition measurementDefinition : measurementDefinitions) {
+ if (summaryIds.contains(measurementDefinition.getId())) {
+ buildSingleGraph(measurementOOBCompositeList, measurementDefinition,
+ measurementData.get(i), MULTI_CHART_HEIGHT);
+ }
+ i++;
+ }
+
+ }
+
+ private void determineGraphsToBuild(List<List<MeasurementDataNumericHighLowComposite>> measurementData,
+ List<MeasurementDefinition> measurementDefinitions, Set<Integer> definitionIds) {
+ int i = 0;
+ for (List<MeasurementDataNumericHighLowComposite> metric : measurementData) {
+
+ for (Integer selectedDefinitionId : definitionIds) {
+ final MeasurementDefinition measurementDefinition = measurementDefinitions.get(i);
+ final int measurementId = measurementDefinition.getId();
+
+ if (null != selectedDefinitionId) {
+ // single graph case
+ if (measurementId == selectedDefinitionId) {
+ buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric, SINGLE_CHART_HEIGHT);
+ }
+ } else {
+ // multiple graph case
+ buildSingleGraph(measurementOOBCompositeList, measurementDefinition, metric, MULTI_CHART_HEIGHT);
+ }
+ }
+ i++;
+ }
+ }
+ });
+
+ }
+
+ private void buildSingleGraph(PageList<MeasurementOOBComposite> measurementOOBCompositeList,
+ MeasurementDefinition measurementDefinition, List<MeasurementDataNumericHighLowComposite> data, int height) {
+
+ MetricGraphData metricGraphData = MetricGraphData.createForResource(resource.getId(), resource.getName(),
+ measurementDefinition, data, measurementOOBCompositeList );
+ StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
+ graph.setMetricGraphData(metricGraphData);
+ MetricD3Graph graphView = new MetricD3Graph(graph);
+
+ graphView.setWidth("95%");
+ graphView.setHeight(height);
+
+ vLayout.addMember(graphView);
+ }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 3041b33..40316af 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -95,7 +95,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
return D3GraphListView.createSingleGraph(resource, measurementId, false);
}
- private D3GraphListView(Resource resource, Set<Integer> definitionIds, boolean showAvailabilityGraph) {
+ protected D3GraphListView(Resource resource, Set<Integer> definitionIds, boolean showAvailabilityGraph) {
super();
this.resource = resource;
commonConstructorSettings();
@@ -103,7 +103,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
this.showAvailabilityGraph = showAvailabilityGraph;
}
- private D3GraphListView(Resource resource, boolean showAvailabilityGraph) {
+ protected D3GraphListView(Resource resource, boolean showAvailabilityGraph) {
super();
this.resource = resource;
this.showAvailabilityGraph = showAvailabilityGraph;
@@ -153,7 +153,9 @@ public class D3GraphListView extends AbstractD3GraphListView {
public void redrawGraphs() {
this.onDraw();
- availabilityGraph.drawJsniChart();
+ if(null != availabilityGraph){
+ availabilityGraph.drawJsniChart();
+ }
}
@Override
commit ecb62e42703486aa81f0916e3e57156b604e231e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 5 18:18:45 2013 -0700
Disable d3 sliding brushes until more solid.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 5f43d42..ad26edc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -678,7 +678,7 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
createOOBLines();
}
createHovers(chartContext);
- createBrush();
+ //createBrush();
}
}
}; // end public closure
commit 094c23644214cce6125ae876e74574a7b9cfdbb2
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 5 17:24:39 2013 -0700
Deprecate LiveGraphD3View.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
index b16035a..c77b68b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
@@ -41,7 +41,9 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
/**
* @author Greg Hinkle
* @author Mike Thompson
+ * @deprecated
*/
+@Deprecated
public class LiveGraphD3View extends EnhancedVLayout {
private static final int MAX_BARS_TO_KEEP = 60;
commit 65ed727e33210f242ea91642facd96de94185ca1
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 4 21:04:09 2013 -0700
Second iteration at consolidated metrics tab with sparklines and expandable graphs.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index e36dc6e..ecf5a03 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -51,7 +51,6 @@ import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.composite.ResourceComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
-import org.rhq.enterprise.gui.coregui.client.components.FullHTMLPane;
import org.rhq.enterprise.gui.coregui.client.dashboard.Portlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.PortletViewFactory;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.PortletConfigurationEditorComponent.Constant;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
index 07622e3..2e4e169 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
@@ -192,7 +192,7 @@ public class ResourceGroupDetailView extends
monitoringTab = new TwoLevelTab(new ViewName("Monitoring", MSG.view_tabs_common_monitoring()),
IconEnum.SUSPECT_METRICS);
monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
- monitorTables = new SubTab(monitoringTab, new ViewName("Tables", MSG.view_tabs_common_tables()), null);
+ monitorTables = new SubTab(monitoringTab, new ViewName("Metrics", MSG.view_tabs_common_metrics()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableDataSource.java
deleted file mode 100644
index 29c6911..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableDataSource.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Set;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.data.DSRequest;
-import com.smartgwt.client.data.DSResponse;
-import com.smartgwt.client.types.ListGridFieldType;
-import com.smartgwt.client.widgets.grid.ListGridField;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-
-import org.rhq.core.domain.criteria.Criteria;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.ui.MetricDisplaySummary;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.resource.group.ResourceGroup;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MeasurementTableDataSource;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.UserPreferences;
-
-/**
- * A simple data source to read in metric data summaries for a resource.
- * This doesn't support paging - everything is returned in one query. Since
- * the number of metrics per resource is relatively small (never more than tens of them),
- * we just load them all in at once.
- *
- * @author John Mazzitelli
- * @author Simeon PInder
- */
-public class GroupMeasurementTableDataSource extends MeasurementTableDataSource {
-
- public static final String FIELD_MEMBERS_REPORTING = "membersReporting";
-
- private int groupId;
- private ResourceGroupComposite groupComposite;
-
- public GroupMeasurementTableDataSource(ResourceGroupComposite groupComposite, int groupId) {
- super(groupId);
- this.groupComposite = groupComposite;
- this.groupId = groupId;
- }
-
- /**
- * The view that contains the list grid which will display this datasource's data will call this
- * method to get the field information which is used to control the display of the data.
- *
- * @return list grid fields used to display the datasource data
- */
- public ArrayList<ListGridField> getListGridFields() {
- ArrayList<ListGridField> fields = new ArrayList<ListGridField>(6);
-
- ListGridField memberCountField = new ListGridField(FIELD_MEMBERS_REPORTING, MSG
- .common_title_members_reporting());
- memberCountField.setWidth("15%");
- fields.add(memberCountField);
-
- ListGridField nameField = new ListGridField(FIELD_METRIC_LABEL, MSG.common_title_name());
- //launching modal window, not normal link so javascript target set.
- nameField.setType(ListGridFieldType.LINK);
- nameField.setTarget("javascript");
- nameField.setWidth("30%");
- fields.add(nameField);
-
- ListGridField alertsField = new ListGridField(FIELD_ALERT_COUNT, MSG.common_title_alerts());
- alertsField.setWidth("10%");
- fields.add(alertsField);
-
- ListGridField minField = new ListGridField(FIELD_MIN_VALUE, MSG.view_resource_monitor_table_min());
- minField.setWidth("15%");
- fields.add(minField);
-
- ListGridField maxField = new ListGridField(FIELD_MAX_VALUE, MSG.view_resource_monitor_table_max());
- maxField.setWidth("15%");
- fields.add(maxField);
-
- ListGridField avgField = new ListGridField(FIELD_AVG_VALUE, MSG.view_resource_monitor_table_avg());
- avgField.setWidth("15%");
- fields.add(avgField);
-
- return fields;
- }
-
- @Override
- public ListGridRecord copyValues(MetricDisplaySummary from) {
- MeasurementUtility.formatSimpleMetrics(from);
-
- ListGridRecord record = new ListGridRecord();
- record.setAttribute(FIELD_METRIC_LABEL, from.getLabel());
- record.setAttribute(FIELD_ALERT_COUNT, String.valueOf(from.getAlertCount()));
- record.setAttribute(FIELD_MIN_VALUE, getMetricStringValue(from.getMinMetric()));
- record.setAttribute(FIELD_MAX_VALUE, getMetricStringValue(from.getMaxMetric()));
- record.setAttribute(FIELD_AVG_VALUE, getMetricStringValue(from.getAvgMetric()));
- record.setAttribute(FIELD_METRIC_DEF_ID, from.getDefinitionId());
- record.setAttribute(FIELD_METRIC_SCHED_ID, from.getScheduleId());
- record.setAttribute(FIELD_METRIC_UNITS, from.getUnits());
- record.setAttribute(FIELD_METRIC_NAME, from.getMetricName());
- record.setAttribute(FIELD_MEMBERS_REPORTING, from.getNumberCollecting());
- return record;
- }
-
- @Override
- protected void executeFetch(final DSRequest request, final DSResponse response, final Criteria unused) {
- final ResourceGroupComposite groupComposite = this.groupComposite;
- final ResourceGroup group = groupComposite.getResourceGroup();
- // Load the fully fetched ResourceType.
- ResourceType groupType = group.getResourceType();
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(
- groupType.getId(),
- EnumSet.of(ResourceTypeRepository.MetadataType.content, ResourceTypeRepository.MetadataType.operations,
- ResourceTypeRepository.MetadataType.measurements, ResourceTypeRepository.MetadataType.events,
- ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
- new ResourceTypeRepository.TypeLoadedCallback() {
- public void onTypesLoaded(ResourceType type) {
- group.setResourceType(type);
- //metric definitions
- Set<MeasurementDefinition> definitions = type.getMetricDefinitions();
-
- //build id mapping for measurementDefinition instances Ex. Free Memory -> MeasurementDefinition[100071]
- final HashMap<String, MeasurementDefinition> measurementDefMap = new HashMap<String, MeasurementDefinition>();
- for (MeasurementDefinition definition : definitions) {
- measurementDefMap.put(definition.getDisplayName(), definition);
- }
- //bundle definition ids for asynch call.
- int[] definitionArrayIds = new int[definitions.size()];
- final String[] displayOrder = new String[definitions.size()];
- measurementDefMap.keySet().toArray(displayOrder);
- //sort the charting data ex. Free Memory, Free Swap Space,..System Load
- Arrays.sort(displayOrder);
-
- //organize definitionArrayIds for ordered request on server.
- int index = 0;
- for (String definitionToDisplay : displayOrder) {
- definitionArrayIds[index++] = measurementDefMap.get(definitionToDisplay).getId();
- }
-
- UserPreferences prefs = UserSessionManager.getUserPreferences();
- MeasurementUserPreferences mprefs = new MeasurementUserPreferences(prefs);
- ArrayList<Long> range = mprefs.getMetricRangePreferences().getBeginEndTimes();
-
- //now retrieve metric display sumamries
- GWTServiceLookup.getMeasurementChartsService().getMetricDisplaySummariesForCompatibleGroup(groupId,
- definitionArrayIds, Long.valueOf(range.get(0)).longValue(),
- Long.valueOf(range.get(1)).longValue(), false,
- new AsyncCallback<ArrayList<MetricDisplaySummary>>() {
- @Override
- public void onSuccess(ArrayList<MetricDisplaySummary> result) {
- ArrayList<MetricDisplaySummary> validSummaries = new ArrayList<MetricDisplaySummary>();
- for (MetricDisplaySummary mds : result) {
- if (mds.getValuesPresent()) {//include only populated datapoints.
- validSummaries.add(mds);
- }
- }
- response.setData(buildRecords(validSummaries));
- processResponse(request.getRequestId(), response);
- }
-
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError("Cannot load metrics", caught);
- }
- });
- }
- });
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableView.java
index 44c7acc..1e73f0d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMeasurementTableView.java
@@ -37,7 +37,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.summary.Abs
* @author John Mazzitelli
* @author Simeon Pinder
*/
-public class GroupMeasurementTableView extends Table<GroupMeasurementTableDataSource> {
+public class GroupMeasurementTableView extends Table<GroupMetricsTableDataSource> {
private final int groupId;
private final boolean isAutogroup;
@@ -46,7 +46,7 @@ public class GroupMeasurementTableView extends Table<GroupMeasurementTableDataSo
super();
this.groupId = groupId;
this.isAutogroup = groupComposite.getResourceGroup().getAutoGroupParentResource() != null;
- setDataSource(new GroupMeasurementTableDataSource(groupComposite, groupId));
+ setDataSource(new GroupMetricsTableDataSource(groupComposite, groupId));
//disable fields used when is full screen
setShowFooterRefresh(true);
setTitle(MSG.common_title_numeric_metrics());
@@ -61,9 +61,9 @@ public class GroupMeasurementTableView extends Table<GroupMeasurementTableDataSo
@Override
public void onCellClick(CellClickEvent event) {
Record record = event.getRecord();
- String title = record.getAttribute(GroupMeasurementTableDataSource.FIELD_METRIC_LABEL);
+ String title = record.getAttribute(GroupMetricsTableDataSource.FIELD_METRIC_LABEL);
ChartViewWindow window = new ChartViewWindow("MeasurementTableFrame", title);
- int defId = record.getAttributeAsInt(GroupMeasurementTableDataSource.FIELD_METRIC_DEF_ID);
+ int defId = record.getAttributeAsInt(GroupMetricsTableDataSource.FIELD_METRIC_DEF_ID);
CompositeGroupD3GraphListView graph = new CompositeGroupMultiLineGraphListView(groupId, defId, isAutogroup);
window.addItem(graph);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMetricsTableDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMetricsTableDataSource.java
new file mode 100644
index 0000000..0b7b0bf
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/GroupMetricsTableDataSource.java
@@ -0,0 +1,175 @@
+package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Set;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.DSRequest;
+import com.smartgwt.client.data.DSResponse;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
+import org.rhq.core.domain.criteria.Criteria;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.ui.MetricDisplaySummary;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MetricsTableDataSource;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.UserPreferences;
+
+/**
+ * A simple data source to read in metric data summaries for a resource.
+ * This doesn't support paging - everything is returned in one query. Since
+ * the number of metrics per resource is relatively small (never more than tens of them),
+ * we just load them all in at once.
+ *
+ * @author John Mazzitelli
+ * @author Simeon PInder
+ */
+public class GroupMetricsTableDataSource extends MetricsTableDataSource {
+
+ public static final String FIELD_MEMBERS_REPORTING = "membersReporting";
+
+ private int groupId;
+ private ResourceGroupComposite groupComposite;
+
+ public GroupMetricsTableDataSource(ResourceGroupComposite groupComposite, int groupId) {
+ super(groupId);
+ this.groupComposite = groupComposite;
+ this.groupId = groupId;
+ }
+
+ /**
+ * The view that contains the list grid which will display this datasource's data will call this
+ * method to get the field information which is used to control the display of the data.
+ *
+ * @return list grid fields used to display the datasource data
+ */
+ public ArrayList<ListGridField> getListGridFields() {
+ ArrayList<ListGridField> fields = new ArrayList<ListGridField>(6);
+
+ ListGridField memberCountField = new ListGridField(FIELD_MEMBERS_REPORTING, MSG
+ .common_title_members_reporting());
+ memberCountField.setWidth("15%");
+ fields.add(memberCountField);
+
+ ListGridField nameField = new ListGridField(FIELD_METRIC_LABEL, MSG.common_title_name());
+ //launching modal window, not normal link so javascript target set.
+ nameField.setType(ListGridFieldType.LINK);
+ nameField.setTarget("javascript");
+ nameField.setWidth("30%");
+ fields.add(nameField);
+
+ ListGridField alertsField = new ListGridField(FIELD_ALERT_COUNT, MSG.common_title_alerts());
+ alertsField.setWidth("10%");
+ fields.add(alertsField);
+
+ ListGridField minField = new ListGridField(FIELD_MIN_VALUE, MSG.view_resource_monitor_table_min());
+ minField.setWidth("15%");
+ fields.add(minField);
+
+ ListGridField maxField = new ListGridField(FIELD_MAX_VALUE, MSG.view_resource_monitor_table_max());
+ maxField.setWidth("15%");
+ fields.add(maxField);
+
+ ListGridField avgField = new ListGridField(FIELD_AVG_VALUE, MSG.view_resource_monitor_table_avg());
+ avgField.setWidth("15%");
+ fields.add(avgField);
+
+ return fields;
+ }
+
+ @Override
+ public ListGridRecord copyValues(MetricDisplaySummary from) {
+ MeasurementUtility.formatSimpleMetrics(from);
+
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute(FIELD_METRIC_LABEL, from.getLabel());
+ record.setAttribute(FIELD_ALERT_COUNT, String.valueOf(from.getAlertCount()));
+ record.setAttribute(FIELD_MIN_VALUE, getMetricStringValue(from.getMinMetric()));
+ record.setAttribute(FIELD_MAX_VALUE, getMetricStringValue(from.getMaxMetric()));
+ record.setAttribute(FIELD_AVG_VALUE, getMetricStringValue(from.getAvgMetric()));
+ record.setAttribute(FIELD_METRIC_DEF_ID, from.getDefinitionId());
+ record.setAttribute(FIELD_METRIC_SCHED_ID, from.getScheduleId());
+ record.setAttribute(FIELD_METRIC_UNITS, from.getUnits());
+ record.setAttribute(FIELD_METRIC_NAME, from.getMetricName());
+ record.setAttribute(FIELD_MEMBERS_REPORTING, from.getNumberCollecting());
+ return record;
+ }
+
+ @Override
+ protected void executeFetch(final DSRequest request, final DSResponse response, final Criteria unused) {
+ final ResourceGroupComposite groupComposite = this.groupComposite;
+ final ResourceGroup group = groupComposite.getResourceGroup();
+ // Load the fully fetched ResourceType.
+ ResourceType groupType = group.getResourceType();
+ ResourceTypeRepository.Cache.getInstance().getResourceTypes(
+ groupType.getId(),
+ EnumSet.of(ResourceTypeRepository.MetadataType.content, ResourceTypeRepository.MetadataType.operations,
+ ResourceTypeRepository.MetadataType.measurements, ResourceTypeRepository.MetadataType.events,
+ ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
+ new ResourceTypeRepository.TypeLoadedCallback() {
+ public void onTypesLoaded(ResourceType type) {
+ group.setResourceType(type);
+ //metric definitions
+ Set<MeasurementDefinition> definitions = type.getMetricDefinitions();
+
+ //build id mapping for measurementDefinition instances Ex. Free Memory -> MeasurementDefinition[100071]
+ final HashMap<String, MeasurementDefinition> measurementDefMap = new HashMap<String, MeasurementDefinition>();
+ for (MeasurementDefinition definition : definitions) {
+ measurementDefMap.put(definition.getDisplayName(), definition);
+ }
+ //bundle definition ids for asynch call.
+ int[] definitionArrayIds = new int[definitions.size()];
+ final String[] displayOrder = new String[definitions.size()];
+ measurementDefMap.keySet().toArray(displayOrder);
+ //sort the charting data ex. Free Memory, Free Swap Space,..System Load
+ Arrays.sort(displayOrder);
+
+ //organize definitionArrayIds for ordered request on server.
+ int index = 0;
+ for (String definitionToDisplay : displayOrder) {
+ definitionArrayIds[index++] = measurementDefMap.get(definitionToDisplay).getId();
+ }
+
+ UserPreferences prefs = UserSessionManager.getUserPreferences();
+ MeasurementUserPreferences mprefs = new MeasurementUserPreferences(prefs);
+ ArrayList<Long> range = mprefs.getMetricRangePreferences().getBeginEndTimes();
+
+ //now retrieve metric display sumamries
+ GWTServiceLookup.getMeasurementChartsService().getMetricDisplaySummariesForCompatibleGroup(groupId,
+ definitionArrayIds, Long.valueOf(range.get(0)).longValue(),
+ Long.valueOf(range.get(1)).longValue(), false,
+ new AsyncCallback<ArrayList<MetricDisplaySummary>>() {
+ @Override
+ public void onSuccess(ArrayList<MetricDisplaySummary> result) {
+ ArrayList<MetricDisplaySummary> validSummaries = new ArrayList<MetricDisplaySummary>();
+ for (MetricDisplaySummary mds : result) {
+ if (mds.getValuesPresent()) {//include only populated datapoints.
+ validSummaries.add(mds);
+ }
+ }
+ response.setData(buildRecords(validSummaries));
+ processResponse(request.getRequestId(), response);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError("Cannot load metrics", caught);
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index c15bcae..be4409a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -68,7 +68,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitorin
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.ResourceAvailabilityView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.schedules.ResourceSchedulesView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MeasurementTableView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table.MetricsTableView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.traits.TraitsView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.history.ResourceOperationHistoryListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.schedule.ResourceOperationScheduleListView;
@@ -198,7 +198,7 @@ public class ResourceDetailView extends
monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
- metricsTables = new SubTab(monitoringTab, new ViewName("Metrics", MSG.view_tabs_common_tables()), null);
+ metricsTables = new SubTab(monitoringTab, new ViewName("Metrics", MSG.view_tabs_common_metrics()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
monitorAvail = new SubTab(monitoringTab, new ViewName("Availability", MSG.view_tabs_common_availability()),
null);
@@ -405,7 +405,7 @@ public class ResourceDetailView extends
viewFactory = (!visible) ? null : new ViewFactory() {
@Override
public Canvas createView() {
- return new MeasurementTableView(resource.getId());
+ return new MetricsTableView(resource.getId());
}
};
updateSubTab(this.monitoringTab, this.metricsTables, visible, true, viewFactory);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
index 1c8d259..b16035a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphD3View.java
@@ -144,6 +144,11 @@ public class LiveGraphD3View extends EnhancedVLayout {
dataLoaderTimer.scheduleRepeating(DATA_REFRESH_TIME);
}
+ /**
+ * Live Graphs are no longer available.
+ * @param resourceId
+ * @param def
+ */
public static void displayAsDialog(int resourceId, MeasurementDefinition def) {
final LiveGraphD3View graph = new LiveGraphD3View(resourceId, def);
final Window graphPopup = new Window();
@@ -200,44 +205,46 @@ public class LiveGraphD3View extends EnhancedVLayout {
}
public native void drawJsniCharts() /*-{
- var chartId = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getChartId()(),
- chartHandle = "#liveChart-"+chartId,
- chartSelection = chartHandle + " svg",
- yAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getYAxisTitle()(),
- yAxisUnits = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getYAxisUnits()(),
- xAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getXAxisTitle()(),
- json = eval(this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getJsonMetrics()()),
- data = function() {
- return [
- {
- values: json,
- key: yAxisLabel ,
- color: '#ff7f0e'
- }
- ];
- };
-
- $wnd.nv.addGraph(function() {
- var chart = $wnd.nv.models.multiBarChart()
- .showControls(false)
- .tooltips(true);
-
- chart.xAxis.axisLabel(xAxisLabel)
- .tickFormat(function(d) { return $wnd.d3.time.format('%X')(new Date(d)) });
-
- chart.yAxis
- .axisLabel(yAxisUnits)
- .tickFormat($wnd.d3.format('.02f'));
-
- $wnd.d3.select(chartSelection)
- .datum(data())
- .transition().duration(100)
- .call(chart);
-
- $wnd.nv.utils.windowResize(chart.update);
-
- return chart;
- });
+ var chartId = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getChartId()(),
+ chartHandle = "#liveChart-" + chartId,
+ chartSelection = chartHandle + " svg",
+ yAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getYAxisTitle()(),
+ yAxisUnits = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getYAxisUnits()(),
+ xAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getXAxisTitle()(),
+ json = eval(this.@org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.LiveGraphD3View::getJsonMetrics()()),
+ data = function () {
+ return [
+ {
+ values: json,
+ key: yAxisLabel,
+ color: '#ff7f0e'
+ }
+ ];
+ };
+
+ $wnd.nv.addGraph(function () {
+ var chart = $wnd.nv.models.multiBarChart()
+ .showControls(false)
+ .tooltips(true);
+
+ chart.xAxis.axisLabel(xAxisLabel)
+ .tickFormat(function (d) {
+ return $wnd.d3.time.format('%X')(new Date(d))
+ });
+
+ chart.yAxis
+ .axisLabel(yAxisUnits)
+ .tickFormat($wnd.d3.format('.02f'));
+
+ $wnd.d3.select(chartSelection)
+ .datum(data())
+ .transition().duration(100)
+ .call(chart);
+
+ $wnd.nv.utils.windowResize(chart.update);
+
+ return chart;
+ });
}-*/;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
index f0f1162..fe0c65f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
@@ -116,37 +116,54 @@ public class MetricD3Graph extends EnhancedVLayout {
/**
* Setup the page elements especially the div and svg elements that serve as
* placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
- * Later the drawJsniGraph() is called to actually fill in the div/svg element
+ * Later the drawJsniChart() is called to actually fill in the div/svg element
* created here with the actual svg element.
*
*/
protected void drawGraph() {
- Log.debug("drawGraph marker in MetricD3Graph for: " + getFullChartId() + " " + graph.getChartTitle());
-
- StringBuilder divAndSvgDefs = new StringBuilder();
- divAndSvgDefs
- .append("<div id=\""
- + getFullChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
- + getChartHeight() + "px;\">");
- divAndSvgDefs.append(getSvgDefs());
- divAndSvgDefs.append("</svg></div>");
+ final String divAndSvgDefs = createGraphMarker();
if (null != graphDiv) {
removeMember(graphDiv);
}
- graphDiv = new HTMLFlow(divAndSvgDefs.toString());
+ graphDiv = new HTMLFlow(divAndSvgDefs);
graphDiv.setWidth100();
graphDiv.setHeight100();
addMember(graphDiv);
- new Timer() {
- @Override
- public void run() {
- drawJsniChart();
- }
- }.schedule(200);
+ drawJsniChart();
+
+ }
+
+ /**
+ * This is used to explicitly use the 2 phase creation of a graph separately.
+ * Used to add the chart to something custom.
+ * @return String Graph Marker to be filled in with drawJsniChart() later
+ */
+ public String createGraphMarker() {
+ return createGraphMarkerTemplate(getFullChartId(), getHeight());
+ }
+
+ /**
+ * A static version of createGraphMarker that can be used when a MetricD3Graph is not
+ * instantiated.
+ * @param fullChartId
+ * @param height
+ * @return String chart marker
+ */
+ public static String createGraphMarkerTemplate(String fullChartId, Integer height){
+ Log.debug("drawGraph marker in MetricD3Graph for: " + fullChartId);
+
+ StringBuilder divAndSvgDefs = new StringBuilder();
+ divAndSvgDefs
+ .append("<div id=\""
+ + fullChartId
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
+ + height + "px;\">");
+ divAndSvgDefs.append(getSvgDefs());
+ divAndSvgDefs.append("</svg></div>");
+ return divAndSvgDefs.toString();
}
/**
@@ -154,7 +171,12 @@ public class MetricD3Graph extends EnhancedVLayout {
* This way the chart type can be swapped out at any time.
*/
public void drawJsniChart() {
- graph.drawJsniChart();
+ new Timer() {
+ @Override
+ public void run() {
+ graph.drawJsniChart();
+ }
+ }.schedule(200);
}
public String getFullChartId() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java
deleted file mode 100644
index 561ea09..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
-
-import java.util.ArrayList;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.data.DSRequest;
-import com.smartgwt.client.data.DSResponse;
-import com.smartgwt.client.data.Record;
-import com.smartgwt.client.widgets.grid.CellFormatter;
-import com.smartgwt.client.widgets.grid.ListGridField;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-
-import org.rhq.core.domain.criteria.Criteria;
-import org.rhq.core.domain.measurement.DataType;
-import org.rhq.core.domain.measurement.MeasurementSchedule;
-import org.rhq.core.domain.measurement.ui.MetricDisplaySummary;
-import org.rhq.core.domain.measurement.ui.MetricDisplayValue;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility;
-import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.UserPreferences;
-
-/**
- * A simple data source to read in metric data summaries for a resource.
- * This doesn't support paging - everything is returned in one query. Since
- * the number of metrics per resource is relatively small (never more than tens of them),
- * we just load them all in at once.
- *
- * @author John Mazzitelli
- */
-public class MeasurementTableDataSource extends RPCDataSource<MetricDisplaySummary, Criteria> {
-
- public static final String FIELD_METRIC_LABEL = "label";
- public static final String FIELD_ALERT_COUNT = "alertCount";
- public static final String FIELD_MIN_VALUE = "min";
- public static final String FIELD_MAX_VALUE = "max";
- public static final String FIELD_AVG_VALUE = "avg";
- public static final String FIELD_LAST_VALUE = "last";
- public static final String FIELD_METRIC_DEF_ID = "defId";
- public static final String FIELD_METRIC_SCHED_ID = "schedId";
- public static final String FIELD_METRIC_UNITS = "units";
- public static final String FIELD_METRIC_NAME = "name";
- public static final String FIELD_RESOURCE_ID = "resourceId";
-
- private int resourceId;
-
- public MeasurementTableDataSource(int resourceId) {
- this.resourceId = resourceId;
- }
-
- /**
- * The view that contains the list grid which will display this datasource's data will call this
- * method to get the field information which is used to control the display of the data.
- *
- * @return list grid fields used to display the datasource data
- */
- public ArrayList<ListGridField> getListGridFields() {
- ArrayList<ListGridField> fields = new ArrayList<ListGridField>(6);
-
- ListGridField nameField = new ListGridField(FIELD_METRIC_LABEL, MSG.common_title_name());
- nameField.setWidth("30%");
- fields.add(nameField);
-
- nameField.setCellFormatter(new CellFormatter() {
- @Override
- public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
- if (value == null) {
- return "";
- }
- String commaDelimitedList = "5, 10, 20, 25";
- //String formattedValue = StringUtility.escapeHtml(value.toString());
- String contents= "<span id='sparkline_" + resourceId + "-"+ record.getAttributeAsInt("FIELD_METRIC_DEF_ID")
- + "' class='dynamicsparkline' width='0' " + "values='"
- + commaDelimitedList + "'>...</span>";
- return contents;
-
- }
- });
-
- ListGridField alertsField = new ListGridField(FIELD_ALERT_COUNT, MSG.common_title_alerts());
- alertsField.setWidth("10%");
- fields.add(alertsField);
-
- ListGridField minField = new ListGridField(FIELD_MIN_VALUE, MSG.view_resource_monitor_table_min());
- minField.setWidth("15%");
- fields.add(minField);
-
- ListGridField maxField = new ListGridField(FIELD_MAX_VALUE, MSG.view_resource_monitor_table_max());
- maxField.setWidth("15%");
- fields.add(maxField);
-
- ListGridField avgField = new ListGridField(FIELD_AVG_VALUE, MSG.view_resource_monitor_table_avg());
- avgField.setWidth("15%");
- fields.add(avgField);
-
- ListGridField lastField = new ListGridField(FIELD_LAST_VALUE, MSG.view_resource_monitor_table_last());
- lastField.setWidth("15%");
- fields.add(lastField);
-
- return fields;
- }
-
- @Override
- public MetricDisplaySummary copyValues(Record from) {
- // we should never need this method - we only go in one direction
- // if we ever need this, just have copyValues store an "object" attribute whose value is "from"
- // which this method then just reads out. Since we don't need this now, save memory by not
- // keeping the MetricDisplayValue around
- return null;
- }
-
- @Override
- public ListGridRecord copyValues(MetricDisplaySummary from) {
- MeasurementUtility.formatSimpleMetrics(from);
-
- ListGridRecord record = new ListGridRecord();
- record.setAttribute(FIELD_METRIC_LABEL, from.getLabel());
- record.setAttribute(FIELD_ALERT_COUNT, String.valueOf(from.getAlertCount()));
- record.setAttribute(FIELD_MIN_VALUE, getMetricStringValue(from.getMinMetric()));
- record.setAttribute(FIELD_MAX_VALUE, getMetricStringValue(from.getMaxMetric()));
- record.setAttribute(FIELD_AVG_VALUE, getMetricStringValue(from.getAvgMetric()));
- record.setAttribute(FIELD_LAST_VALUE, getMetricStringValue(from.getLastMetric()));
- record.setAttribute(FIELD_METRIC_DEF_ID, from.getDefinitionId());
- record.setAttribute(FIELD_METRIC_SCHED_ID, from.getScheduleId());
- record.setAttribute(FIELD_METRIC_UNITS, from.getUnits());
- record.setAttribute(FIELD_METRIC_NAME, from.getMetricName());
- record.setAttribute(FIELD_RESOURCE_ID, resourceId);
- return record;
- }
-
- protected String getMetricStringValue(MetricDisplayValue value) {
- return (value != null) ? value.toString() : "";
- }
-
- @Override
- protected Criteria getFetchCriteria(DSRequest request) {
- // we don't use criterias for this datasource, just return null
- return null;
- }
-
- @Override
- protected void executeFetch(final DSRequest request, final DSResponse response, final Criteria unused) {
-
- // see MetricsTableUIBean for the old JSF class to see where this came from
-
- GWTServiceLookup.getMeasurementScheduleService().findSchedulesForResourceAndType(resourceId,
- DataType.MEASUREMENT, null, true, new AsyncCallback<ArrayList<MeasurementSchedule>>() {
- @Override
- public void onSuccess(ArrayList<MeasurementSchedule> result) {
- int[] schedIds = new int[result.size()];
- int i = 0;
- for (MeasurementSchedule measurementSchedule : result) {
- schedIds[i++] = measurementSchedule.getId();
- }
-
- UserPreferences prefs = UserSessionManager.getUserPreferences();
- MeasurementUserPreferences mprefs = new MeasurementUserPreferences(prefs);
- ArrayList<Long> range = mprefs.getMetricRangePreferences().getBeginEndTimes();
- GWTServiceLookup.getMeasurementChartsService().getMetricDisplaySummariesForResource(resourceId,
- schedIds, range.get(0), range.get(1), new AsyncCallback<ArrayList<MetricDisplaySummary>>() {
- @Override
- public void onSuccess(ArrayList<MetricDisplaySummary> result) {
- response.setData(buildRecords(result));
- processResponse(request.getRequestId(), response);
- }
-
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError("Cannot load metrics", caught);
- }
- });
- }
-
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError("Cannot load schedules", caught);
- }
- });
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
deleted file mode 100644
index 17e05dc..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.TreeSet;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.types.Alignment;
-import com.smartgwt.client.types.ExpansionMode;
-import com.smartgwt.client.types.SelectionStyle;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.IButton;
-import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.CloseClickEvent;
-import com.smartgwt.client.widgets.events.CloseClickHandler;
-import com.smartgwt.client.widgets.events.DrawEvent;
-import com.smartgwt.client.widgets.events.DrawHandler;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
-import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
-import com.smartgwt.client.widgets.grid.CellFormatter;
-import com.smartgwt.client.widgets.grid.ListGrid;
-import com.smartgwt.client.widgets.grid.ListGridField;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-import com.smartgwt.client.widgets.grid.events.RecordExpandEvent;
-import com.smartgwt.client.widgets.grid.events.RecordExpandHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import org.rhq.core.domain.criteria.ResourceCriteria;
-import org.rhq.core.domain.measurement.MeasurementData;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.composite.ResourceComposite;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.components.FullHTMLPane;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.components.table.Table;
-import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
-import org.rhq.enterprise.gui.coregui.client.drift.DriftSnapshotDataSource;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.InventoryView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.summary.AbstractActivityView.ChartViewWindow;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-
-/**
- * Views a resource's metrics in a tabular view with sparkline graph
- * and optional detailed graph .
- *
- * @author John Mazzitelli
- * @author Mike Thompson
- */
-public class MeasurementTableView extends Table<MeasurementTableDataSource> {
-
- private final int resourceId;
-
- public MeasurementTableView(int resourceId) {
- super();
- this.resourceId = resourceId;
- setDataSource(new MeasurementTableDataSource(resourceId));
- }
-
- /**
- * Creates this Table's list grid (called by onInit()). Subclasses can override this if they require a custom subclass
- * of ListGrid.
- *
- * @return this Table's list grid (must be an instance of ListGrid)
- */
- @Override
- protected ListGrid createListGrid() {
- return new MetricsTableListGrid();
- }
-
- protected void configureTable() {
- ArrayList<ListGridField> fields = getDataSource().getListGridFields();
- setListGridFields(fields.toArray(new ListGridField[0]));
- this.getListGrid().setCanExpandRecords(true);
- this.getListGrid().addRecordExpandHandler(new RecordExpandHandler() {
- @Override
- public void onRecordExpand(RecordExpandEvent recordExpandEvent) {
- Log.debug("Record Expanded: ");
-
- }
- });
-
- //addExtraWidget(new UserPreferencesMeasurementRangeEditor(), true);
- addTableAction(MSG.view_measureTable_getLive(), new TableAction() {
- @Override
- public boolean isEnabled(ListGridRecord[] selection) {
- return selection != null && selection.length > 0;
- }
-
- @Override
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- if (selection == null || selection.length == 0) {
- return;
- }
- // keyed on metric name - string[0] is the metric label, [1] is the units
- final HashMap<String, String[]> scheduleNamesAndUnits = new HashMap<String, String[]>();
- int[] definitionIds = new int[selection.length];
- int i = 0;
- for (ListGridRecord record : selection) {
- Integer defId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_METRIC_DEF_ID);
- definitionIds[i++] = defId;
-
- String name = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_NAME);
- String label = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_LABEL);
- String units = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_UNITS);
- if (units == null || units.length() < 1) {
- units = MeasurementUnits.NONE.name();
- }
-
- scheduleNamesAndUnits.put(name, new String[]{label, units});
- }
-
- // actually go out and ask the agents for the data
- GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId, definitionIds,
- new AsyncCallback<Set<MeasurementData>>() {
- @Override
- public void onSuccess(Set<MeasurementData> result) {
- if (result == null) {
- result = new HashSet<MeasurementData>(0);
- }
- ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
- for (MeasurementData data : result) {
- String[] nameAndUnits = scheduleNamesAndUnits.get(data.getName());
- if (nameAndUnits != null) {
- double doubleValue;
- if (data.getValue() instanceof Number) {
- doubleValue = ((Number)data.getValue()).doubleValue();
- }
- else {
- doubleValue = Double.parseDouble(data.getValue().toString());
- }
- String value = MeasurementConverterClient.formatToSignificantPrecision(
- new double[]{doubleValue}, MeasurementUnits.valueOf(nameAndUnits[1]), true)[0];
-
- ListGridRecord record = new ListGridRecord();
- record.setAttribute("name", nameAndUnits[0]);
- record.setAttribute("value", value);
- records.add(record);
- }
- }
- Collections.sort(records, new Comparator<ListGridRecord>() {
- public int compare(ListGridRecord o1, ListGridRecord o2) {
- return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
- }
- });
- showLiveData(records);
- }
-
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
- }
- });
- }
- });
-
-
- addTableAction(MSG.view_measureTable_addToDashboard(), new TableAction() {
-
- @Override
- public boolean isEnabled(ListGridRecord[] selection) {
- return selection != null && selection.length > 0;
- }
-
- @Override
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
-
- }
- });
-
- }
-
- private void showLiveData(ArrayList<ListGridRecord> records) {
- final Window liveDataWindow = new Window();
- liveDataWindow.setTitle(MSG.view_measureTable_live_title());
- liveDataWindow.setShowModalMask(true);
- liveDataWindow.setShowMinimizeButton(false);
- liveDataWindow.setShowMaximizeButton(true);
- liveDataWindow.setShowCloseButton(true);
- liveDataWindow.setShowResizer(true);
- liveDataWindow.setCanDragResize(true);
- liveDataWindow.setDismissOnEscape(true);
- liveDataWindow.setIsModal(true);
- liveDataWindow.setWidth(700);
- liveDataWindow.setHeight(425);
- liveDataWindow.setAutoCenter(true);
- liveDataWindow.centerInPage();
- liveDataWindow.addCloseClickHandler(new CloseClickHandler() {
- @Override
- public void onCloseClick(CloseClickEvent event) {
- liveDataWindow.destroy();
- refreshTableInfo();
- }
- });
-
- ListGrid liveDataGrid = new ListGrid();
- liveDataGrid.setShowAllRecords(true);
- liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
- liveDataGrid.setSelectionType(SelectionStyle.NONE);
- ListGridField name = new ListGridField("name", MSG.common_title_metric());
- ListGridField value = new ListGridField("value", MSG.common_title_value());
- liveDataGrid.setFields(name, value);
-
- liveDataWindow.addItem(liveDataGrid);
- liveDataWindow.show();
- }
-
- private class MetricsTableListGrid extends ListGrid {
- public MetricsTableListGrid() {
- super();
-
- setCanExpandRecords(true);
- setCanExpandMultipleRecords(true);
- setExpansionMode(ExpansionMode.RELATED);
- }
-
- @Override
- protected Canvas getExpansionComponent(final ListGridRecord record) {
- final Integer definitionId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_METRIC_DEF_ID);
- final Integer resourceId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_RESOURCE_ID);
- VLayout vLayout = new VLayout(5);
- vLayout.setPadding(5);
- //vLayout.addMember(graphListView);
-
- final DynamicForm df = new DynamicForm();
- df.setNumCols(4);
- df.setDataSource(getDataSource());
-
- IButton saveButton = new IButton("Mike");
- IButton cancelButton = new IButton("Done");
-
- HLayout hLayout = new HLayout(10);
- hLayout.setAlign(Alignment.CENTER);
- hLayout.addMember(saveButton);
- hLayout.addMember(cancelButton);
-
- vLayout.addMember(df);
- vLayout.addMember(hLayout);
-
-
- //locate resource reference
- ResourceCriteria criteria = new ResourceCriteria();
- criteria.addFilterId(resourceId);
-
- //locate the resource
- GWTServiceLookup.getResourceService().findResourceCompositesByCriteria(criteria,
- new AsyncCallback<PageList<ResourceComposite>>() {
- @Override
- public void onFailure(Throwable caught) {
- Log.debug("Error retrieving resource resource composite for resource [" + resourceId + "]:"
- + caught.getMessage());
- }
-
- @Override
- public void onSuccess(PageList<ResourceComposite> results) {
- if (!results.isEmpty()) {
- Resource resource = results.get(0).getResource();
- D3GraphListView graphListView = D3GraphListView.createSingleGraph(resource, definitionId, false);
-
-
- }
- }
- });
-
- return vLayout;
-
-
- }
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java
new file mode 100644
index 0000000..2fa11da
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableDataSource.java
@@ -0,0 +1,185 @@
+package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
+
+import java.util.ArrayList;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.DSRequest;
+import com.smartgwt.client.data.DSResponse;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
+import org.rhq.core.domain.criteria.Criteria;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.ui.MetricDisplaySummary;
+import org.rhq.core.domain.measurement.ui.MetricDisplayValue;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.util.BrowserUtility;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility;
+import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.UserPreferences;
+
+/**
+ * A simple data source to read in metric data summaries for a resource.
+ * This doesn't support paging - everything is returned in one query. Since
+ * the number of metrics per resource is relatively small (never more than tens of them),
+ * we just load them all in at once.
+ *
+ * @author John Mazzitelli
+ */
+public class MetricsTableDataSource extends RPCDataSource<MetricDisplaySummary, Criteria> {
+
+ public static final String FIELD_METRIC_LABEL = "label";
+ public static final String FIELD_ALERT_COUNT = "alertCount";
+ public static final String FIELD_MIN_VALUE = "min";
+ public static final String FIELD_MAX_VALUE = "max";
+ public static final String FIELD_AVG_VALUE = "avg";
+ public static final String FIELD_LAST_VALUE = "last";
+ public static final String FIELD_METRIC_DEF_ID = "defId";
+ public static final String FIELD_METRIC_SCHED_ID = "schedId";
+ public static final String FIELD_METRIC_UNITS = "units";
+ public static final String FIELD_METRIC_NAME = "name";
+ public static final String FIELD_RESOURCE_ID = "resourceId";
+
+ private int resourceId;
+
+ public MetricsTableDataSource(int resourceId) {
+ this.resourceId = resourceId;
+ }
+
+ /**
+ * The view that contains the list grid which will display this datasource's data will call this
+ * method to get the field information which is used to control the display of the data.
+ *
+ * @return list grid fields used to display the datasource data
+ */
+ public ArrayList<ListGridField> getListGridFields() {
+ ArrayList<ListGridField> fields = new ArrayList<ListGridField>(6);
+
+ ListGridField nameField = new ListGridField(FIELD_METRIC_LABEL, MSG.common_title_name());
+ nameField.setWidth("30%");
+ fields.add(nameField);
+
+ nameField.setCellFormatter(new CellFormatter() {
+ @Override
+ public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
+ if (value == null) {
+ return "";
+ }
+ String commaDelimitedList = "5, 10, 20, 25";
+ //String formattedValue = StringUtility.escapeHtml(value.toString());
+ String contents= "<span id='sparkline_" + resourceId + "-"+ record.getAttributeAsInt("FIELD_METRIC_DEF_ID")
+ + "' class='dynamicsparkline' width='0' " + "values='"
+ + commaDelimitedList + "'>...</span>";
+ return contents;
+
+ }
+ });
+ BrowserUtility.graphSparkLines();
+
+ ListGridField alertsField = new ListGridField(FIELD_ALERT_COUNT, MSG.common_title_alerts());
+ alertsField.setWidth("10%");
+ fields.add(alertsField);
+
+ ListGridField minField = new ListGridField(FIELD_MIN_VALUE, MSG.view_resource_monitor_table_min());
+ minField.setWidth("15%");
+ fields.add(minField);
+
+ ListGridField maxField = new ListGridField(FIELD_MAX_VALUE, MSG.view_resource_monitor_table_max());
+ maxField.setWidth("15%");
+ fields.add(maxField);
+
+ ListGridField avgField = new ListGridField(FIELD_AVG_VALUE, MSG.view_resource_monitor_table_avg());
+ avgField.setWidth("15%");
+ fields.add(avgField);
+
+ ListGridField lastField = new ListGridField(FIELD_LAST_VALUE, MSG.view_resource_monitor_table_last());
+ lastField.setWidth("15%");
+ fields.add(lastField);
+
+ return fields;
+ }
+
+ @Override
+ public MetricDisplaySummary copyValues(Record from) {
+ // we should never need this method - we only go in one direction
+ // if we ever need this, just have copyValues store an "object" attribute whose value is "from"
+ // which this method then just reads out. Since we don't need this now, save memory by not
+ // keeping the MetricDisplayValue around
+ return null;
+ }
+
+ @Override
+ public ListGridRecord copyValues(MetricDisplaySummary from) {
+ MeasurementUtility.formatSimpleMetrics(from);
+
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute(FIELD_METRIC_LABEL, from.getLabel());
+ record.setAttribute(FIELD_ALERT_COUNT, String.valueOf(from.getAlertCount()));
+ record.setAttribute(FIELD_MIN_VALUE, getMetricStringValue(from.getMinMetric()));
+ record.setAttribute(FIELD_MAX_VALUE, getMetricStringValue(from.getMaxMetric()));
+ record.setAttribute(FIELD_AVG_VALUE, getMetricStringValue(from.getAvgMetric()));
+ record.setAttribute(FIELD_LAST_VALUE, getMetricStringValue(from.getLastMetric()));
+ record.setAttribute(FIELD_METRIC_DEF_ID, from.getDefinitionId());
+ record.setAttribute(FIELD_METRIC_SCHED_ID, from.getScheduleId());
+ record.setAttribute(FIELD_METRIC_UNITS, from.getUnits());
+ record.setAttribute(FIELD_METRIC_NAME, from.getMetricName());
+ record.setAttribute(FIELD_RESOURCE_ID, resourceId);
+ return record;
+ }
+
+ protected String getMetricStringValue(MetricDisplayValue value) {
+ return (value != null) ? value.toString() : "";
+ }
+
+ @Override
+ protected Criteria getFetchCriteria(DSRequest request) {
+ // we don't use criterias for this datasource, just return null
+ return null;
+ }
+
+ @Override
+ protected void executeFetch(final DSRequest request, final DSResponse response, final Criteria unused) {
+
+ // see MetricsTableUIBean for the old JSF class to see where this came from
+
+ GWTServiceLookup.getMeasurementScheduleService().findSchedulesForResourceAndType(resourceId,
+ DataType.MEASUREMENT, null, true, new AsyncCallback<ArrayList<MeasurementSchedule>>() {
+ @Override
+ public void onSuccess(ArrayList<MeasurementSchedule> result) {
+ int[] schedIds = new int[result.size()];
+ int i = 0;
+ for (MeasurementSchedule measurementSchedule : result) {
+ schedIds[i++] = measurementSchedule.getId();
+ }
+
+ UserPreferences prefs = UserSessionManager.getUserPreferences();
+ MeasurementUserPreferences mprefs = new MeasurementUserPreferences(prefs);
+ ArrayList<Long> range = mprefs.getMetricRangePreferences().getBeginEndTimes();
+ GWTServiceLookup.getMeasurementChartsService().getMetricDisplaySummariesForResource(resourceId,
+ schedIds, range.get(0), range.get(1), new AsyncCallback<ArrayList<MetricDisplaySummary>>() {
+ @Override
+ public void onSuccess(ArrayList<MetricDisplaySummary> result) {
+ response.setData(buildRecords(result));
+ processResponse(request.getRequestId(), response);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError("Cannot load metrics", caught);
+ }
+ });
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError("Cannot load schedules", caught);
+ }
+ });
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java
new file mode 100644
index 0000000..6dd4db7
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java
@@ -0,0 +1,356 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.ExpansionMode;
+import com.smartgwt.client.types.SelectionStyle;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.HTMLFlow;
+import com.smartgwt.client.widgets.Window;
+import com.smartgwt.client.widgets.events.CloseClickEvent;
+import com.smartgwt.client.widgets.events.CloseClickHandler;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordExpandEvent;
+import com.smartgwt.client.widgets.grid.events.RecordExpandHandler;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.composite.ResourceComposite;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.table.Table;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3Graph;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+/**
+ * Views a resource's metrics in a tabular view with sparkline graph
+ * and optional detailed graph .
+ *
+ * @author John Mazzitelli
+ * @author Mike Thompson
+ */
+public class MetricsTableView extends Table<MetricsTableDataSource> {
+
+ private final int resourceId;
+
+ public MetricsTableView(int resourceId) {
+ super();
+ this.resourceId = resourceId;
+ setDataSource(new MetricsTableDataSource(resourceId));
+ }
+
+ /**
+ * Creates this Table's list grid (called by onInit()). Subclasses can override this if they require a custom subclass
+ * of ListGrid.
+ *
+ * @return this Table's list grid (must be an instance of ListGrid)
+ */
+ @Override
+ protected ListGrid createListGrid() {
+ return new MetricsTableListGrid();
+ }
+
+ protected void configureTable() {
+ ArrayList<ListGridField> fields = getDataSource().getListGridFields();
+ setListGridFields(fields.toArray(new ListGridField[0]));
+ this.getListGrid().setCanExpandRecords(true);
+ this.getListGrid().addRecordExpandHandler(new RecordExpandHandler() {
+ @Override
+ public void onRecordExpand(RecordExpandEvent recordExpandEvent) {
+ Log.debug("Record Expanded: ");
+
+ }
+ });
+
+ //addExtraWidget(new UserPreferencesMeasurementRangeEditor(), true);
+ addTableAction(MSG.view_measureTable_getLive(), new TableAction() {
+ @Override
+ public boolean isEnabled(ListGridRecord[] selection) {
+ return selection != null && selection.length > 0;
+ }
+
+ @Override
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ if (selection == null || selection.length == 0) {
+ return;
+ }
+ // keyed on metric name - string[0] is the metric label, [1] is the units
+ final HashMap<String, String[]> scheduleNamesAndUnits = new HashMap<String, String[]>();
+ int[] definitionIds = new int[selection.length];
+ int i = 0;
+ for (ListGridRecord record : selection) {
+ Integer defId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_METRIC_DEF_ID);
+ definitionIds[i++] = defId;
+
+ String name = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_NAME);
+ String label = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_LABEL);
+ String units = record.getAttribute(MetricsTableDataSource.FIELD_METRIC_UNITS);
+ if (units == null || units.length() < 1) {
+ units = MeasurementUnits.NONE.name();
+ }
+
+ scheduleNamesAndUnits.put(name, new String[] { label, units });
+ }
+
+ // actually go out and ask the agents for the data
+ GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId, definitionIds,
+ new AsyncCallback<Set<MeasurementData>>() {
+ @Override
+ public void onSuccess(Set<MeasurementData> result) {
+ if (result == null) {
+ result = new HashSet<MeasurementData>(0);
+ }
+ ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+ for (MeasurementData data : result) {
+ String[] nameAndUnits = scheduleNamesAndUnits.get(data.getName());
+ if (nameAndUnits != null) {
+ double doubleValue;
+ if (data.getValue() instanceof Number) {
+ doubleValue = ((Number) data.getValue()).doubleValue();
+ } else {
+ doubleValue = Double.parseDouble(data.getValue().toString());
+ }
+ String value = MeasurementConverterClient.formatToSignificantPrecision(
+ new double[] { doubleValue }, MeasurementUnits.valueOf(nameAndUnits[1]), true)[0];
+
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute("name", nameAndUnits[0]);
+ record.setAttribute("value", value);
+ records.add(record);
+ }
+ }
+ Collections.sort(records, new Comparator<ListGridRecord>() {
+ public int compare(ListGridRecord o1, ListGridRecord o2) {
+ return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+ }
+ });
+ showLiveData(records);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+ }
+ });
+ }
+ });
+
+ addTableAction(MSG.view_measureTable_addToDashboard(), new TableAction() {
+
+ @Override
+ public boolean isEnabled(ListGridRecord[] selection) {
+ return selection != null && selection.length > 0;
+ }
+
+ @Override
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+
+ }
+ });
+
+ }
+
+ private void showLiveData(ArrayList<ListGridRecord> records) {
+ final Window liveDataWindow = new Window();
+ liveDataWindow.setTitle(MSG.view_measureTable_live_title());
+ liveDataWindow.setShowModalMask(true);
+ liveDataWindow.setShowMinimizeButton(false);
+ liveDataWindow.setShowMaximizeButton(true);
+ liveDataWindow.setShowCloseButton(true);
+ liveDataWindow.setShowResizer(true);
+ liveDataWindow.setCanDragResize(true);
+ liveDataWindow.setDismissOnEscape(true);
+ liveDataWindow.setIsModal(true);
+ liveDataWindow.setWidth(700);
+ liveDataWindow.setHeight(425);
+ liveDataWindow.setAutoCenter(true);
+ liveDataWindow.centerInPage();
+ liveDataWindow.addCloseClickHandler(new CloseClickHandler() {
+ @Override
+ public void onCloseClick(CloseClickEvent event) {
+ liveDataWindow.destroy();
+ refreshTableInfo();
+ }
+ });
+
+ ListGrid liveDataGrid = new ListGrid();
+ liveDataGrid.setShowAllRecords(true);
+ liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
+ liveDataGrid.setSelectionType(SelectionStyle.NONE);
+ ListGridField name = new ListGridField("name", MSG.common_title_metric());
+ ListGridField value = new ListGridField("value", MSG.common_title_value());
+ liveDataGrid.setFields(name, value);
+
+ liveDataWindow.addItem(liveDataGrid);
+ liveDataWindow.show();
+ }
+
+ private class MetricsTableListGrid extends ListGrid {
+ public MetricsTableListGrid() {
+ super();
+
+ setCanExpandRecords(true);
+ setCanExpandMultipleRecords(true);
+ setExpansionMode(ExpansionMode.RELATED);
+ }
+
+ @Override
+ protected Canvas getExpansionComponent(final ListGridRecord record) {
+ final Integer definitionId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_METRIC_DEF_ID);
+ final Integer resourceId = record.getAttributeAsInt(MetricsTableDataSource.FIELD_RESOURCE_ID);
+ VLayout vLayout = new VLayout();
+ vLayout.setPadding(5);
+
+ final String chartId = "rChart" + resourceId + "-" + definitionId;
+ HTMLFlow htmlFlow = new HTMLFlow(MetricD3Graph.createGraphMarkerTemplate(chartId, 200));
+ vLayout.addMember(htmlFlow);
+
+ //locate resource reference
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterId(resourceId);
+
+ //locate the resource
+ GWTServiceLookup.getResourceService().findResourceCompositesByCriteria(criteria,
+ new AsyncCallback<PageList<ResourceComposite>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.debug("Error retrieving resource resource composite for resource [" + resourceId + "]:"
+ + caught.getMessage());
+ }
+
+ @Override
+ public void onSuccess(PageList<ResourceComposite> results) {
+ if (!results.isEmpty()) {
+ final Resource resource = results.get(0).getResource();
+ //D3GraphListView graphListView = D3GraphListView.createSingleGraph(resource, definitionId, false);
+
+ // Load the fully fetched ResourceType.
+ ResourceType resourceType = resource.getResourceType();
+ ResourceTypeRepository.Cache.getInstance().getResourceTypes(
+ resourceType.getId(),
+ EnumSet.of(ResourceTypeRepository.MetadataType.content,
+ ResourceTypeRepository.MetadataType.operations,
+ ResourceTypeRepository.MetadataType.measurements,
+ ResourceTypeRepository.MetadataType.events,
+ ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
+ new ResourceTypeRepository.TypeLoadedCallback() {
+ public void onTypesLoaded(ResourceType type) {
+ resource.setResourceType(type);
+ //metric definitions
+ Set<MeasurementDefinition> definitions = type.getMetricDefinitions();
+ final MeasurementDefinition measurementDefinition;
+
+ //build id mapping for measurementDefinition instances Ex. Free Memory -> MeasurementDefinition[100071]
+ final HashMap<String, MeasurementDefinition> measurementDefMap = new HashMap<String, MeasurementDefinition>();
+ for (MeasurementDefinition definition : definitions) {
+ measurementDefMap.put(definition.getDisplayName(), definition);
+ if (definition.getId() == definitionId) {
+ measurementDefinition = definition;
+ break;
+ }
+ }
+
+ int[] definitionArrayIds = new int[1];
+ definitionArrayIds[0] = definitionId;
+ GWTServiceLookup.getMeasurementDataService().findDataForResource(resourceId,
+ definitionArrayIds, 1370156400, 1370446147, 60,
+ new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.debug("Error retrieving recent metrics charting data for resource ["
+ + resourceId + "]:" + caught.getMessage());
+ //setRefreshing(false);
+ }
+
+ @Override
+ public void onSuccess(
+ List<List<MeasurementDataNumericHighLowComposite>> results) {
+ if (!results.isEmpty()) {
+
+ //load the data results for the given metric definition
+ List<MeasurementDataNumericHighLowComposite> data = results
+ .get(0);
+
+ //locate last and minimum values.
+ double lastValue = -1;
+ double minValue = Double.MAX_VALUE;//
+ for (MeasurementDataNumericHighLowComposite d : data) {
+ if ((!Double.isNaN(d.getValue()))
+ && (!String.valueOf(d.getValue()).contains("NaN"))) {
+ if (d.getValue() < minValue) {
+ minValue = d.getValue();
+ }
+ lastValue = d.getValue();
+ }
+ }
+
+ //@todo: OOB data
+// MetricGraphData metricGraphData = MetricGraphData
+// .createForResource(resourceId, resource.getName(),
+// measurementDefinition, data, null);
+//
+// StackedBarMetricGraphImpl graph = GWT
+// .create(StackedBarMetricGraphImpl.class);
+// graph.setMetricGraphData(metricGraphData);
+// MetricD3Graph graphView = new MetricD3Graph(graph);
+// graphView.drawJsniChart();
+
+ } else {
+
+ }
+ //setRefreshing(false);
+ }
+ });
+
+ }
+ });
+
+ }
+ }
+ });
+
+ return vLayout;
+
+ }
+ }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index bd0ba1f..6d02548 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -2055,12 +2055,12 @@ view_tabs_common_groups = Groups
view_tabs_common_history = History
view_tabs_common_inventory = Inventory
view_tabs_common_members = Members
+view_tabs_common_metrics = Metrics
view_tabs_common_monitoring = Monitoring
view_tabs_common_overview = Overview
view_tabs_common_schedule = Schedule
view_tabs_common_schedules = Schedules
view_tabs_common_subscriptions = Subscriptions
-view_tabs_common_tables = Tables
view_tabs_common_timeline = Timeline
view_tabs_common_traits = Traits
view_tabs_invalidSubTab = Invalid subtab: {0}
commit b3228cafdc51924b5fad4b2cb4aa48ac483f6feb
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 4 21:03:57 2013 -0700
Get rid of d3 slider (brush) graphing classes no longer used.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
deleted file mode 100644
index 015a528..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
-
-import java.util.Date;
-import java.util.List;
-
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AvailabilityGraphType;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
- * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
- * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
- *
- * @author Mike Thompson
- */
-@Deprecated
-public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGraphType {
-
- private static Messages MSG = CoreGUI.getMessages();
- private List<Availability> availabilityList;
- private List<ResourceGroupAvailability> groupAvailabilityList;
- private Integer entityId;
-
- /**
- * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
- * for all cases but the dashboard portlet).
- */
- public AvailabilityOverUnderGraphWithSliderType(Integer entityId) {
- this.entityId = entityId;
- }
-
- @Override
- public void setAvailabilityList(List<Availability> availabilityList) {
- this.availabilityList = availabilityList;
- }
-
- @Override
- public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
- this.groupAvailabilityList = groupAvailabilityList;
- }
-
- @Override
- public String getAvailabilityJson() {
- StringBuilder sb = new StringBuilder("[");
- if (null != availabilityList) {
- // loop through the avail intervals
- for (Availability availability : availabilityList) {
- sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
- // last record will be null
- long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - availability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
-
- } else if (null != groupAvailabilityList) {
- // loop through the group avail down intervals
- for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
- // allows substitution for situations like WARN=MIXED for easier terminology
- String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
- .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
- .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
-
- sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
- sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
- // last record will be null
- long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
- .getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - groupAvailability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
- }
-
- sb.append("]");
- Log.debug(sb.toString());
- return sb.toString();
- }
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- @Override
- public native void drawJsniChart() /*-{
- console.log("Draw Enhanced Availability chart");
-
- var global = this,
- // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
- // NOTE: rhq.js has the javascript object constructors in it.
- availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailabilityJson()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverAvailabilityLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverDateFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailChartTitleLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailChartUpLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailChartDownLabel()()
- );
-
-
- var availabilityGraph = function () {
- "use strict";
- // privates
-
- var margin = {top: 5, right: 5, bottom: 5, left: 40},
- barOffset = 10,
- width = 750 - margin.left - margin.right + barOffset,
- height = 40 - margin.top - margin.bottom,
- svg;
-
-
- function drawBars(availChartContext) {
- var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
- return +d.availStart;
- }),
- xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
- return +d.availEnd;
- }),
-
- timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain([xAxisMin, xAxisMax]),
-
- yScale = $wnd.d3.scale.linear()
- .clamp(true)
- .rangeRound([height, 0])
- .domain([0, 4]),
-
- xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(8)
- .tickSize(13, 0, 0)
- .orient("bottom"),
-
- calcBarY = function (d) {
- var ABOVE = -6,
- BELOW = 0,
- STRADDLE = -3,
- offset;
-
- if (d.availType === 'DOWN'){
- offset = BELOW;
- }
- else if (d.availType === 'DISABLED') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UNKNOWN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UP') {
- offset = ABOVE;
- }
- else if (d.availType === 'WARN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'EMPTY') {
- offset = STRADDLE;
- }
- return yScale(0) + offset;
-
- },
-
- calcBarFill = function (d) {
- if (d.availType === 'DOWN') {
- return "#c5888b"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "url(#diagonalHatchFill)"; // grey diagonal hatches
- }
- else if (d.availType === 'UNKNOWN') {
- return "#d8d8d8"; // gray
- }
- else if (d.availType === 'UP') {
- return "#8cbe89"; // green
- }
- else if (d.availType === 'WARN') {
- return "#e1b36b"; // orange
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.log("AvailabilityType not valid.");
- return "#000"; //black
- }
- },
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-
- svg.selectAll("rect.availBars")
- .data(availChartContext.data)
- .enter().append("rect")
- .attr("class", "availBars")
- .attr("x", function (d) {
- return timeScale(+d.availStart);
- })
- .attr("y", function (d) {
- return calcBarY(d);
- })
- .attr("height", function (d) {
- return 6;
- })
- .attr("width", function (d) {
- return timeScale(+d.availEnd) - timeScale(+d.availStart);
- })
- .attr("opacity", ".75")
- .attr("fill", function (d) {
- return calcBarFill(d);
- });
-
- // create x-axis
- svg.append("g")
- .attr("class", "x axis")
- .attr("fill", "#b0b0b0")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
-
- svg.append("text")
- .attr("class", "availabilityLabel")
- .attr("x", -40)
- .attr("y", 10)
- .style("font-size", "12px")
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-weight", "bold")
- .attr("fill", "#545454")
- .text(availChartContext.chartTitle);
-
- svg.append("text")
- .attr("class", "upLabel")
- .attr("x", -5)
- .attr("y", 28)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#545454")
- .style("text-anchor", "end")
- .text(availChartContext.chartUpLabel);
-
- svg.append("text")
- .attr("class", "downLabel")
- .attr("x", -5)
- .attr("y", 39)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#545454")
- .style("text-anchor", "end")
- .text(availChartContext.chartDownLabel);
-
-
- // here is all the brush related stuff
- var brush = $wnd.d3.svg.brush()
- .x(timeScale)
- .extent([1369033200, 1369084807])
- .on("brushstart", brushstart)
- .on("brush", brushmove)
- .on("brushend", brushend);
-
-// var arc = $wnd.d3.svg.arc()
-// .outerRadius(30 / 2)
-// .startAngle(0)
-// .endAngle(function(d, i) { return i ? -Math.PI : Math.PI; });
-
- var brushg = svg.append("g")
- .attr("class", "brush")
- .call(brush);
-
- brushg.selectAll(".resize").append("path")
- .attr("transform", "translate(0," + height / 2 + ")")
- .attr("d", resizePath);
-
- brushg.selectAll("rect")
- .attr("height", 30);
-
- brushstart();
- brushmove();
-
- function brushstart() {
- svg.classed("selecting", true);
- }
-
- function brushmove() {
- var s = brush.extent();
- //circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
- console.log("Move start: "+s[0] + "Move End: "+ s[1]);
- }
-
- function brushend() {
- var s = brush.extent();
- svg.classed("selecting", !d3.event.target.empty());
- console.log("End start: "+s[0] + "End End: "+ s[1]);
- }
- // Taken from crossfilter (http://square.github.com/crossfilter/)
- function resizePath(d) {
- var e = +(d == 'e'),
- x = e ? 1 : -1,
- y = height / 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 createHovers() {
- $wnd.jQuery('svg rect.availBars').tipsy({
- gravity: 's',
- html: true,
- trigger: 'hover',
- title: function () {
- var d = this.__data__;
- return formatHovers(d);
- },
- show: function (e, el) {
- el.css({ 'z-index': '990000'})
- }
- });
- }
-
- function formatHovers(d) {
- var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
- dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart);
-
- return '<div class="chartHoverEnclosingDiv">' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
- '</div>';
-
- }
-
- return {
- // Public API
- draw: function (availChartContext) {
- "use strict";
- console.log("AvailabilityChart");
- drawBars(availChartContext);
- createHovers();
- }
- }; // end public closure
-
-
- }();
-
- if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
- availabilityGraph.draw(availChartContext);
- }
-
- }-*/;
-
- public String getChartId() {
- return String.valueOf(entityId);
- }
-
- public String getChartTimeLabel() {
- return MSG.chart_time_label();
- }
-
- public String getChartDateLabel() {
- return MSG.chart_date_label();
- }
-
- public String getChartHoverAvailabilityLabel() {
- return MSG.chart_hover_availability_label();
- }
-
- public String getChartHoverStartLabel() {
- return MSG.chart_hover_start_label();
- }
-
- public String getAvailChartDownLabel() {
- return MSG.avail_chart_down_label();
- }
-
- public String getAvailChartUpLabel() {
- return MSG.avail_chart_up_label();
- }
-
- public String getAvailChartTitleLabel() {
- return MSG.avail_chart_title_label();
- }
-
- public String getChartHoverBarLabel() {
- return MSG.chart_hover_bar_label();
- }
-
- public String getChartHoverTimeFormat() {
- return MSG.chart_hover_time_format();
- }
-
- public String getChartHoverDateFormat() {
- return MSG.chart_hover_date_format();
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
deleted file mode 100644
index 10a2635..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
-
-
-/**
- * The simplest of a all graph types as this d3 graph does not even require data, just x axis range so we can plot an
- * x-axis. No y data values needed. The purpose of this graph is to provide an x axis and a way to drag a
- * range over it (via d3 brushes).
- *
- * @author Mike Thompson
- */
-@Deprecated
-public class DateSliderGraphType {
-
- private Long startDateTime;
- private Long endDateTime;
-
- public DateSliderGraphType(Long startTime, Long endTime) {
- this.startDateTime = startTime;
- this.endDateTime = endTime;
- }
-
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart(double start, double end) /*-{
- console.log("Draw Date Range graph");
-
- var dateSliderGraph = function () {
- "use strict";
- // privates
-
- var margin = {top: 5, right: 5, bottom: 5, left: 40},
- barOffset = 10,
- width = 750 - margin.left - margin.right + barOffset,
- height = 40 - margin.top - margin.bottom,
- svg;
-
-
- function drawBars(startTime, endTime) {
-
- var timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain([startTime, endTime]),
-
- xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(8)
- .tickSize(13, 0, 0)
- .orient("bottom"),
-
- svg = $wnd.d3.select("#dateSlider svg").append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
- // create x-axis
- svg.append("g")
- .attr("class", "x axis")
- .attr("fill", "#b0b0b0")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
-
-
- // here is all the brush related stuff
- var brush = $wnd.d3.svg.brush()
- .x(timeScale)
- .extent([startTime, endTime])
- .on("brushstart", brushstart)
- .on("brush", brushmove)
- .on("brushend", brushend);
-
-
- var brushg = svg.append("g")
- .attr("class", "brush")
- .call(brush);
-
- brushg.selectAll(".resize").append("path")
- .attr("transform", "translate(0," + height / 2 + ")")
- .attr("d", resizePath);
-
- brushg.selectAll("rect")
- .attr("height", 29);
-
- brushstart();
- brushmove();
-
- function brushstart() {
- svg.classed("selecting", true);
- }
-
- function brushmove() {
- var s = brush.extent();
- //circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
- updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
- }
-
- function brushend() {
- var s = brush.extent();
- svg.classed("selecting", !$wnd.d3.event.target.empty());
- updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
- }
-
- function updateDateRangeDisplay(startDate, endDate ) {
- var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- $wnd.jQuery('#dateRange').val(formattedDateRange);
- }
-
- // Taken from crossfilter (http://square.github.com/crossfilter/)
- function resizePath(d) {
- var e = +(d == 'e'),
- x = e ? 1 : -1,
- y = height / 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);
- }
- }
-
- return {
- // Public API
- draw: function (startTime, endTime) {
- "use strict";
- console.log("DateSliderChart");
- drawBars(startTime, endTime);
- }
- }; // end public closure
-
-
- }();
-
- dateSliderGraph.draw(this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.DateSliderGraphType::getStartTime()(), this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.DateSliderGraphType::getEndTime()());
-
- }-*/;
-
- public Long getStartTime() {
- return startDateTime;
- }
-
- public void setStartDateTime(Long startDateTime) {
- this.startDateTime = startDateTime;
- }
-
-
- public Long getEndTime() {
- return endDateTime;
- }
-
-
- public void setEndDateTime(Long endDateTime) {
- this.endDateTime = endDateTime;
- }
-
-
-}
commit a34de45a82d8bc63c1de6427711c12b227009dbb
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 4 17:34:20 2013 -0700
Second iteration at consolidated metrics tab with sparklines and expandable graphs.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
index fdba334..4706252 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
@@ -62,7 +62,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3Graph;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.selection.SingleResourceGroupSelector;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
@@ -75,7 +75,7 @@ import org.rhq.enterprise.server.measurement.util.MeasurementUtils;
* @author Jay Shaughnessy
* @author Mike Thompson
*/
-public class ResourceGroupD3GraphPortlet extends MetricD3GraphView implements AutoRefreshPortlet, CustomSettingsPortlet {
+public class ResourceGroupD3GraphPortlet extends MetricD3Graph implements AutoRefreshPortlet, CustomSettingsPortlet {
// A non-displayed, persisted identifier for the portlet
public static final String KEY = "ResourceGroupMetricD3";
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
index 73d217b..03216b2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
@@ -58,7 +58,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3Graph;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.util.BrowserUtility;
@@ -70,7 +70,7 @@ import org.rhq.enterprise.server.measurement.util.MeasurementUtils;
* @author Jay Shaughnessy
* @author Mike Thompson
*/
-public class ResourceD3GraphPortlet extends MetricD3GraphView implements AutoRefreshPortlet, CustomSettingsPortlet {
+public class ResourceD3GraphPortlet extends MetricD3Graph implements AutoRefreshPortlet, CustomSettingsPortlet {
// A non-displayed, persisted identifier for the portlet
public static final String KEY = "ResourceMetricD3";
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index 049be45..b5e12e9 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -29,7 +29,7 @@ import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.AutoRefreshUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -48,13 +48,13 @@ public abstract class AbstractD3GraphListView extends EnhancedVLayout implements
protected static Label loadingLabel = new Label(MSG.common_msg_loading());
protected MeasurementUserPreferences measurementUserPrefs;
protected boolean showAvailabilityGraph = false;
- protected GraphDateTimeRangeEditor graphDateTimeRangeEditor;
+ protected ButtonBarDateTimeRangeEditor buttonBarDateTimeRangeEditor;
protected Timer refreshTimer;
public AbstractD3GraphListView() {
super();
measurementUserPrefs = new MeasurementUserPreferences(UserSessionManager.getUserPreferences());
- graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs,this);
+ buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
startRefreshCycle();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractGraph.java
deleted file mode 100644
index 6498f65..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractGraph.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
-
-
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-
-/**
- * Common Graph capability used across multiple graphs.
- * The MetricGraphData delegate is wrapped for JSNI access via d3 charts.
- * Also, by delegating and directly extending MetricGraphData we have more
- * control over the visibility of what we want graphs to 'see'.
- *
- * @see MetricGraphData
- *
- * @author Mike Thompson
- */
-public abstract class AbstractGraph extends VLayout implements HasD3MetricJsniChart {
-
- private MetricGraphData metricGraphData;
-
- public MetricGraphData getMetricGraphData() {
- return metricGraphData;
- }
-
- public void setMetricGraphData(MetricGraphData metricGraphData) {
- this.metricGraphData = metricGraphData;
- }
-
- public int getEntityId() {
- return metricGraphData.getEntityId();
- }
-
- @Override
- public void setEntityId(int entityId) {
- metricGraphData.setEntityId(entityId);
- }
-
-
- @Override
- public void setEntityName(String entityName) {
- metricGraphData.setEntityName(entityName);
- }
-
- public int getDefinitionId() {
- return metricGraphData.getDefinitionId();
- }
-
- public MeasurementDefinition getDefinition() {
- return metricGraphData.getDefinition();
- }
-
- @Override
- public void setDefinition(MeasurementDefinition definition) {
- metricGraphData.setDefinition(definition);
- }
-
- public String getChartId() {
- return metricGraphData.getChartId();
- }
-
- public boolean showBarAvgTrendLine(){
- return metricGraphData.showBarAvgTrendLine();
- }
-
- public String getChartTitleMinLabel() {
- return metricGraphData.getChartTitleMinLabel();
- }
-
- public String getChartTitleAvgLabel() {
- return metricGraphData.getChartTitleAvgLabel();
- }
-
- public String getChartTitlePeakLabel() {
- return metricGraphData.getChartTitlePeakLabel();
- }
-
- public String getChartDateLabel() {
- return metricGraphData.getChartDateLabel();
- }
-
- public String getChartDownLabel() {
- return metricGraphData.getChartDownLabel();
- }
-
- public String getChartTimeLabel() {
- return metricGraphData.getChartTimeLabel();
- }
-
- public String getChartUnknownLabel() {
- return metricGraphData.getChartUnknownLabel();
- }
-
- public String getChartNoDataLabel() {
- return metricGraphData.getChartNoDataLabel();
- }
-
- public String getChartHoverStartLabel() {
- return metricGraphData.getChartHoverStartLabel();
- }
-
- public String getChartHoverEndLabel() {
- return metricGraphData.getChartHoverEndLabel();
- }
-
- public String getChartHoverPeriodLabel() {
- return metricGraphData.getChartHoverPeriodLabel();
- }
-
- public String getChartHoverBarLabel() {
- return metricGraphData.getChartHoverBarLabel();
- }
-
- public String getChartHoverTimeFormat() {
- return metricGraphData.getChartHoverTimeFormat();
- }
-
- public String getChartHoverDateFormat() {
- return metricGraphData.getChartHoverDateFormat();
- }
-
-
- public int getChartHeight() {
- return metricGraphData.getChartHeight();
- }
-
- public void setChartHeight(Integer chartHeight) {
- metricGraphData.setChartHeight(chartHeight);
- }
-
- public String getChartTitle() {
- return metricGraphData != null ? metricGraphData.getChartTitle() : "";
- }
- public boolean isPortalGraph(){
- return metricGraphData.isPortalGraph();
- }
-
-
- public String getYAxisUnits() {
- return metricGraphData.getYAxisUnits();
- }
-
- public String getXAxisTitle() {
- return metricGraphData.getXAxisTitle();
- }
-
- public String getJsonMetrics() {
- return metricGraphData.getJsonMetrics();
- }
-
- public int getPortalId() {
- return metricGraphData.getPortalId();
- }
-
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
new file mode 100644
index 0000000..f681d64
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractMetricGraph.java
@@ -0,0 +1,174 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+
+import com.smartgwt.client.widgets.layout.VLayout;
+
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+
+/**
+ * Common Metric Graph capability used across multiple metric rendering graphs.
+ * The MetricGraphData delegate is wrapped for JSNI access via d3 charts.
+ * Also, by delegating and directly extending MetricGraphData we have more
+ * control over the visibility of what we want graphs to 'see'.
+ *
+ * @see MetricGraphData
+ *
+ * @author Mike Thompson
+ */
+public abstract class AbstractMetricGraph extends VLayout implements HasD3MetricJsniChart {
+
+ private MetricGraphData metricGraphData;
+
+ public MetricGraphData getMetricGraphData() {
+ return metricGraphData;
+ }
+
+ public void setMetricGraphData(MetricGraphData metricGraphData) {
+ this.metricGraphData = metricGraphData;
+ }
+
+ public int getEntityId() {
+ return metricGraphData.getEntityId();
+ }
+
+ @Override
+ public void setEntityId(int entityId) {
+ metricGraphData.setEntityId(entityId);
+ }
+
+
+ @Override
+ public void setEntityName(String entityName) {
+ metricGraphData.setEntityName(entityName);
+ }
+
+ public int getDefinitionId() {
+ return metricGraphData.getDefinitionId();
+ }
+
+ public MeasurementDefinition getDefinition() {
+ return metricGraphData.getDefinition();
+ }
+
+ @Override
+ public void setDefinition(MeasurementDefinition definition) {
+ metricGraphData.setDefinition(definition);
+ }
+
+ public String getChartId() {
+ return metricGraphData.getChartId();
+ }
+
+ public boolean showBarAvgTrendLine(){
+ return metricGraphData.showBarAvgTrendLine();
+ }
+
+ public String getChartTitleMinLabel() {
+ return metricGraphData.getChartTitleMinLabel();
+ }
+
+ public String getChartTitleAvgLabel() {
+ return metricGraphData.getChartTitleAvgLabel();
+ }
+
+ public String getChartTitlePeakLabel() {
+ return metricGraphData.getChartTitlePeakLabel();
+ }
+
+ public String getChartDateLabel() {
+ return metricGraphData.getChartDateLabel();
+ }
+
+ public String getChartDownLabel() {
+ return metricGraphData.getChartDownLabel();
+ }
+
+ public String getChartTimeLabel() {
+ return metricGraphData.getChartTimeLabel();
+ }
+
+ public String getChartUnknownLabel() {
+ return metricGraphData.getChartUnknownLabel();
+ }
+
+ public String getChartNoDataLabel() {
+ return metricGraphData.getChartNoDataLabel();
+ }
+
+ public String getChartHoverStartLabel() {
+ return metricGraphData.getChartHoverStartLabel();
+ }
+
+ public String getChartHoverEndLabel() {
+ return metricGraphData.getChartHoverEndLabel();
+ }
+
+ public String getChartHoverPeriodLabel() {
+ return metricGraphData.getChartHoverPeriodLabel();
+ }
+
+ public String getChartHoverBarLabel() {
+ return metricGraphData.getChartHoverBarLabel();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return metricGraphData.getChartHoverTimeFormat();
+ }
+
+ public String getChartHoverDateFormat() {
+ return metricGraphData.getChartHoverDateFormat();
+ }
+
+
+ public int getChartHeight() {
+ return metricGraphData.getChartHeight();
+ }
+
+ public void setChartHeight(Integer chartHeight) {
+ metricGraphData.setChartHeight(chartHeight);
+ }
+
+ public String getChartTitle() {
+ return metricGraphData != null ? metricGraphData.getChartTitle() : "";
+ }
+ public boolean isPortalGraph(){
+ return metricGraphData.isPortalGraph();
+ }
+
+
+ public String getYAxisUnits() {
+ return metricGraphData.getYAxisUnits();
+ }
+
+ public String getXAxisTitle() {
+ return metricGraphData.getXAxisTitle();
+ }
+
+ public String getJsonMetrics() {
+ return metricGraphData.getJsonMetrics();
+ }
+
+ public int getPortalId() {
+ return metricGraphData.getPortalId();
+ }
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
new file mode 100644
index 0000000..3957d9f
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/ButtonBarDateTimeRangeEditor.java
@@ -0,0 +1,276 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import java.util.List;
+
+import com.google.gwt.user.client.Timer;
+import com.smartgwt.client.widgets.HTMLFlow;
+
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+
+/**
+ * Component to allow selection of Date/Time range for graphs using a button group from bootstrap.
+ *
+ * @author Mike Thompson
+ */
+public class ButtonBarDateTimeRangeEditor extends EnhancedVLayout {
+
+ private MeasurementUserPreferences measurementUserPreferences;
+ private AbstractD3GraphListView d3GraphListView;
+ private static final Messages MSG = CoreGUI.getMessages();
+ private Long startDateTime;
+ private Long endDateTime;
+
+
+ public ButtonBarDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
+ AbstractD3GraphListView d3GraphListView) {
+ this.measurementUserPreferences = measurementUserPrefs;
+ this.d3GraphListView = d3GraphListView;
+
+
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+
+ // initialize with saved begin/end times
+ List<Long> beginEndTimes = prefs.getBeginEndTimes();
+ startDateTime = beginEndTimes.get(0);
+ endDateTime = beginEndTimes.get(1);
+ }
+
+ /**
+ * Setup the page elements especially the div and svg elements that serve as
+ * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
+ * Later the drawJsniGraph() is called to actually fill in the div/svg element
+ * created here with the actual svg element.
+ * NOTE: auxiliary javascript functions in rhq.js
+ *
+ */
+ public void createDateSliderMarker() {
+ Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
+
+ // append the bootstrap buttongroup since smartGWT doesn't have one
+ StringBuilder buttonBarDiv = new StringBuilder();
+ buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
+ "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
+ " <div class=\"accordion-group\">" +
+ " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
+ " <div class=\"accordion-inner\">" +
+ " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
+ " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
+ " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
+ " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
+ " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
+ " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
+ " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
+ " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
+ " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
+ " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
+ " </span>" +
+ " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
+ " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
+ " </div>" +
+ " </div>" +
+ " </div>" +
+ " </div>");
+ HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
+ buttonBarDivFlow.setWidth100();
+ buttonBarDivFlow.setHeight(50);
+ addMember(buttonBarDivFlow);
+ new Timer(){
+ @Override
+ public void run() {
+ changeDateRange(getStartTime(), getEndTime());
+ //drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
+ attachGraphDateRangeEditorButtonGroupHandlers();
+ }
+ }.schedule(200);
+ }
+
+ public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
+ console.log("Draw GraphDateTimeRangeEditor");
+ var global = this;
+
+ function updateDateDisplay(startDate, endDate ) {
+ var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ $wnd.jQuery('#dateRange').text(formattedDateRange);
+ }
+
+ function saveDateRange(startDate, endDate){
+ var start = startDate | 0, end = endDate | 0;
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor::changeDateRange(DD)(start,end);
+ //@todo: fixme
+ //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
+ }
+
+ var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
+
+ $wnd.jQuery("#radio1h").bind('click', function (event) {
+ console.log("1h selected");
+ graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio6h").bind('click', function (event) {
+ console.log(" 6h selected");
+ graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio12h").bind('click', function (event) {
+ console.log("12h selected");
+ graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio1d").bind('click', function (event) {
+ console.log("1d selected");
+ graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio5d").bind('click', function (event) {
+ console.log("5d selected");
+ graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio1m").bind('click', function (event) {
+ console.log("1m selected");
+ graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio3m").bind('click', function (event) {
+ console.log("3m selected");
+ graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio1y").bind('click', function (event) {
+ console.log("1y selected");
+ graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioCustom").bind('click', function (event) {
+ console.log("Custom Range selected");
+ graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+
+
+ // initially populate with default click
+ $wnd.jQuery("#radio12h").click();
+
+ }-*/;
+
+ public native void refreshGraphs() /*-{
+ console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
+ this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor::redrawGraphs()();
+ }-*/;
+
+
+// public void drawJsniDateSlider(){
+// dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
+// }
+//
+// public void drawJsniDateSlider(Long startTime, Long endTime){
+// dateSliderGraphType.drawJsniChart(startTime, endTime);
+// }
+
+ public void redrawGraphs(){
+ d3GraphListView.redrawGraphs();
+ }
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ removeMembers(getMembers());
+ createDateSliderMarker();
+ }
+
+ @Override
+ public void parentResized() {
+ super.parentResized();
+ removeMembers(getMembers());
+ createDateSliderMarker();
+ //drawJsniChart();
+ }
+
+
+ public Long getStartTime() {
+ return measurementUserPreferences.getMetricRangePreferences().begin;
+ }
+
+ public Long getEndTime() {
+ return measurementUserPreferences.getMetricRangePreferences().end;
+ }
+ /**
+ * Whenever we make a change to the date range save it here so it gets propogated to
+ * the correct places.
+ * @param startTime double because JSNI doesnt support long
+ * @param endTime double because JSNI doesnt support long
+ */
+ public void changeDateRange(double startTime, double endTime){
+
+ startDateTime = (long)startTime;
+ endDateTime = (long)endTime;
+
+ //@todo: uncomment when ready
+// final boolean advanced = true;
+// AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+// prefs.explicitBeginEnd = advanced;
+// prefs.begin = (long) startTime;
+// prefs.end = (long) endTime;
+// if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
+// CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
+// } else {
+// measurementUserPreferences.setMetricRangePreferences(prefs);
+// }
+
+ }
+
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
deleted file mode 100644
index 6a3c4a5..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
-
-import java.util.List;
-
-import com.google.gwt.user.client.Timer;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
-
-/**
- * Component to allow selection of Date/Time range for graphs using a button group from bootstrap.
- *
- * @author Mike Thompson
- */
-public class GraphDateTimeRangeEditor extends EnhancedVLayout {
-
- private MeasurementUserPreferences measurementUserPreferences;
- private AbstractD3GraphListView d3GraphListView;
- private static final Messages MSG = CoreGUI.getMessages();
- private Long startDateTime;
- private Long endDateTime;
-
-
- public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
- AbstractD3GraphListView d3GraphListView) {
- this.measurementUserPreferences = measurementUserPrefs;
- this.d3GraphListView = d3GraphListView;
-
-
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
-
- // initialize with saved begin/end times
- List<Long> beginEndTimes = prefs.getBeginEndTimes();
- startDateTime = beginEndTimes.get(0);
- endDateTime = beginEndTimes.get(1);
- }
-
- /**
- * Setup the page elements especially the div and svg elements that serve as
- * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
- * Later the drawJsniGraph() is called to actually fill in the div/svg element
- * created here with the actual svg element.
- * NOTE: auxiliary javascript functions in rhq.js
- *
- */
- public void createDateSliderMarker() {
- Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
-
- // append the bootstrap buttongroup since smartGWT doesn't have one
- StringBuilder buttonBarDiv = new StringBuilder();
- buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
- "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
- " <div class=\"accordion-group\">" +
- " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
- " <div class=\"accordion-inner\">" +
- " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
- " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
- " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
- " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
- " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
- " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
- " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
- " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
- " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
- " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
- " </span>" +
- " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
- " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
- " </div>" +
- " </div>" +
- " </div>" +
- " </div>");
- HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
- buttonBarDivFlow.setWidth100();
- buttonBarDivFlow.setHeight(50);
- addMember(buttonBarDivFlow);
- new Timer(){
- @Override
- public void run() {
- changeDateRange(getStartTime(), getEndTime());
- //drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
- attachGraphDateRangeEditorButtonGroupHandlers();
- }
- }.schedule(200);
- }
-
- public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
- console.log("Draw GraphDateTimeRangeEditor");
- var global = this;
-
- function updateDateDisplay(startDate, endDate ) {
- var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- $wnd.jQuery('#dateRange').text(formattedDateRange);
- }
-
- function saveDateRange(startDate, endDate){
- var start = startDate | 0, end = endDate | 0;
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::changeDateRange(DD)(start,end);
- //@todo: fixme
- //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
- }
-
- var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
-
- $wnd.jQuery("#radio1h").bind('click', function (event) {
- console.log("1h selected");
- graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio6h").bind('click', function (event) {
- console.log(" 6h selected");
- graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio12h").bind('click', function (event) {
- console.log("12h selected");
- graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio1d").bind('click', function (event) {
- console.log("1d selected");
- graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio5d").bind('click', function (event) {
- console.log("5d selected");
- graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio1m").bind('click', function (event) {
- console.log("1m selected");
- graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio3m").bind('click', function (event) {
- console.log("3m selected");
- graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radio1y").bind('click', function (event) {
- console.log("1y selected");
- graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radioCustom").bind('click', function (event) {
- console.log("Custom Range selected");
- graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
- graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
- });
-
-
- // initially populate with default click
- $wnd.jQuery("#radio12h").click();
-
- }-*/;
-
- public native void refreshGraphs() /*-{
- console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
- this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::redrawGraphs()();
- }-*/;
-
-
-// public void drawJsniDateSlider(){
-// dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
-// }
-//
-// public void drawJsniDateSlider(Long startTime, Long endTime){
-// dateSliderGraphType.drawJsniChart(startTime, endTime);
-// }
-
- public void redrawGraphs(){
- d3GraphListView.redrawGraphs();
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- removeMembers(getMembers());
- createDateSliderMarker();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- createDateSliderMarker();
- //drawJsniChart();
- }
-
-
- public Long getStartTime() {
- return measurementUserPreferences.getMetricRangePreferences().begin;
- }
-
- public Long getEndTime() {
- return measurementUserPreferences.getMetricRangePreferences().end;
- }
- /**
- * Whenever we make a change to the date range save it here so it gets propogated to
- * the correct places.
- * @param startTime double because JSNI doesnt support long
- * @param endTime double because JSNI doesnt support long
- */
- public void changeDateRange(double startTime, double endTime){
-
- startDateTime = (long)startTime;
- endDateTime = (long)endTime;
-
- //@todo: uncomment when ready
-// final boolean advanced = true;
-// AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
-// prefs.explicitBeginEnd = advanced;
-// prefs.begin = (long) startTime;
-// prefs.end = (long) endTime;
-// if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
-// CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
-// } else {
-// measurementUserPreferences.setMetricRangePreferences(prefs);
-// }
-
- }
-
-
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java
index 45d0aba..91d829c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java
@@ -38,7 +38,7 @@ import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
* The data portion of the graphs making these methods accessible via JSNI to
* classes extending this and implementing graphs.
* Provide i18n labels and format the json data for the graph.
- * @see AbstractGraph
+ * @see AbstractMetricGraph
*
* @author Mike Thompson
*/
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java
index 279921c..079b2ab 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java
@@ -18,7 +18,7 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
/**
@@ -28,7 +28,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphD
*
* @author Mike Thompson
*/
-public final class LineMetricGraph extends AbstractGraph {
+public final class LineMetricGraph extends AbstractMetricGraph {
/**
* General constructor for stacked bar graph when you have all the data needed to
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java
index 544a71b..22b6feb 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java
@@ -18,7 +18,7 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
/**
@@ -26,7 +26,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphD
*
* @author Mike Thompson
*/
-public final class MetricNvd3MultiLineGraph extends AbstractGraph
+public final class MetricNvd3MultiLineGraph extends AbstractMetricGraph
{
/**
* General constructor for stacked bar graph when you have all the data needed to
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java
index 8a1998a..8bf1a6b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java
@@ -20,7 +20,10 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
/**
* Contains the javascript chart definition for an IE8 d3 Stacked Bar graph chart.
- * Curr
+ * A deferred representation for IE8 rendering currently not implemented.
+ * IE8 cannot render SVG so this implementation is not defined.
+ * If a shim for IE8 to render becomes practical then this could be useful.
+ * Another option here is a HTML div graph representation or a just an HTML table.
*
* @author Mike Thompson
*/
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 21e4774..5f43d42 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -18,14 +18,16 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph;
/**
* Contains the javascript chart definition for a d3 Stacked Bar graph chart.
+ * The purpose of this class is the fill the div element with id: '#rChart-[resourceId]-[metricId]'.
+ * with SVG instructions to draw a d3 graph (in this case a stacked bar graph).
*
* @author Mike Thompson
*/
-public class StackedBarMetricGraphImpl extends AbstractGraph {
+public class StackedBarMetricGraphImpl extends AbstractMetricGraph {
/**
* GWT constructor for GWT.create() deferred instantiation.
@@ -46,28 +48,28 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
// create a chartContext object (from rhq.js) with the data required to render to a chart
// this same data could be passed to different chart types
// This way, we are decoupled from the dependency on globals and JSNI and kept all the java interaction right here.
- chartContext = new $wnd.ChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHeight()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getJsonMetrics()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getXAxisTitle()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitle()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getYAxisUnits()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitleMinLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitleAvgLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitlePeakLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartDownLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartUnknownLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartNoDataLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverEndLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverPeriodLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverDateFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::isPortalGraph()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getPortalId()()
+ chartContext = new $wnd.ChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHeight()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getJsonMetrics()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getXAxisTitle()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitle()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getYAxisUnits()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitleMinLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitleAvgLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTitlePeakLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartDownLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartUnknownLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartNoDataLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverEndLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverPeriodLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::isPortalGraph()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::getPortalId()()
);
@@ -466,7 +468,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
function createAvgLines() {
var showBarAvgTrendline =
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::showBarAvgTrendLine()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractMetricGraph::showBarAvgTrendLine()(),
barAvgLine = $wnd.d3.svg.line()
.interpolate("linear")
.defined(function (d) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index 448a08f..e5b219b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -44,7 +44,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphLis
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3Graph;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.util.Log;
@@ -72,7 +72,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
destroyMembers();
- addMember(graphDateTimeRangeEditor);
+ addMember(buttonBarDateTimeRangeEditor);
if (showAvailabilityGraph) {
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
// first step in 2 step to create d3 chart
@@ -101,8 +101,8 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
*/
private void buildGraphs() {
- queryAvailability(EntityContext.forGroup(resourceGroup), graphDateTimeRangeEditor.getStartTime(),
- graphDateTimeRangeEditor.getEndTime(), null);
+ queryAvailability(EntityContext.forGroup(resourceGroup), buttonBarDateTimeRangeEditor.getStartTime(),
+ buttonBarDateTimeRangeEditor.getEndTime(), null);
ResourceTypeRepository.Cache.getInstance().getResourceTypes(resourceGroup.getResourceType().getId(),
EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
@@ -129,7 +129,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
}
GWTServiceLookup.getMeasurementDataService().findDataForCompatibleGroup(resourceGroup.getId(),
- measDefIdArray, graphDateTimeRangeEditor.getStartTime(), graphDateTimeRangeEditor.getEndTime(), 60,
+ measDefIdArray, buttonBarDateTimeRangeEditor.getStartTime(), buttonBarDateTimeRangeEditor.getEndTime(), 60,
new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
@Override
public void onFailure(Throwable caught) {
@@ -198,7 +198,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
graph.setMetricGraphData(metricGraphData);
- MetricD3GraphView graphView = new MetricD3GraphView(graph);
+ MetricD3Graph graphView = new MetricD3Graph(graph);
graphView.setWidth("95%");
graphView.setHeight(MULTI_CHART_HEIGHT);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index c19cdab..3041b33 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -46,7 +46,7 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.ButtonBarDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
@@ -112,13 +112,13 @@ public class D3GraphListView extends AbstractD3GraphListView {
}
private void commonConstructorSettings() {
- graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs,this);
+ buttonBarDateTimeRangeEditor = new ButtonBarDateTimeRangeEditor(measurementUserPrefs,this);
setOverflow(Overflow.HIDDEN);
}
@Deprecated
public void addSetButtonClickHandler(ClickHandler clickHandler) {
- Log.debug("measurementRangeEditor " + graphDateTimeRangeEditor);
+ Log.debug("measurementRangeEditor " + buttonBarDateTimeRangeEditor);
// graphDateTimeRangeEditor.getSetButton().addClickHandler(clickHandler);
}
@@ -128,8 +128,8 @@ public class D3GraphListView extends AbstractD3GraphListView {
Log.debug("D3GraphListView.onDraw() for: " + resource.getName());
destroyMembers();
- addMember(graphDateTimeRangeEditor);
- graphDateTimeRangeEditor.createDateSliderMarker();
+ addMember(buttonBarDateTimeRangeEditor);
+ buttonBarDateTimeRangeEditor.createDateSliderMarker();
if (showAvailabilityGraph) {
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resource.getId()));
@@ -193,8 +193,8 @@ public class D3GraphListView extends AbstractD3GraphListView {
final long startTimer = System.currentTimeMillis();
if(null != availabilityGraph){
- queryAvailability(EntityContext.forResource(resource.getId()), graphDateTimeRangeEditor.getStartTime(),
- graphDateTimeRangeEditor.getEndTime(), null);
+ queryAvailability(EntityContext.forResource(resource.getId()), buttonBarDateTimeRangeEditor.getStartTime(),
+ buttonBarDateTimeRangeEditor.getEndTime(), null);
}
ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(),
@@ -270,7 +270,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
private void queryMetricData(final int[] measDefIdArray, final CountDownLatch countDownLatch) {
GWTServiceLookup.getMeasurementDataService().findDataForResource(resource.getId(), measDefIdArray,
- graphDateTimeRangeEditor.getStartTime(), graphDateTimeRangeEditor.getEndTime(), 60,
+ buttonBarDateTimeRangeEditor.getStartTime(), buttonBarDateTimeRangeEditor.getEndTime(), 60,
new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
@Override
public void onFailure(Throwable caught) {
@@ -376,7 +376,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
measurementDefinition, data, measurementOOBCompositeList );
StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
graph.setMetricGraphData(metricGraphData);
- MetricD3GraphView graphView = new MetricD3GraphView(graph);
+ MetricD3Graph graphView = new MetricD3Graph(graph);
graphView.setWidth("95%");
graphView.setHeight(height);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
new file mode 100644
index 0000000..f0f1162
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java
@@ -0,0 +1,179 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
+
+import com.google.gwt.user.client.Timer;
+import com.smartgwt.client.widgets.HTMLFlow;
+
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+
+/**
+ * A D3 graph implementation for graphing Resource metrics.
+ * Just the graph only. No avail graph no buttons just he graph.
+ */
+public class MetricD3Graph extends EnhancedVLayout {
+
+ protected StackedBarMetricGraphImpl graph;
+ private HTMLFlow graphDiv = null;
+ protected Timer refreshTimer;
+
+ /**
+ * This constructor is for the use case in the Dashboard where we dont actually
+ * have a entity or measurement yet.
+ */
+ public MetricD3Graph() {
+ super();
+ }
+
+ public MetricD3Graph(StackedBarMetricGraphImpl graph) {
+ super();
+ this.graph = graph;
+ setHeight100();
+ setWidth100();
+ }
+
+ /**
+ * Svg definitions for patterns and gradients to use on SVG shapes.
+ * @return xml String
+ */
+ private static String getSvgDefs() {
+ return " <defs>"
+ + " <linearGradient id=\"headerGrad\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">"
+ + " <stop offset=\"0%\" style=\"stop-color:#E6E6E6;stop-opacity:1\"/>"
+ + " <stop offset=\"100%\" style=\"stop-color:#F0F0F0;stop-opacity:1\"/>"
+ + " </linearGradient>"
+ + " <pattern id=\"noDataStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
+ + " width=\"6\" height=\"3\">"
+ + " <path d=\"M 0 0 6 0\" style=\"stroke:#CCCCCC; fill:none;\"/>"
+ + " </pattern>"
+ + " <pattern id=\"unknownStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
+ + " width=\"6\" height=\"3\">"
+ + " <path d=\"M 0 0 6 0\" style=\"stroke:#2E9EC2; fill:none;\"/>"
+ + " </pattern>"
+ + "<pattern id=\"diagonalHatchFill\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
+ + "<g style=\"fill:none; stroke:black; stroke-width:1\">"
+ + "<path d=\"M0 90 l15,15\"/>"
+ + "<path d=\"M0 75 l30,30\"/>"
+ + "<path d=\"M0 60 l45,45\"/>"
+ + "<path d=\"M0 45 l60,60\"/>"
+ + "<path d=\"M0 30 l75,75\"/>"
+ + "<path d=\"M0 15 l90,90\"/>"
+ + "<path d=\"M0 0 l105,105\"/>"
+ + "<path d=\"M15 0 l90,90\"/>"
+ + "<path d=\"M30 0 l75,75\"/>"
+ + "<path d=\"M45 0 l60,60\"/>"
+ + "<path d=\"M60 0 l45,45\"/>"
+ + "<path d=\"M75 0 l30,30\"/>"
+ + "<path d=\"M90 0 l15,15\"/>"
+ + "</g>"
+ + "</pattern>"
+ + "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
+ + "<g style=\"fill:none; stroke:black; stroke-width:1\">" + "<path d=\"M0 90 l15,15\"/>"
+ + "<path d=\"M0 75 l30,30\"/>" + "<path d=\"M0 60 l45,45\"/>" + "<path d=\"M0 45 l60,60\"/>"
+ + "<path d=\"M0 30 l75,75\"/>" + "<path d=\"M0 15 l90,90\"/>" + "<path d=\"M0 0 l105,105\"/>"
+ + "<path d=\"M15 0 l90,90\"/>" + "<path d=\"M30 0 l75,75\"/>" + "<path d=\"M45 0 l60,60\"/>"
+ + "<path d=\"M60 0 l45,45\"/>" + "<path d=\"M75 0 l30,30\"/>" + "<path d=\"M90 0 l15,15\"/>" + "</g>"
+ + "</pattern>"
+ + "<pattern id=\"downStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
+ + " width=\"6\" height=\"3\">"
+ + "<path d=\"M 0 0 6 0\" style=\"stroke:#ff8a9a; fill:none;\"/>"
+ + "</pattern>" + "</defs>";
+ }
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ if (graph.getDefinition() != null) {
+ drawGraph();
+ }
+ }
+
+ @Override
+ public void parentResized() {
+ super.parentResized();
+ removeMembers(getMembers());
+ drawGraph();
+ }
+
+ /**
+ * Setup the page elements especially the div and svg elements that serve as
+ * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
+ * Later the drawJsniGraph() is called to actually fill in the div/svg element
+ * created here with the actual svg element.
+ *
+ */
+ protected void drawGraph() {
+ Log.debug("drawGraph marker in MetricD3Graph for: " + getFullChartId() + " " + graph.getChartTitle());
+
+ StringBuilder divAndSvgDefs = new StringBuilder();
+ divAndSvgDefs
+ .append("<div id=\""
+ + getFullChartId()
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
+ + getChartHeight() + "px;\">");
+ divAndSvgDefs.append(getSvgDefs());
+ divAndSvgDefs.append("</svg></div>");
+
+ if (null != graphDiv) {
+ removeMember(graphDiv);
+ }
+
+ graphDiv = new HTMLFlow(divAndSvgDefs.toString());
+ graphDiv.setWidth100();
+ graphDiv.setHeight100();
+ addMember(graphDiv);
+
+ new Timer() {
+ @Override
+ public void run() {
+ drawJsniChart();
+ }
+ }.schedule(200);
+ }
+
+ /**
+ * Delegate the call to rendering the JSNI chart.
+ * This way the chart type can be swapped out at any time.
+ */
+ public void drawJsniChart() {
+ graph.drawJsniChart();
+ }
+
+ public String getFullChartId() {
+ return "rChart-" + graph.getMetricGraphData().getChartId();
+
+ }
+
+ public Integer getChartHeight() {
+ return graph.getMetricGraphData().getChartHeight();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ }
+
+ @Override
+ public void hide() {
+ super.hide();
+ }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
deleted file mode 100644
index 21025fc..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import com.google.gwt.user.client.Timer;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-
-/**
- * A D3 graph implementation for graphing Resource metrics.
- */
-public class MetricD3GraphView extends EnhancedVLayout {
-
- protected StackedBarMetricGraphImpl graph;
- private HTMLFlow graphDiv = null;
- protected Timer refreshTimer;
-
- /**
- * This constructor is for the use case in the Dashboard where we dont actually
- * have a entity or measurement yet.
- */
- public MetricD3GraphView() {
- super();
- }
-
- public MetricD3GraphView(StackedBarMetricGraphImpl graph) {
- super();
- this.graph = graph;
- setHeight100();
- setWidth100();
- }
-
- /**
- * Svg definitions for patterns and gradients to use on SVG shapes.
- * @return xml String
- */
- private static String getSvgDefs() {
- return " <defs>"
- + " <linearGradient id=\"headerGrad\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">"
- + " <stop offset=\"0%\" style=\"stop-color:#E6E6E6;stop-opacity:1\"/>"
- + " <stop offset=\"100%\" style=\"stop-color:#F0F0F0;stop-opacity:1\"/>"
- + " </linearGradient>"
- + " <pattern id=\"noDataStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
- + " width=\"6\" height=\"3\">"
- + " <path d=\"M 0 0 6 0\" style=\"stroke:#CCCCCC; fill:none;\"/>"
- + " </pattern>"
- + " <pattern id=\"unknownStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
- + " width=\"6\" height=\"3\">"
- + " <path d=\"M 0 0 6 0\" style=\"stroke:#2E9EC2; fill:none;\"/>"
- + " </pattern>"
- + "<pattern id=\"diagonalHatchFill\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
- + "<g style=\"fill:none; stroke:black; stroke-width:1\">"
- + "<circle cx=\"0\" cy=\"0\" r=\"1000\" fill=\"grey\"/>"
- + "<path d=\"M0 90 l15,15\"/>"
- + "<path d=\"M0 75 l30,30\"/>"
- + "<path d=\"M0 60 l45,45\"/>"
- + "<path d=\"M0 45 l60,60\"/>"
- + "<path d=\"M0 30 l75,75\"/>"
- + "<path d=\"M0 15 l90,90\"/>"
- + "<path d=\"M0 0 l105,105\"/>"
- + "<path d=\"M15 0 l90,90\"/>"
- + "<path d=\"M30 0 l75,75\"/>"
- + "<path d=\"M45 0 l60,60\"/>"
- + "<path d=\"M60 0 l45,45\"/>"
- + "<path d=\"M75 0 l30,30\"/>"
- + "<path d=\"M90 0 l15,15\"/>"
- + "</g>"
- + "</pattern>"
- + "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
- + "<g style=\"fill:none; stroke:black; stroke-width:1\">" + "<path d=\"M0 90 l15,15\"/>"
- + "<path d=\"M0 75 l30,30\"/>" + "<path d=\"M0 60 l45,45\"/>" + "<path d=\"M0 45 l60,60\"/>"
- + "<path d=\"M0 30 l75,75\"/>" + "<path d=\"M0 15 l90,90\"/>" + "<path d=\"M0 0 l105,105\"/>"
- + "<path d=\"M15 0 l90,90\"/>" + "<path d=\"M30 0 l75,75\"/>" + "<path d=\"M45 0 l60,60\"/>"
- + "<path d=\"M60 0 l45,45\"/>" + "<path d=\"M75 0 l30,30\"/>" + "<path d=\"M90 0 l15,15\"/>" + "</g>"
- + "</pattern>"
- + " <pattern id=\"downStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
- + " width=\"6\" height=\"3\">"
- + " <path d=\"M 0 0 6 0\" style=\"stroke:#ff8a9a; fill:none;\"/>"
- + " </pattern>" + "</defs>";
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- if (graph.getDefinition() != null) {
- drawGraph();
- }
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- drawGraph();
- }
-
- /**
- * Setup the page elements especially the div and svg elements that serve as
- * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
- * Later the drawJsniGraph() is called to actually fill in the div/svg element
- * created here with the actual svg element.
- *
- */
- protected void drawGraph() {
- Log.debug("drawGraph marker in MetricD3Graph for: " + getFullChartId() + " " + graph.getChartTitle());
-
- StringBuilder divAndSvgDefs = new StringBuilder();
- divAndSvgDefs
- .append("<div id=\""
- + getFullChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
- + getChartHeight() + "px;\">");
- divAndSvgDefs.append(getSvgDefs());
- divAndSvgDefs.append("</svg></div>");
-
- if (null != graphDiv) {
- removeMember(graphDiv);
- }
-
- graphDiv = new HTMLFlow(divAndSvgDefs.toString());
- graphDiv.setWidth100();
- graphDiv.setHeight100();
- addMember(graphDiv);
-
- new Timer() {
- @Override
- public void run() {
- //@todo: this is a hack around timing issue of jsni not seeing the DOM
- drawJsniChart();
- }
- }.schedule(200);
- }
-
- /**
- * Delegate the call to rendering the JSNI chart.
- * This way the chart type can be swapped out at any time.
- */
- public void drawJsniChart() {
- graph.drawJsniChart();
- }
-
- public String getFullChartId() {
- return "rChart-" + graph.getMetricGraphData().getChartId();
-
- }
-
- public Integer getChartHeight() {
- return graph.getMetricGraphData().getChartHeight();
- }
-
- @Override
- public void destroy() {
- super.destroy();
- }
-
- @Override
- public void hide() {
- super.hide();
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index b45c7ce..17e05dc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -128,7 +128,7 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
int i = 0;
for (ListGridRecord record : selection) {
Integer defId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_METRIC_DEF_ID);
- definitionIds[i++] = defId.intValue();
+ definitionIds[i++] = defId;
String name = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_NAME);
String label = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_LABEL);
@@ -185,7 +185,7 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
});
- addTableAction("Add To Dashboard", new TableAction() {
+ addTableAction(MSG.view_measureTable_addToDashboard(), new TableAction() {
@Override
public boolean isEnabled(ListGridRecord[] selection) {
@@ -256,7 +256,7 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
df.setNumCols(4);
df.setDataSource(getDataSource());
- IButton saveButton = new IButton("Save");
+ IButton saveButton = new IButton("Mike");
IButton cancelButton = new IButton("Done");
HLayout hLayout = new HLayout(10);
@@ -285,11 +285,9 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
public void onSuccess(PageList<ResourceComposite> results) {
if (!results.isEmpty()) {
Resource resource = results.get(0).getResource();
-
D3GraphListView graphListView = D3GraphListView.createSingleGraph(resource, definitionId, false);
-
}
}
});
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index bee2d4e..bd0ba1f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -1752,6 +1752,7 @@ view_measureRange_last = Time Range - Previous
view_measureRange_simple = Simple...
view_measureRange_start = Time Range - Start
view_measureTable_chartMetricValues = Chart Selected Metrics
+view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_getLive = Get Live Value
view_measureTable_getLive_failure = Cannot get live values for those metrics. Make sure the agent is running and the managed resource is up.
view_measureTable_live_title = Live Data
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 03dd890..f0271b3 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1765,6 +1765,7 @@ view_login_welcomeMsg = VÃtejte v {0}! <br/><br/> VloÅŸte/zmÄÅte následujÃc
view_measureRange_last = ÄasovÃœ rozsah - PÅedchozÃ
view_measureRange_simple = Jednoduché...
view_measureRange_start = ÄasovÃœ rozsah - Start
+##view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_chartMetricValues = Vykreslit vybraná mÄÅenÃ
view_measureTable_getLive = ZÃskat aktuálnà hodnotu
view_measureTable_getLive_failure = NepodaÅilo se zÃskat hodnoty tÄchto mÄÅenÃ. UjistÄte se, ÅŸe agent bÄÅŸÃ a ÅŸe spravovanÃœ zdroj také.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 32b26af..c204267 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1542,6 +1542,7 @@ view_login_registerUser = Benutzer Anlegen
view_measureRange_last = Letzte
view_measureRange_simple = Einfach...
view_measureRange_start = Zeitraum - Start
+##view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_chartMetricValues = Graphen fÌr ausgewÀhlte Metriken anzeigen
view_measureTable_getLive = Aktuellen Wert holen
##view_measureTable_startBeforeEnd = Start time should be before the end time.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index ad61a00..80ed6e6 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1737,6 +1737,7 @@ view_login_welcomeMsg = {0}ãžãããã! <br/><br/> ç»é²ãå®æããã
view_measureRange_last = æéã®ç¯å² - çŽå
view_measureRange_simple = ã·ã³ãã«...
view_measureRange_start = æéã®ç¯å² - éå§
+##view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_chartMetricValues = éžæãããã¡ããªãã¯ã¹ãå³ã«æã
view_measureTable_getLive = åäœäžã®å€ã®ååŸ
view_measureTable_getLive_failure = ãããã®ã¡ããªãã¯ã¹ã®åäœäžã®å€ãååŸã§ããŸããã§ããã ãšãŒãžã§ã³ãã¯å®è¡äžã§ç®¡çãªãœãŒã¹ã¯äœåäžã§ããããšã確èªããŠãã ããã
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index ebb6309..7a24dee 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -1459,6 +1459,7 @@ view_login_registerUser = ì¬ì©ì ë±ë¡
view_measureRange_last = ìê° ë²ì - ìŽì
view_measureRange_simple = ëšì...
view_measureRange_start = ìê° ë²ì - ìì
+##view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_chartMetricValues = ì íë íµê³ ì°šíž
view_measureTable_getLive = ëŒìŽëž ê° ê°ì žì€êž°
view_measureTable_getLive_failure = ìŽë¬í íµê³ì ëŒìŽëž ê°ì ê°ì žì¬ ì ììµëë€. ììŽì ížë ì€íì€ìž êŽëŠ¬ 늬ìì€ê° ìë ì€ìì íìžíììì€.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 133ad89..73ae1b0 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -1768,6 +1768,7 @@ view_measureRange_minutes = {0} Minutos
view_measureRange_range = Faixa
view_measureRange_simple = Simples...
view_measureRange_start = Time Range - Start
+##view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_chartMetricValues = Chart Selected Metrics
view_measureTable_getLive = Get Live Value
view_measureTable_getLive_failure = Cannot get live values for those metrics. Make sure the agent is running and the managed resource is up.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index c393b98..b442269 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -1693,6 +1693,7 @@
#view_measureRange_last = Time Range - Previous
#view_measureRange_simple = Simple...
#view_measureRange_start = Time Range - Start
+##view_measureTable_addToDashboard = Add To Dashboard
#view_measureTable_chartMetricValues = Chart Selected Metrics
#view_measureTable_getLive = Get Live Value
#view_measureTable_getLive_failure = Cannot get live values for those metrics. Make sure the agent is running and the managed resource is up.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 8b0da6d..c544469 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -1738,6 +1738,7 @@ view_login_registerUser = \u7528\u6237\u6ce8\u518c
view_measureRange_last = \u65f6\u95f4\u8303\u56f4 - \u5148\u524d\u7684
view_measureRange_simple = \u4e00\u822c...
view_measureRange_start = \u65f6\u95f4\u8303\u56f4 - \u8d77\u59cb
+##view_measureTable_addToDashboard = Add To Dashboard
view_measureTable_chartMetricValues = \u751f\u6210\u6307\u6807\u56fe
view_measureTable_getLive = \u53d6\u5f97\u6d3b\u52a8\u6570\u636e
view_measureTable_getLive_failure = Cannot get live values for those metrics. Make sure the agent is running and the managed resource is up.
commit dcea2d646c70da1b800e7aaf6dabdcf8d9b7b63e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 4 10:05:08 2013 -0700
First iteration consolidated metrics tab with sparklines and expandable graphs.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index 91db630..c15bcae 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -130,7 +130,7 @@ public class ResourceDetailView extends
private SubTab summaryActivity;
private SubTab summaryTimeline;
private SubTab monitorNewGraphs;
- private SubTab monitorTables;
+ private SubTab metricsTables;
private SubTab monitorTraits;
private SubTab monitorAvail;
private SubTab monitorSched;
@@ -198,13 +198,13 @@ public class ResourceDetailView extends
monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
- monitorTables = new SubTab(monitoringTab, new ViewName("Tables", MSG.view_tabs_common_tables()), null);
+ metricsTables = new SubTab(monitoringTab, new ViewName("Metrics", MSG.view_tabs_common_tables()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
monitorAvail = new SubTab(monitoringTab, new ViewName("Availability", MSG.view_tabs_common_availability()),
null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- monitoringTab.registerSubTabs(monitorTables, monitorNewGraphs, monitorTraits, monitorAvail,
+ monitoringTab.registerSubTabs(metricsTables, monitorNewGraphs, monitorTraits, monitorAvail,
monitorSched, monitorCallTime);
tabs.add(monitoringTab);
@@ -408,7 +408,7 @@ public class ResourceDetailView extends
return new MeasurementTableView(resource.getId());
}
};
- updateSubTab(this.monitoringTab, this.monitorTables, visible, true, viewFactory);
+ updateSubTab(this.monitoringTab, this.metricsTables, visible, true, viewFactory);
visible = hasMetricsOfType(this.resourceComposite, DataType.TRAIT);
viewFactory = (!visible) ? null : new ViewFactory() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 451d9a3..c19cdab 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -91,7 +91,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
}
- public static D3GraphListView createSingleGraph(Resource resource, Integer measurementId) {
+ public static D3GraphListView createSingleGraphNoAvail(Resource resource, Integer measurementId) {
return D3GraphListView.createSingleGraph(resource, measurementId, false);
}
@@ -146,7 +146,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
vLayout.setHeight100();
if (resource != null) {
- buildGraphs();
+ queryAndBuildGraphs();
}
addMember(vLayout);
}
@@ -154,7 +154,6 @@ public class D3GraphListView extends AbstractD3GraphListView {
public void redrawGraphs() {
this.onDraw();
availabilityGraph.drawJsniChart();
- //graphDateTimeRangeEditor.drawJsniDateSlider();
}
@Override
@@ -190,11 +189,13 @@ public class D3GraphListView extends AbstractD3GraphListView {
* Build whatever graph (summary or not) by grabbing the MeasurementDefinitions
* that are defined for the resource and then querying the metric and availability data.
*/
- private void buildGraphs() {
+ private void queryAndBuildGraphs() {
final long startTimer = System.currentTimeMillis();
- queryAvailability(EntityContext.forResource(resource.getId()), graphDateTimeRangeEditor.getStartTime(),
+ if(null != availabilityGraph){
+ queryAvailability(EntityContext.forResource(resource.getId()), graphDateTimeRangeEditor.getStartTime(),
graphDateTimeRangeEditor.getEndTime(), null);
+ }
ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(),
EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
@@ -250,7 +251,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
determineGraphsToBuild(metricsDataList, measurementDefinitions, definitionIds);
}
// There is a weird timing case when availabilityGraph can be null
- if (availabilityGraph != null) {
+ if (null != availabilityGraph) {
// we only need the first metricData since we are only taking the
// availability data set in there for the dropdowns already
availabilityGraph.setAvailabilityList(availabilityList);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java
index 32975b4..561ea09 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableDataSource.java
@@ -6,6 +6,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.Record;
+import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
@@ -42,6 +43,7 @@ public class MeasurementTableDataSource extends RPCDataSource<MetricDisplaySumma
public static final String FIELD_METRIC_SCHED_ID = "schedId";
public static final String FIELD_METRIC_UNITS = "units";
public static final String FIELD_METRIC_NAME = "name";
+ public static final String FIELD_RESOURCE_ID = "resourceId";
private int resourceId;
@@ -62,6 +64,22 @@ public class MeasurementTableDataSource extends RPCDataSource<MetricDisplaySumma
nameField.setWidth("30%");
fields.add(nameField);
+ nameField.setCellFormatter(new CellFormatter() {
+ @Override
+ public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
+ if (value == null) {
+ return "";
+ }
+ String commaDelimitedList = "5, 10, 20, 25";
+ //String formattedValue = StringUtility.escapeHtml(value.toString());
+ String contents= "<span id='sparkline_" + resourceId + "-"+ record.getAttributeAsInt("FIELD_METRIC_DEF_ID")
+ + "' class='dynamicsparkline' width='0' " + "values='"
+ + commaDelimitedList + "'>...</span>";
+ return contents;
+
+ }
+ });
+
ListGridField alertsField = new ListGridField(FIELD_ALERT_COUNT, MSG.common_title_alerts());
alertsField.setWidth("10%");
fields.add(alertsField);
@@ -109,6 +127,7 @@ public class MeasurementTableDataSource extends RPCDataSource<MetricDisplaySumma
record.setAttribute(FIELD_METRIC_SCHED_ID, from.getScheduleId());
record.setAttribute(FIELD_METRIC_UNITS, from.getUnits());
record.setAttribute(FIELD_METRIC_NAME, from.getMetricName());
+ record.setAttribute(FIELD_RESOURCE_ID, resourceId);
return record;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index c6ad891..b45c7ce 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -28,19 +28,32 @@ import java.util.Set;
import java.util.TreeSet;
import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.types.ExpansionMode;
import com.smartgwt.client.types.SelectionStyle;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.CloseClickEvent;
import com.smartgwt.client.widgets.events.CloseClickHandler;
+import com.smartgwt.client.widgets.events.DrawEvent;
+import com.smartgwt.client.widgets.events.DrawHandler;
+import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
+import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordExpandEvent;
+import com.smartgwt.client.widgets.grid.events.RecordExpandHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.measurement.MeasurementData;
import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.composite.ResourceComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -48,17 +61,21 @@ import org.rhq.enterprise.gui.coregui.client.components.FullHTMLPane;
import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.components.table.Table;
import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.drift.DriftSnapshotDataSource;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.InventoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.summary.AbstractActivityView.ChartViewWindow;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/**
- * Views a resource's measurements in a tabular view.
+ * Views a resource's metrics in a tabular view with sparkline graph
+ * and optional detailed graph .
*
* @author John Mazzitelli
+ * @author Mike Thompson
*/
public class MeasurementTableView extends Table<MeasurementTableDataSource> {
@@ -70,10 +87,30 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
setDataSource(new MeasurementTableDataSource(resourceId));
}
+ /**
+ * Creates this Table's list grid (called by onInit()). Subclasses can override this if they require a custom subclass
+ * of ListGrid.
+ *
+ * @return this Table's list grid (must be an instance of ListGrid)
+ */
+ @Override
+ protected ListGrid createListGrid() {
+ return new MetricsTableListGrid();
+ }
+
protected void configureTable() {
ArrayList<ListGridField> fields = getDataSource().getListGridFields();
setListGridFields(fields.toArray(new ListGridField[0]));
- addExtraWidget(new UserPreferencesMeasurementRangeEditor(), true);
+ this.getListGrid().setCanExpandRecords(true);
+ this.getListGrid().addRecordExpandHandler(new RecordExpandHandler() {
+ @Override
+ public void onRecordExpand(RecordExpandEvent recordExpandEvent) {
+ Log.debug("Record Expanded: ");
+
+ }
+ });
+
+ //addExtraWidget(new UserPreferencesMeasurementRangeEditor(), true);
addTableAction(MSG.view_measureTable_getLive(), new TableAction() {
@Override
public boolean isEnabled(ListGridRecord[] selection) {
@@ -100,54 +137,56 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
units = MeasurementUnits.NONE.name();
}
- scheduleNamesAndUnits.put(name, new String[] { label, units });
+ scheduleNamesAndUnits.put(name, new String[]{label, units});
}
// actually go out and ask the agents for the data
GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId, definitionIds,
- new AsyncCallback<Set<MeasurementData>>() {
- @Override
- public void onSuccess(Set<MeasurementData> result) {
- if (result == null) {
- result = new HashSet<MeasurementData>(0);
- }
- ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
- for (MeasurementData data : result) {
- String[] nameAndUnits = scheduleNamesAndUnits.get(data.getName());
- if (nameAndUnits != null) {
- double doubleValue;
- if (data.getValue() instanceof Number) {
- doubleValue = ((Number) data.getValue()).doubleValue();
- } else {
- doubleValue = Double.parseDouble(data.getValue().toString());
- }
- String value = MeasurementConverterClient.formatToSignificantPrecision(
- new double[] { doubleValue }, MeasurementUnits.valueOf(nameAndUnits[1]), true)[0];
+ new AsyncCallback<Set<MeasurementData>>() {
+ @Override
+ public void onSuccess(Set<MeasurementData> result) {
+ if (result == null) {
+ result = new HashSet<MeasurementData>(0);
+ }
+ ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+ for (MeasurementData data : result) {
+ String[] nameAndUnits = scheduleNamesAndUnits.get(data.getName());
+ if (nameAndUnits != null) {
+ double doubleValue;
+ if (data.getValue() instanceof Number) {
+ doubleValue = ((Number)data.getValue()).doubleValue();
+ }
+ else {
+ doubleValue = Double.parseDouble(data.getValue().toString());
+ }
+ String value = MeasurementConverterClient.formatToSignificantPrecision(
+ new double[]{doubleValue}, MeasurementUnits.valueOf(nameAndUnits[1]), true)[0];
- ListGridRecord record = new ListGridRecord();
- record.setAttribute("name", nameAndUnits[0]);
- record.setAttribute("value", value);
- records.add(record);
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute("name", nameAndUnits[0]);
+ record.setAttribute("value", value);
+ records.add(record);
+ }
}
+ Collections.sort(records, new Comparator<ListGridRecord>() {
+ public int compare(ListGridRecord o1, ListGridRecord o2) {
+ return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+ }
+ });
+ showLiveData(records);
}
- Collections.sort(records, new Comparator<ListGridRecord>() {
- public int compare(ListGridRecord o1, ListGridRecord o2) {
- return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
- }
- });
- showLiveData(records);
- }
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
- }
- });
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+ }
+ });
}
});
- addTableAction(MSG.view_measureTable_chartMetricValues(), new TableAction() {
+ addTableAction("Add To Dashboard", new TableAction() {
+
@Override
public boolean isEnabled(ListGridRecord[] selection) {
return selection != null && selection.length > 0;
@@ -155,57 +194,10 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
@Override
public void executeAction(ListGridRecord[] selection, Object actionValue) {
- if (selection == null || selection.length == 0) {
- return;
- }
- final TreeSet<Integer> definitionIds = new TreeSet<Integer>();
- for (ListGridRecord record : selection) {
- Integer defId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_METRIC_DEF_ID);
- definitionIds.add(defId);
- }
-
- ResourceCriteria criteria = new ResourceCriteria();
- criteria.addFilterId(resourceId);
- criteria.fetchSchedules(true);
- GWTServiceLookup.getResourceService().findResourceCompositesByCriteria(criteria,
- new AsyncCallback<PageList<ResourceComposite>>() {
-
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getMessageCenter().notify(
- new Message(MSG.view_inventory_resource_loadFailed(String.valueOf(resourceId)),
- Message.Severity.Warning));
-
- CoreGUI.goToView(InventoryView.VIEW_ID.getName());
- }
-
- @Override
- public void onSuccess(PageList<ResourceComposite> result) {
- if (result.isEmpty()) {
- onFailure(new Exception(MSG.view_inventory_resource_loadFailed(String
- .valueOf(resourceId))));
- } else {
- final ResourceComposite resourceComposite = result.get(0);
-
- ChartViewWindow window = new ChartViewWindow("");
- final D3GraphListView graphListView = D3GraphListView.createMultipleGraphs(
- resourceComposite.getResource(), definitionIds, true);
- graphListView.addSetButtonClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- graphListView.redrawGraphs();
- }
- });
- window.addItem(graphListView);
- window.show();
- refreshTableInfo();
-
- }
- }
- });
}
});
+
}
private void showLiveData(ArrayList<ListGridRecord> records) {
@@ -242,4 +234,70 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
liveDataWindow.addItem(liveDataGrid);
liveDataWindow.show();
}
+
+ private class MetricsTableListGrid extends ListGrid {
+ public MetricsTableListGrid() {
+ super();
+
+ setCanExpandRecords(true);
+ setCanExpandMultipleRecords(true);
+ setExpansionMode(ExpansionMode.RELATED);
+ }
+
+ @Override
+ protected Canvas getExpansionComponent(final ListGridRecord record) {
+ final Integer definitionId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_METRIC_DEF_ID);
+ final Integer resourceId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_RESOURCE_ID);
+ VLayout vLayout = new VLayout(5);
+ vLayout.setPadding(5);
+ //vLayout.addMember(graphListView);
+
+ final DynamicForm df = new DynamicForm();
+ df.setNumCols(4);
+ df.setDataSource(getDataSource());
+
+ IButton saveButton = new IButton("Save");
+ IButton cancelButton = new IButton("Done");
+
+ HLayout hLayout = new HLayout(10);
+ hLayout.setAlign(Alignment.CENTER);
+ hLayout.addMember(saveButton);
+ hLayout.addMember(cancelButton);
+
+ vLayout.addMember(df);
+ vLayout.addMember(hLayout);
+
+
+ //locate resource reference
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterId(resourceId);
+
+ //locate the resource
+ GWTServiceLookup.getResourceService().findResourceCompositesByCriteria(criteria,
+ new AsyncCallback<PageList<ResourceComposite>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.debug("Error retrieving resource resource composite for resource [" + resourceId + "]:"
+ + caught.getMessage());
+ }
+
+ @Override
+ public void onSuccess(PageList<ResourceComposite> results) {
+ if (!results.isEmpty()) {
+ Resource resource = results.get(0).getResource();
+
+ D3GraphListView graphListView = D3GraphListView.createSingleGraph(resource, definitionId, false);
+
+
+
+ }
+ }
+ });
+
+ return vLayout;
+
+
+ }
+ }
+
}
commit 95ba38868f1876d8474fe29f588737a3c8e0d700
Merge: 255e6b7 861dc16
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 4 08:48:57 2013 -0700
Merge branch 'master' into mtho11/dual-slider-chart-control
commit 255e6b7074d2c10211eb06ca24e785143fcc6f2b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 31 12:56:23 2013 -0700
Fix merge conflict in Messages_de.properties.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index bc27bbd..4aad28e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -15,24 +15,24 @@ avail_chart_title_label = VerfÃŒgbarkeit
chart_date_label = Datum
##chart_down_label = Down
##chart_time_label = Start
-##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
-##chart_title_avg_label = Avg
-##chart_title_min_label = Min
-##chart_title_peak_label = Max
-##chart_hover_availability_label = Availability
-##chart_hover_availability_type_warn = MIXED
-##chart_hover_date_format = %m/%d/%y
+chart_unknown_label = Unbekannt
+chart_no_data_label = Keine Daten vorhanden
+chart_title_avg_label = Durchschn.
+chart_title_min_label = Min
+chart_title_peak_label = Max
+chart_hover_availability_label = VerfÃŒgbarkeit
+chart_hover_availability_type_warn = Gemischt
+chart_hover_date_format = %d.%m.%y
##chart_hover_time_format = %I:%M:%S %p
-##chart_ie_not_supported = Charting is not available for this browser.
+chart_ie_not_supported = Charting ist bei diesem Browser nicht unterstÃŒtzt
##chart_no_data_label = No Data
##chart_slider_button_bar_minute = Min
##chart_slider_button_bar_hour = Hour
##chart_slider_button_bar_day = Day
##chart_slider_button_bar_month = Month
##chart_slider_button_bar_year = Year
-##chart_hover_start_label = Start
-##chart_hover_end_label = End
+chart_hover_start_label = Start
+chart_hover_end_label = Ende
##chart_hover_period_label = Period
chart_hover_bar_label = Dauer
common_alert_high = HOCH
commit 3cae2a2f511def625b327e8e1cf031fd8816099f
Merge: 29b1871 32a4a3b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 31 12:51:00 2013 -0700
Merge cassandra master to slider graph controls. Fix merge conflict in Messages_de.properties.
diff --cc modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 56684d2,5e6013b..bc27bbd
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@@ -10,30 -10,25 +10,31 @@@
#
###################################
##avail_chart_down_label = DOWN
- ##avail_chart_title_label = Availability
+ avail_chart_title_label = VerfÃŒgbarkeit
##avail_chart_up_label = UP
- ##chart_date_label = Date
+ chart_date_label = Datum
##chart_down_label = Down
##chart_time_label = Start
-chart_unknown_label = Unbekannt
-chart_no_data_label = Keine Daten vorhanden
-chart_title_avg_label = Durchschn.
-chart_title_min_label = Min
-chart_title_peak_label = Max
-chart_hover_availability_label = VerfÃŒgbarkeit
-chart_hover_availability_type_warn = Gemischt
-chart_hover_date_format = %d.%m.%y
+##chart_unknown_label = Unknown
++##chart_no_data_label = No Data
+##chart_title_avg_label = Avg
+##chart_title_min_label = Min
+##chart_title_peak_label = Max
+##chart_hover_availability_label = Availability
+##chart_hover_availability_type_warn = MIXED
+##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
-chart_ie_not_supported = Charting ist bei diesem Browser nicht unterstÃŒtzt
-chart_hover_start_label = Start
-chart_hover_end_label = Ende
+##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
+##chart_hover_start_label = Start
+##chart_hover_end_label = End
##chart_hover_period_label = Period
- ##chart_hover_bar_label = Duration
+ chart_hover_bar_label = Dauer
common_alert_high = HOCH
common_alert_low = NIEDRIG
common_alert_medium = MITTEL
commit 29b1871084bb26e56aed03de01af0f079a0bd1aa
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 14:51:23 2013 -0700
[BZ 958754] Time units should have proper units for multi-line graphs. Updated the nvd3 javascript libraries to 0.9.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
index e405d2e..a547f21 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
@@ -135,7 +135,11 @@ d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {
gravity = gravity || 's';
dist = dist || 20;
- var body = parentContainer ? parentContainer : document.getElementsByTagName('body')[0];
+ var body = parentContainer;
+ if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) {
+ //If the parent element is an SVG element, place tooltip in the <body> element.
+ body = document.getElementsByTagName('body')[0];
+ }
container.innerHTML = content;
container.style.left = 0;
@@ -351,6 +355,19 @@ nv.utils.pjax = function(links, content) {
});
}
+/* For situations where 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 (svgTextElem instanceof d3.selection) {
+ var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""));
+ var textLength = svgTextElem.text().length;
+
+ return textLength * fontSize * 0.5;
+ }
+ return 0;
+};
nv.models.axis = function() {
//============================================================
@@ -1633,7 +1650,7 @@ nv.models.bulletChart = function() {
//------------------------------------------------------------
dispatch.on('tooltipShow', function(e) {
- e.key = data[0].title;
+ e.key = d.title;
if (tooltips) showTooltip(e, that.parentNode);
});
@@ -1788,6 +1805,7 @@ nv.models.cumulativeLineChart = function() {
, state = { index: 0, rescaleY: rescaleY }
, defaultState = null
, noData = 'No Data Available.'
+ , average = function(d) { return d.average }
, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
@@ -1985,6 +2003,7 @@ nv.models.cumulativeLineChart = function() {
gEnter.append('g').attr('class', 'nv-y nv-axis');
gEnter.append('g').attr('class', 'nv-background');
gEnter.append('g').attr('class', 'nv-linesWrap');
+ gEnter.append('g').attr('class', 'nv-avgLinesWrap');
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
@@ -2047,8 +2066,6 @@ nv.models.cumulativeLineChart = function() {
.text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
}
-
-
//------------------------------------------------------------
// Main Chart Component(s)
@@ -2066,16 +2083,51 @@ nv.models.cumulativeLineChart = function() {
.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 }));
+ }).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 }));
+ .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
//d3.transition(linesWrap).call(lines);
linesWrap.call(lines);
+ /*Handle average lines [AN-612] ----------------------------*/
+
+ //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; });
+
+ 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', function(d) { return y(average(d)); })
+ .attr('y2', function(d) { return y(average(d)); });
+
+ avgLines
+ .attr('x1',0)
+ .attr('x2',availableWidth)
+ .attr('y1', function(d) { return y(average(d)); })
+ .attr('y2', function(d) { return y(average(d)); });
+
+ avgLines.exit().remove();
+
+ //Create index line -----------------------------------------
var indexLine = linesWrap.selectAll('.nv-indexLine')
.data([index]);
@@ -2349,6 +2401,12 @@ nv.models.cumulativeLineChart = function() {
return chart;
};
+ chart.average = function(_) {
+ if(!arguments.length) return average;
+ average = _;
+ return chart;
+ };
+
//============================================================
@@ -2359,6 +2417,9 @@ nv.models.cumulativeLineChart = function() {
/* Normalize the data according to an index point. */
function indexify(idx, data) {
return data.map(function(line, i) {
+ if (!line.values) {
+ return line;
+ }
var v = lines.y()(line.values[idx], idx);
//TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
@@ -3533,9 +3594,13 @@ nv.models.indentedTree = function() {
// NEW ALIGNING CODE, TODO: clean up
if (align) {
+
var seriesWidths = [];
series.each(function(d,i) {
- seriesWidths.push(d3.select(this).select('text').node().getComputedTextLength() + 28); // 28 is ~ the width of the circle plus some padding
+ var legendText = d3.select(this).select('text');
+ var svgComputedTextLength = legendText.node().getComputedTextLength()
+ || nv.utils.calcApproxTextWidth(legendText);
+ seriesWidths.push(svgComputedTextLength + 28); // 28 is ~ the width of the circle plus some padding
});
//nv.log('Series Widths: ', JSON.stringify(seriesWidths));
@@ -4002,7 +4067,7 @@ nv.models.lineChart = function() {
// New addition to calculate position if SVG is scaled with viewBox, may move TODO: consider implementing everywhere else
if (offsetElement) {
var svg = d3.select(offsetElement).select('svg');
- var viewBox = svg.attr('viewBox');
+ var viewBox = (svg.node()) ? svg.attr('viewBox') : null;
if (viewBox) {
viewBox = viewBox.split(' ');
var ratio = parseInt(svg.style('width')) / viewBox[2];
@@ -6160,10 +6225,11 @@ nv.models.multiBar = function() {
groups.enter().append('g')
.style('stroke-opacity', 1e-6)
.style('fill-opacity', 1e-6);
- d3.transition(groups.exit())
- //.style('stroke-opacity', 1e-6)
- //.style('fill-opacity', 1e-6)
+
+
+ groups.exit()
.selectAll('rect.nv-bar')
+ .transition()
.delay(function(d,i) { return i * delay/ data[0].values.length })
.attr('y', function(d) { return stacked ? y0(d.y0) : y0(0) })
.attr('height', 0)
@@ -6259,7 +6325,7 @@ nv.models.multiBar = function() {
if (stacked)
- d3.transition(bars)
+ bars.transition()
.delay(function(d,i) { return i * delay / data[0].values.length })
.attr('y', function(d,i) {
@@ -6443,13 +6509,14 @@ nv.models.multiBarChart = function() {
, controls = nv.models.legend()
;
- var margin = {top: 30, right: 20, bottom: 30, left: 60}
+ var margin = {top: 30, right: 20, bottom: 50, left: 60}
, width = null
, height = null
, color = nv.utils.defaultColor()
, showControls = true
, showLegend = true
, reduceXTicks = true // if false a tick will show for every data point
+ , staggerLabels = false
, rotateLabels = 0
, tooltips = true
, tooltip = function(key, x, y, e, graph) {
@@ -6664,6 +6731,27 @@ nv.models.multiBarChart = function() {
.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) {
@@ -6853,6 +6941,12 @@ nv.models.multiBarChart = function() {
return chart;
}
+ chart.staggerLabels = function(_) {
+ if (!arguments.length) return staggerLabels;
+ staggerLabels = _;
+ return chart;
+ };
+
chart.tooltip = function(_) {
if (!arguments.length) return tooltip;
tooltip = _;
@@ -9327,7 +9421,7 @@ nv.models.scatter = function() {
})
);
- x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x }).concat(forceX)))
+ x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))
if (padData && data[0])
x.range([(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);
@@ -9353,6 +9447,14 @@ nv.models.scatter = function() {
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;
@@ -9399,8 +9501,16 @@ nv.models.scatter = function() {
return group.values
.map(function(point, pointIndex) {
// *Adding noise to make duplicates very unlikely
- // **Injecting series and point index for reference
- return [x(getX(point,pointIndex)) * (Math.random() / 1e12 + 1) , y(getY(point,pointIndex)) * (Math.random() / 1e12 + 1), groupIndex, pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates
+ // *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) + Math.random() * 1e-10;
+ var pY = getY(point,pointIndex) + Math.random() * 1e-10;
+
+ return [x(pX),
+ y(pY),
+ groupIndex,
+ pointIndex, point]; //temp hack to add noise untill 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!
@@ -9467,7 +9577,12 @@ nv.models.scatter = function() {
.attr('class', function(d,i) { return 'nv-path-'+i; });
pointPaths.exit().remove();
pointPaths
- .attr('d', function(d) { return 'M' + d.data.join('L') + 'Z'; });
+ .attr('d', function(d) {
+ if (d.data.length === 0)
+ return 'M 0 0'
+ else
+ return 'M' + d.data.join('L') + 'Z';
+ });
pointPaths
.on('click', function(d) {
@@ -11277,7 +11392,7 @@ nv.models.sparklinePlus = function() {
availableHeight = (height || parseInt(container.style('height')) || 400)
- margin.top - margin.bottom;
- var currentValue = sparkline.y()(data[data.length-1], data.length-1);
+
chart.update = function() { chart(selection) };
chart.container = this;
@@ -11304,6 +11419,8 @@ nv.models.sparklinePlus = function() {
container.selectAll('.nv-noData').remove();
}
+ var currentValue = sparkline.y()(data[data.length-1], data.length-1);
+
//------------------------------------------------------------
@@ -11350,7 +11467,7 @@ nv.models.sparklinePlus = function() {
var valueWrap = g.select('.nv-valueWrap');
-
+
var value = valueWrap.selectAll('.nv-currentValue')
.data([currentValue]);
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js
new file mode 100644
index 0000000..dc28049
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js
@@ -0,0 +1,6 @@
+(function(){function t(e,t){return(new Date(t,e+1,0)).getDate()}function n(e,t,n){return function(r,i,s){var o=e(r),u=[];o<r&&t(o);if(s>1)while(o<i){var a=new Date(+o);n(a)%s===0&&u.push(a),t(o)}else while(o<i)u.push(new Date(+o)),t(o);return u}}var e=window.nv||{};e.version="0.0.1a",e.dev=!0,window.nv=e,e.tooltip={},e.utils={},e.models={},e.charts={},e.graphs=[],e.logs={},e.dispatch=d3.dispatch("render_start","render_end"),e.dev&&(e.dispatch.on("render_start",function(t){e.logs.startTime=+(new Date)}),e.dispatch.on("render_end",function(t){e.logs.endTime=+(new Date),e.logs.totalTime=e.logs.endTime-e.logs.startTime,e.log("total",e.logs.totalTime)})),e.log=function(){if(e.dev&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(e.dev&&console.log&&Function.prototype.bind){var t=Function.prototype.bind.call(console.log,console);t.apply(console,arguments)}return arguments[arguments.length-1]},e.render=function(n){n=n||1,e.render.active=!0,e.dispatch.rend
er_start(),setTimeout(function(){var t,r;for(var i=0;i<n&&(r=e.render.queue[i]);i++)t=r.generate(),typeof r.callback==typeof Function&&r.callback(t),e.graphs.push(t);e.render.queue.splice(0,i),e.render.queue.length?setTimeout(arguments.callee,0):(e.render.active=!1,e.dispatch.render_end())},0)},e.render.active=!1,e.render.queue=[],e.addGraph=function(t){typeof arguments[0]==typeof Function&&(t={generate:arguments[0],callback:arguments[1]}),e.render.queue.push(t),e.render.active||e.render()},e.identity=function(e){return e},e.strip=function(e){return e.replace(/(\s|&)/g,"")},d3.time.monthEnd=function(e){return new Date(e.getFullYear(),e.getMonth(),0)},d3.time.monthEnds=n(d3.time.monthEnd,function(e){e.setUTCDate(e.getUTCDate()+1),e.setDate(t(e.getMonth()+1,e.getFullYear()))},function(e){return e.getMonth()}),function(){var t=window.nv.tooltip={};t.show=function(t,n,r,i,s,o){var u=document.createElement("div");u.className="nvtooltip "+(o?o:"xy-tooltip"),r=r||"s",i=i||20;var a=
s;if(!s||s.tagName.match(/g|svg/i))a=document.getElementsByTagName("body")[0];u.innerHTML=n,u.style.left=0,u.style.top=0,u.style.opacity=0,a.appendChild(u);var f=parseInt(u.offsetHeight),l=parseInt(u.offsetWidth),c=e.utils.windowSize().width,h=e.utils.windowSize().height,p=window.scrollY,d=window.scrollX,v,m;h=window.innerWidth>=document.body.scrollWidth?h:h-16,c=window.innerHeight>=document.body.scrollHeight?c:c-16;var g=function(e){var t=m;do isNaN(e.offsetTop)||(t+=e.offsetTop);while(e=e.offsetParent);return t},y=function(e){var t=v;do isNaN(e.offsetLeft)||(t+=e.offsetLeft);while(e=e.offsetParent);return t};switch(r){case"e":v=t[0]-l-i,m=t[1]-f/2;var b=y(u),w=g(u);b<d&&(v=t[0]+i>d?t[0]+i:d-b+v),w<p&&(m=p-w+m),w+f>p+h&&(m=p+h-w+m-f);break;case"w":v=t[0]+i,m=t[1]-f/2,b+l>c&&(v=t[0]-l-i),w<p&&(m=p+5),w+f>p+h&&(m=p-f-5);break;case"n":v=t[0]-l/2-5,m=t[1]+i;var b=y(u),w=g(u);b<d&&(v=d+5),b+l>c&&(v=v-l/2+5),w+f>p+h&&(m=p+h-w+m-f);break;case"s":v=t[0]-l/2,m=t[1]-f-i;var b=y(u),w=
g(u);b<d&&(v=d+5),b+l>c&&(v=v-l/2+5),p>w&&(m=p)}return u.style.left=v+"px",u.style.top=m+"px",u.style.opacity=1,u.style.position="absolute",u.style.pointerEvents="none",u},t.cleanup=function(){var e=document.getElementsByClassName("nvtooltip"),t=[];while(e.length)t.push(e[0]),e[0].style.transitionDelay="0 !important",e[0].style.opacity=0,e[0].className="nvtooltip-pending-removal";setTimeout(function(){while(t.length){var e=t.pop();e.parentNode.removeChild(e)}},500)}}(),e.utils.windowSize=function(){var e={width:640,height:480};return document.body&&document.body.offsetWidth&&(e.width=document.body.offsetWidth,e.height=document.body.offsetHeight),document.compatMode=="CSS1Compat"&&document.documentElement&&document.documentElement.offsetWidth&&(e.width=document.documentElement.offsetWidth,e.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(e.width=window.innerWidth,e.height=window.innerHeight),e},e.utils.windowResize=function(e){var t=windo
w.onresize;window.onresize=function(n){typeof t=="function"&&t(n),e(n)}},e.utils.getColor=function(t){return arguments.length?Object.prototype.toString.call(t)==="[object Array]"?function(e,n){return e.color||t[n%t.length]}:t:e.utils.defaultColor()},e.utils.defaultColor=function(){var e=d3.scale.category20().range();return function(t,n){return t.color||e[n%e.length]}},e.utils.customTheme=function(e,t,n){t=t||function(e){return e.key},n=n||d3.scale.category20().range();var r=n.length;return function(i,s){var o=t(i);return r||(r=n.length),typeof e[o]!="undefined"?typeof e[o]=="function"?e[o]():e[o]:n[--r]}},e.utils.pjax=function(t,n){function r(r){d3.html(r,function(r){var i=d3.select(n).node();i.parentNode.replaceChild(d3.select(r).select(n).node(),i),e.utils.pjax(t,n)})}d3.selectAll(t).on("click",function(){history.pushState(this.href,this.textContent,this.href),r(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&r(d3.event.sta
te)})},e.utils.calcApproxTextWidth=function(e){if(e instanceof d3.selection){var t=parseInt(e.style("font-size").replace("px","")),n=e.text().length;return n*t*.5}return 0},e.models.axis=function(){function d(r){return r.each(function(r){var d=d3.select(this),v=d.selectAll("g.nv-wrap.nv-axis").data([r]),m=v.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),g=m.append("g"),y=v.select("g");h!==null?e.ticks(h):(e.orient()=="top"||e.orient()=="bottom")&&e.ticks(Math.abs(i.range()[1]-i.range()[0])/100),d3.transition(y).call(e),p=p||e.scale();var b=e.tickFormat();b==null&&(b=p.tickFormat());var w=y.selectAll("text.nv-axislabel").data([s||null]);w.exit().remove();switch(e.orient()){case"top":w.enter().append("text").attr("class","nv-axislabel");var E=i.range().length==2?i.range()[1]:i.range()[i.range().length-1]+(i.range()[1]-i.range()[0]);w.attr("text-anchor","middle").attr("y",0).attr("x",E/2);if(o){var S=v.selectAll("g.nv-axisMaxMin").data(i.domain());S.enter().append("g"
).attr("class","nv-axisMaxMin").append("text"),S.exit().remove(),S.attr("transform",function(e,t){return"translate("+i(e)+",0)"}).select("text").attr("dy","0em").attr("y",-e.tickPadding()).attr("text-anchor","middle").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transform",function(e,t){return"translate("+i.range()[t]+",0)"})}break;case"bottom":var x=36,T=30,N=y.selectAll("g").select("text");if(a%360){N.each(function(e,t){var n=this.getBBox().width;n>T&&(T=n)});var C=Math.abs(Math.sin(a*Math.PI/180)),x=(C?C*T:T)+30;N.attr("transform",function(e,t,n){return"rotate("+a+" 0,0)"}).attr("text-anchor",a%360>0?"start":"end")}w.enter().append("text").attr("class","nv-axislabel");var E=i.range().length==2?i.range()[1]:i.range()[i.range().length-1]+(i.range()[1]-i.range()[0]);w.attr("text-anchor","middle").attr("y",x).attr("x",E/2);if(o){var S=v.selectAll("g.nv-axisMaxMin").data([i.domain()[0],i.domain()[i.domain().length-1]]);S.enter().append(
"g").attr("class","nv-axisMaxMin").append("text"),S.exit().remove(),S.attr("transform",function(e,t){return"translate("+(i(e)+(c?i.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",e.tickPadding()).attr("transform",function(e,t,n){return"rotate("+a+" 0,0)"}).attr("text-anchor",a?a%360>0?"start":"end":"middle").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transform",function(e,t){return"translate("+(i(e)+(c?i.rangeBand()/2:0))+",0)"})}l&&N.attr("transform",function(e,t){return"translate(0,"+(t%2==0?"0":"12")+")"});break;case"right":w.enter().append("text").attr("class","nv-axislabel"),w.attr("text-anchor",f?"middle":"begin").attr("transform",f?"rotate(90)":"").attr("y",f?-Math.max(t.right,n)+12:-10).attr("x",f?i.range()[0]/2:e.tickPadding());if(o){var S=v.selectAll("g.nv-axisMaxMin").data(i.domain());S.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),S.exit().remove(),S.attr("transf
orm",function(e,t){return"translate(0,"+i(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",e.tickPadding()).attr("text-anchor","start").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transform",function(e,t){return"translate(0,"+i.range()[t]+")"}).select("text").style("opacity",1)}break;case"left":w.enter().append("text").attr("class","nv-axislabel"),w.attr("text-anchor",f?"middle":"end").attr("transform",f?"rotate(-90)":"").attr("y",f?-Math.max(t.left,n)+12:-10).attr("x",f?-i.range()[0]/2:-e.tickPadding());if(o){var S=v.selectAll("g.nv-axisMaxMin").data(i.domain());S.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),S.exit().remove(),S.attr("transform",function(e,t){return"translate(0,"+p(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-e.tickPadding()).attr("text-anchor","end").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transfor
m",function(e,t){return"translate(0,"+i.range()[t]+")"}).select("text").style("opacity",1)}}w.text(function(e){return e}),o&&(e.orient()==="left"||e.orient()==="right")&&(y.selectAll("g").each(function(e,t){d3.select(this).select("text").attr("opacity",1);if(i(e)<i.range()[1]+10||i(e)>i.range()[0]-10)(e>1e-10||e<-1e-10)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0)}),i.domain()[0]==i.domain()[1]&&i.domain()[0]==0&&v.selectAll("g.nv-axisMaxMin").style("opacity",function(e,t){return t?0:1}));if(o&&(e.orient()==="top"||e.orient()==="bottom")){var k=[];v.selectAll("g.nv-axisMaxMin").each(function(e,t){try{t?k.push(i(e)-this.getBBox().width-4):k.push(i(e)+this.getBBox().width+4)}catch(n){t?k.push(i(e)-4):k.push(i(e)+4)}}),y.selectAll("g").each(function(e,t){if(i(e)<k[0]||i(e)>k[1])e>1e-10||e<-1e-10?d3.select(this).remove():d3.select(this).select("text").remove()})}u&&y.selectAll("line.tick").filter(function(e){return!parseFloat(Math.round(e*1
e5)/1e6)}).classed("zero",!0),p=i.copy()}),d}var e=d3.svg.axis(),t={top:0,right:0,bottom:0,left:0},n=75,r=60,i=d3.scale.linear(),s=null,o=!0,u=!0,a=0,f=!0,l=!1,c=!1,h=null;e.scale(i).orient("bottom").tickFormat(function(e){return e});var p;return d.axis=e,d3.rebind(d,e,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(d,i,"domain","range","rangeBand","rangeBands"),d.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,d):t},d.width=function(e){return arguments.length?(n=e,d):n},d.ticks=function(e){return arguments.length?(h=e,d):h},d.height=function(e){return arguments.length?(r=e,d):r},d.axisLabel=function(e){return arguments.length?(s=e,d):s},d.showMaxMin=function(e){return arguments.length?(o=e,d):o},d.highlightZero=function(e){return arguments.len
gth?(u=e,d):u},d.scale=function(t){return arguments.length?(i=t,e.scale(i),c=typeof i.rangeBands=="function",d3.rebind(d,i,"domain","range","rangeBand","rangeBands"),d):i},d.rotateYLabel=function(e){return arguments.length?(f=e,d):f},d.rotateLabels=function(e){return arguments.length?(a=e,d):a},d.staggerLabels=function(e){return arguments.length?(l=e,d):l},d},e.models.historicalBar=function(){function g(e){return e.each(function(e){var g=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);s.domain(d||d3.extent(e[0].values.map(u).concat(f))),c?s.range([g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range([0,g]),o.domain(v||d3.extent(e[0].values.map(a).concat(l))).range([b,0]);if(s.domain()[0]===s.domain()[1]||o.domain()[0]===o.domain()[1])singlePoint=!0;s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.
domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var E=w.selectAll("g.nv-wrap.nv-bar").data([e[0].values]),S=E.enter().append("g").attr("class","nvd3 nv-wrap nv-bar"),T=S.append("defs"),N=S.append("g"),C=E.select("g");N.append("g").attr("class","nv-bars"),E.attr("transform","translate("+t.left+","+t.top+")"),w.on("click",function(e,t){m.chartClick({data:e,index:t,pos:d3.event,id:i})}),T.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),E.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",b),C.attr("clip-path",h?"url(#nv-chart-clip-path-"+i+")":"");var k=E.select(".nv-bars").selectAll(".nv-bar").data(function(e){return e});k.exit().remove();var L=k.enter().append("rect").attr("x",0).attr("y",function(e,t){return o(Math.max(0,a(e,t)))}).attr("height",function(e,t){return Math.abs(o(a(e,t))-o(0))}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),m.elementMouseover({point:t,series:e[0],pos:[
s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),m.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){m.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){m.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});k.attr("fill",function(e,t){return p(e,t)}).attr("class",function(e,t,n){return(a(e,t)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+n+"-"+t}).attr("transform",function(t,n){return"translate("+(s(u(t,n))-g/e[0].values.length*.45)+",0)"}).attr("width",g/e[0].values.length*.9),d3.transition(k).attr("y",function(e,t){return a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t))}).attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)})}),g}var t={top:0,right:0,bottom:0,left:0
},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[],l=[0],c=!1,h=!0,p=e.utils.defaultColor(),d,v,m=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return g.dispatch=m,g.x=function(e){return arguments.length?(u=e,g):u},g.y=function(e){return arguments.length?(a=e,g):a},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.xScale=function(e){return arguments.length?(s=e,g):s},g.yScale=function(e){return arguments.length?(o=e,g):o},g.xDomain=function(e){return arguments.length?(d=e,g):d},g.yDomain=function(e){return arguments.length?(v=
e,g):v},g.forceX=function(e){return arguments.length?(f=e,g):f},g.forceY=function(e){return arguments.length?(l=e,g):l},g.padData=function(e){return arguments.length?(c=e,g):c},g.clipEdge=function(e){return arguments.length?(h=e,g):h},g.color=function(t){return arguments.length?(p=e.utils.getColor(t),g):p},g.id=function(e){return arguments.length?(i=e,g):i},g},e.models.bullet=function(){function p(e){return e.each(function(e,n){var l=a-t.left-t.right,p=f-t.top-t.bottom,d=d3.select(this),v=i.call(this,e,n).slice().sort(d3.descending),m=s.call(this,e,n).slice().sort(d3.descending),g=o.call(this,e,n).slice().sort(d3.descending),y=d3.scale.linear().domain(d3.extent(d3.merge([u,v]))).range(r?[l,0]:[0,l]),b=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(y.range());this.__chart__=y;var w=d3.min(v),E=d3.max(v),S=v[1],x=d.selectAll("g.nv-wrap.nv-bullet").data([e]),T=x.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),N=T.append("g"),C=x.select("g");N.append("re
ct").attr("class","nv-range nv-rangeMax"),N.append("rect").attr("class","nv-range nv-rangeAvg"),N.append("rect").attr("class","nv-range nv-rangeMin"),N.append("rect").attr("class","nv-measure"),N.append("path").attr("class","nv-markerTriangle"),x.attr("transform","translate("+t.left+","+t.top+")");var k=function(e){return Math.abs(b(e)-b(0))},L=function(e){return Math.abs(y(e)-y(0))},A=function(e){return e<0?b(e):b(0)},O=function(e){return e<0?y(e):y(0)};C.select("rect.nv-rangeMax").attr("height",p).attr("width",L(E>0?E:w)).attr("x",O(E>0?E:w)).datum(E>0?E:w),C.select("rect.nv-rangeAvg").attr("height",p).attr("width",L(S)).attr("x",O(S)).datum(S),C.select("rect.nv-rangeMin").attr("height",p).attr("width",L(E)).attr("x",O(E)).attr("width",L(E>0?w:E)).attr("x",O(E>0?w:E)).datum(E>0?w:E),C.select("rect.nv-measure").style("fill",c).attr("height",p/3).attr("y",p/3).attr("width",g<0?y(0)-y(g[0]):y(g[0])-y(0)).attr("x",O(g)).on("mouseover",function(){h.elementMouseover({value:g[0],
label:"Current",pos:[y(g[0]),p/2]})}).on("mouseout",function(){h.elementMouseout({value:g[0],label:"Current"})});var M=p/6;m[0]?C.selectAll("path.nv-markerTriangle").attr("transform",function(e){return"translate("+y(m[0])+","+p/2+")"}).attr("d","M0,"+M+"L"+M+","+ -M+" "+ -M+","+ -M+"Z").on("mouseover",function(){h.elementMouseover({value:m[0],label:"Previous",pos:[y(m[0]),p/2]})}).on("mouseout",function(){h.elementMouseout({value:m[0],label:"Previous"})}):C.selectAll("path.nv-markerTriangle").remove(),x.selectAll(".nv-range").on("mouseover",function(e,t){var n=t?t==1?"Mean":"Minimum":"Maximum";h.elementMouseover({value:e,label:n,pos:[y(e),p/2]})}).on("mouseout",function(e,t){var n=t?t==1?"Mean":"Minimum":"Maximum";h.elementMouseout({value:e,label:n})})}),p}var t={top:0,right:0,bottom:0,left:0},n="left",r=!1,i=function(e){return e.ranges},s=function(e){return e.markers},o=function(e){return e.measures},u=[0],a=380,f=30,l=null,c=e.utils.getColor(["#1f77b4"]),h=d3.dispatch("ele
mentMouseover","elementMouseout");return p.dispatch=h,p.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",p):n},p.ranges=function(e){return arguments.length?(i=e,p):i},p.markers=function(e){return arguments.length?(s=e,p):s},p.measures=function(e){return arguments.length?(o=e,p):o},p.forceX=function(e){return arguments.length?(u=e,p):u},p.width=function(e){return arguments.length?(a=e,p):a},p.height=function(e){return arguments.length?(f=e,p):f},p.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,p):t},p.tickFormat=function(e){return arguments.length?(l=e,p):l},p.color=function(t){return arguments.length?(c=e.utils.getColor(t),p):c},p},e.models.bulletChart=function(){function m(e){return e.each(function(n,h){var g=d3.select(this),y=(a||parseInt(g.style("width")
)||960)-i.left-i.right,b=f-i.top-i.bottom,w=this;m.update=function(){m(e)},m.container=this;if(!n||!s.call(this,n,h)){var E=g.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+y/2).attr("y",18+i.top+b/2).text(function(e){return e}),m}g.selectAll(".nv-noData").remove();var S=s.call(this,n,h).slice().sort(d3.descending),x=o.call(this,n,h).slice().sort(d3.descending),T=u.call(this,n,h).slice().sort(d3.descending),N=g.selectAll("g.nv-wrap.nv-bulletChart").data([n]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-bulletWrap"),k.append("g").attr("class","nv-titles"),N.attr("transform","translate("+i.left+","+i.top+")");var A=d3.scale.linear().domain([0,Math.max(S[0],x[0],T[0])]).range(r?[y,0]:[0,y]),O=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(A.range());this.__chart__=
A;var M=function(e){return Math.abs(O(e)-O(0))},_=function(e){return Math.abs(A(e)-A(0))},D=k.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(f-i.top-i.bottom)/2+")");D.append("text").attr("class","nv-title").text(function(e){return e.title}),D.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(e){return e.subtitle}),t.width(y).height(b);var P=L.select(".nv-bulletWrap");d3.transition(P).call(t);var H=l||A.tickFormat(y/100),B=L.selectAll("g.nv-tick").data(A.ticks(y/50),function(e){return this.textContent||H(e)}),j=B.enter().append("g").attr("class","nv-tick").attr("transform",function(e){return"translate("+O(e)+",0)"}).style("opacity",1e-6);j.append("line").attr("y1",b).attr("y2",b*7/6),j.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",b*7/6).text(H);var F=d3.transition(B).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1);F.select("line").attr("y1",b).attr("
y2",b*7/6),F.select("text").attr("y",b*7/6),d3.transition(B.exit()).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1e-6).remove(),d.on("tooltipShow",function(e){e.key=n.title,c&&v(e,w.parentNode)})}),d3.timer.flush(),m}var t=e.models.bullet(),n="left",r=!1,i={top:5,right:40,bottom:20,left:120},s=function(e){return e.ranges},o=function(e){return e.markers},u=function(e){return e.measures},a=null,f=55,l=null,c=!0,h=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide"),v=function(t,n){var r=t.pos[0]+(n.offsetLeft||0)+i.left,s=t.pos[1]+(n.offsetTop||0)+i.top,o=h(t.key,t.label,t.value,t,m);e.tooltip.show([r,s],o,t.value<0?"e":"w",null,n)};return t.dispatch.on("elementMouseover.tooltip",function(e){d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),m.dispatch=d,m.bullet=t,d3.rebind(m,t,"co
lor"),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(s=e,m):s},m.markers=function(e){return arguments.length?(o=e,m):o},m.measures=function(e){return arguments.length?(u=e,m):u},m.width=function(e){return arguments.length?(a=e,m):a},m.height=function(e){return arguments.length?(f=e,m):f},m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.tickFormat=function(e){return arguments.length?(l=e,m):l},m.tooltips=function(e){return arguments.length?(c=e,m):c},m.tooltipContent=function(e){return arguments.length?(h=e,m):h},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.cumulativeLineChart=function(){function C(e){return e.each(function(d){function P(e,t){d3.select(C.container).style("
cursor","ew-resize")}function H(e,t){T.x=d3.event.x,T.i=Math.round(x.invert(T.x)),K()}function B(e,t){d3.select(C.container).style("cursor","auto"),y.index=T.i,S.stateChange(y)}function K(){J.data([T]),C.update()}var L=d3.select(this).classed("nv-chart-"+g,!0),A=this,O=(a||parseInt(L.style("width"))||960)-o.left-o.right,M=(f||parseInt(L.style("height"))||400)-o.top-o.bottom;C.update=function(){C(e)},C.container=this,y.disabled=d.map(function(e){return!!e.disabled});if(!b){var _;b={};for(_ in y)y[_]instanceof Array?b[_]=y[_].slice(0):b[_]=y[_]}var D=d3.behavior.drag().on("dragstart",P).on("drag",H).on("dragend",B);if(!d||!d.length||!d.filter(function(e){return e.values.length}).length){var j=L.selectAll(".nv-noData").data([w]);return j.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),j.attr("x",o.left+O/2).attr("y",o.top+M/2).text(function(e){return e}),C}L.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();if(!p){
var F=d.filter(function(e){return!e.disabled}).map(function(e,n){var r=d3.extent(e.values,t.y());return r[0]<-0.95&&(r[0]=-0.95),[(r[0]-r[1])/(1+r[1]),(r[1]-r[0])/(1+r[0])]}),I=[d3.min(F,function(e){return e[0]}),d3.max(F,function(e){return e[1]})];t.yDomain(I)}else t.yDomain(null);x.domain([0,d[0].values.length-1]).range([0,O]).clamp(!0);var d=k(T.i,d),q=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([d]),R=q.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),U=q.select("g");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-background"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-avgLinesWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),l&&(i.width(O),U.select(".nv-legendWrap").datum(d).call(i),o.top!=i.height()&&(o.top=i.height(),M=(f||parseInt(L.style("height"))||400)-o.top-o.bottom),U.select(".nv-lege
ndWrap").attr("transform","translate(0,"+ -o.top+")"));if(h){var z=[{key:"Re-scale y-axis",disabled:!p}];s.width(140).color(["#444","#444","#444"]),U.select(".nv-controlsWrap").datum(z).attr("transform","translate(0,"+ -o.top+")").call(s)}q.attr("transform","translate("+o.left+","+o.top+")");var W=d.filter(function(e){return e.tempDisabled});q.select(".tempDisabled").remove(),W.length&&q.append("text").attr("class","tempDisabled").attr("x",O/2).attr("y","-.71em").style("text-anchor","end").text(W.map(function(e){return e.key}).join(", ")+" values cannot be calculated for this time period."),R.select(".nv-background").append("rect"),U.select(".nv-background rect").attr("width",O).attr("height",M),t.y(function(e){return e.display.y}).width(O).height(M).color(d.map(function(e,t){return e.color||u(e,t)}).filter(function(e,t){return!d[t].disabled&&!d[t].tempDisabled}));var X=U.select(".nv-linesWrap").datum(d.filter(function(e){return!e.disabled&&!e.tempDisabled}));X.call(t),d.for
Each(function(e,t){e.seriesIndex=t});var V=d.filter(function(e){return!e.disabled&&!!E(e)}),$=U.select(".nv-avgLinesWrap").selectAll("line").data(V,function(e){return e.key});$.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(e,n){return t.color()(e,e.seriesIndex)}).attr("x1",0).attr("x2",O).attr("y1",function(e){return m(E(e))}).attr("y2",function(e){return m(E(e))}),$.attr("x1",0).attr("x2",O).attr("y1",function(e){return m(E(e))}).attr("y2",function(e){return m(E(e))}),$.exit().remove();var J=X.selectAll(".nv-indexLine").data([T]);J.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).call(D),J.attr("transform",function(e){return"translate("+x(e.i)+",0)"}).attr("height",M),n.scale(v).ticks(Math.min(d[0].values.length,O/70)).tickSize(-M,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+m.range()[0]+")"),d3.transition(U.select(".nv-x.nv-a
xis")).call(n),r.scale(m).ticks(M/36).tickSize(-O,0),d3.transition(U.select(".nv-y.nv-axis")).call(r),U.select(".nv-background rect").on("click",function(){T.x=d3.mouse(this)[0],T.i=Math.round(x.invert(T.x)),y.index=T.i,S.stateChange(y),K()}),t.dispatch.on("elementClick",function(e){T.i=e.pointIndex,T.x=x(T.i),y.index=T.i,S.stateChange(y),K()}),s.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,p=!t.disabled,y.rescaleY=p,S.stateChange(y),e.call(C)}),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,d.filter(function(e){return!e.disabled}).length||d.map(function(e){return e.disabled=!1,q.selectAll(".nv-series").classed("disabled",!1),e}),y.disabled=d.map(function(e){return!!e.disabled}),S.stateChange(y),e.call(C)}),S.on("tooltipShow",function(e){c&&N(e,A.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(d.forEach(function(e,n){e.disabled=t.disabled[n]}),y.disabled=t.disabled),typeof t.index!="undefined"&&(T.i=t.index,T.
x=x(T.i),y.index=t.index,J.data([T])),typeof t.rescaleY!="undefined"&&(p=t.rescaleY),e.call(C)})}),C}function k(e,n){return n.map(function(n,r){if(!n.values)return n;var i=t.y()(n.values[e],e);return i<-0.95?(n.tempDisabled=!0,n):(n.tempDisabled=!1,n.values=n.values.map(function(e,n){return e.display={y:(t.y()(e,n)-i)/(1+i)},e}),n)})}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:30,bottom:50,left:60},u=e.utils.defaultColor(),a=null,f=null,l=!0,c=!0,h=!0,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},v,m,g=t.id(),y={index:0,rescaleY:p},b=null,w="No Data Available.",E=function(e){return e.average},S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.orient("bottom").tickPadding(7),r.orient("left");var x=d3.scale.linear(),T={i:0,x:0},N=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickF
ormat()(t.y()(i.point,i.pointIndex)),l=d(i.series.key,a,f,i,C);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),C.dispatch=S,C.lines=t,C.legend=i,C.xAxis=n,C.yAxis=r,d3.rebind(C,t,"defined","isArea","x","y","size","xDomain","yDomain","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),C.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,C):o},C.width=function(e){return arguments.length?(a=e,C):a},C.height=function(e){return arguments.length?(f=e,C):f},C.color=function(t){return arguments.length?(u=e.utils.getColor(t),i.color(u),C):u},C.rescaleY=fu
nction(e){return arguments.length?(p=e,p):p},C.showControls=function(e){return arguments.length?(h=e,C):h},C.showLegend=function(e){return arguments.length?(l=e,C):l},C.tooltips=function(e){return arguments.length?(c=e,C):c},C.tooltipContent=function(e){return arguments.length?(d=e,C):d},C.state=function(e){return arguments.length?(y=e,C):y},C.defaultState=function(e){return arguments.length?(b=e,C):b},C.noData=function(e){return arguments.length?(w=e,C):w},C.average=function(e){return arguments.length?(E=e,C):E},C},e.models.discreteBar=function(){function b(e){return e.each(function(e){var i=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e});var E=p&&d?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0}})});s.domain(p||d3.merge(E).map(function(e){return e.x})).rangeBands([0,i],.1),o.domain(d||d3.extent(d3.merge(E).map(function(e){return e.y}).conc
at(f))),c?o.range([b-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range([b,0]),g=g||s,y=y||o.copy().range([o(0),o(0)]);var S=w.selectAll("g.nv-wrap.nv-discretebar").data([e]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-groups"),S.attr("transform","translate("+t.left+","+t.top+")");var k=S.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});k.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(k.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),k.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),d3.transition(k).style("stroke-opacity",1).style("fill-opacity",.75);var L=k.selectAll("g.nv-bar").data(function(e){return e.values});L.exit().remove();var A=L.enter().append("g").attr("transform",function(e,t,n){return"translate("+(s(u(e
,t))+s.rangeBand()*.05)+", "+o(0)+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),v.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),v.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){v.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){v.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()});A.append("rect").attr("height",0).attr("width",s.rangeBand()*.9/e.length),c?(A.append("text").
attr("text-anchor","middle"),L.select("text").attr("x",s.rangeBand()*.9/2).attr("y",function(e,t){return a(e,t)<0?o(a(e,t))-o(0)+12:-4
+}).text(function(e,t){return h(a(e,t))})):L.selectAll("text").remove(),L.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(e,t){return e.color||l(e,t)}).style("stroke",function(e,t){return e.color||l(e,t)}).select("rect").attr("class",m).attr("width",s.rangeBand()*.9/e.length),d3.transition(L).attr("transform",function(e,t){var n=s(u(e,t))+s.rangeBand()*.05,r=a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t));return"translate("+n+", "+r+")"}).select("rect").attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0))||1)}),g=s.copy(),y=o.copy()}),b}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=!1,h=d3.format(",.2f"),p,d,v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),m="discreteBar",g,y;return b.dispatch=v,b.x
=function(e){return arguments.length?(u=e,b):u},b.y=function(e){return arguments.length?(a=e,b):a},b.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,b):t},b.width=function(e){return arguments.length?(n=e,b):n},b.height=function(e){return arguments.length?(r=e,b):r},b.xScale=function(e){return arguments.length?(s=e,b):s},b.yScale=function(e){return arguments.length?(o=e,b):o},b.xDomain=function(e){return arguments.length?(p=e,b):p},b.yDomain=function(e){return arguments.length?(d=e,b):d},b.forceY=function(e){return arguments.length?(f=e,b):f},b.color=function(t){return arguments.length?(l=e.utils.getColor(t),b):l},b.id=function(e){return arguments.length?(i=e,b):i},b.showValues=function(e){return arguments.length?(c=e,b):c},b.valueFormat=function(e){return arguments.length?(h=e,b):h}
,b.rectClass=function(e){return arguments.length?(m=e,b):m},b},e.models.discreteBarChart=function(){function m(e){return e.each(function(u){var l=d3.select(this),g=this,b=(s||parseInt(l.style("width"))||960)-i.left-i.right,w=(o||parseInt(l.style("height"))||400)-i.top-i.bottom;m.update=function(){d.beforeUpdate(),e.transition().call(m)},m.container=this;if(!u||!u.length||!u.filter(function(e){return e.values.length}).length){var E=l.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+b/2).attr("y",i.top+w/2).text(function(e){return e}),m}l.selectAll(".nv-noData").remove(),c=t.xScale(),h=t.yScale();var S=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([u]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),N=T.append("defs"),C=S.select("g");T.append("g").attr("class","nv-x nv-axis"),T.append("g").attr("class","nv-y nv-axis")
,T.append("g").attr("class","nv-barsWrap"),C.attr("transform","translate("+i.left+","+i.top+")"),t.width(b).height(w);var k=C.select(".nv-barsWrap").datum(u.filter(function(e){return!e.disabled}));d3.transition(k).call(t),N.append("clipPath").attr("id","nv-x-label-clip-"+t.id()).append("rect"),C.select("#nv-x-label-clip-"+t.id()+" rect").attr("width",c.rangeBand()*(a?2:1)).attr("height",16).attr("x",-c.rangeBand()/(a?1:2)),n.scale(c).ticks(b/100).tickSize(-w,0),C.select(".nv-x.nv-axis").attr("transform","translate(0,"+(h.range()[0]+(t.showValues()&&h.domain()[0]<0?16:0))+")"),C.select(".nv-x.nv-axis").transition().duration(0).call(n);var L=C.select(".nv-x.nv-axis").selectAll("g");a&&L.selectAll("text").attr("transform",function(e,t,n){return"translate(0,"+(n%2==0?"5":"17")+")"}),r.scale(h).ticks(w/36).tickSize(-b,0),d3.transition(C.select(".nv-y.nv-axis")).call(r),d.on("tooltipShow",function(e){f&&v(e,g.parentNode)})}),m}var t=e.models.discreteBar(),n=e.models.axis(),r=e.mod
els.axis(),i={top:15,right:10,bottom:50,left:60},s=null,o=null,u=e.utils.getColor(),a=!1,f=!0,l=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},c,h,p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate");n.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("left").tickFormat(d3.format(",.1f"));var v=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),c=l(i.series.key,a,f,i,m);e.tooltip.show([o,u],c,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+i.left,e.pos[1]+i.top],d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){f&&e.tooltip.cleanup()}),m.dispatch=d,m.discretebar=t,m.xAxis=n,m.yAxis=r,d3.rebind(m,t,"x","y","xDomain","yDomain","forceX","forceY","id","showValu
es","valueFormat"),m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.width=function(e){return arguments.length?(s=e,m):s},m.height=function(e){return arguments.length?(o=e,m):o},m.color=function(n){return arguments.length?(u=e.utils.getColor(n),t.color(u),m):u},m.staggerLabels=function(e){return arguments.length?(a=e,m):a},m.tooltips=function(e){return arguments.length?(f=e,m):f},m.tooltipContent=function(e){return arguments.length?(l=e,m):l},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.distribution=function(){function l(e){return e.each(function(e){var a=n-(i==="x"?t.left+t.right:t.top+t.bottom),l=i=="x"?"y":"x",c=d3.select(this);f=f||u;var h=c.selectAll("g.nv-distribution").data([e]),p=h.enter().append("g").attr("class","nvd3 nv-distribution"),d=p.ap
pend("g"),v=h.select("g");h.attr("transform","translate("+t.left+","+t.top+")");var m=v.selectAll("g.nv-dist").data(function(e){return e},function(e){return e.key});m.enter().append("g"),m.attr("class",function(e,t){return"nv-dist nv-series-"+t}).style("stroke",function(e,t){return o(e,t)});var g=m.selectAll("line.nv-dist"+i).data(function(e){return e.values});g.enter().append("line").attr(i+"1",function(e,t){return f(s(e,t))}).attr(i+"2",function(e,t){return f(s(e,t))}),d3.transition(m.exit().selectAll("line.nv-dist"+i)).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}).style("stroke-opacity",0).remove(),g.attr("class",function(e,t){return"nv-dist"+i+" nv-dist"+i+"-"+t}).attr(l+"1",0).attr(l+"2",r),d3.transition(g).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}),f=u.copy()}),l}var t={top:0,right:0,bottom:0,left:0},n=400,r=8,i="x",s=function(e){return e[i]},o=e.utils.defaultColor(),u=d3.scale.linea
r(),a,f;return l.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,l):t},l.width=function(e){return arguments.length?(n=e,l):n},l.axis=function(e){return arguments.length?(i=e,l):i},l.size=function(e){return arguments.length?(r=e,l):r},l.getData=function(e){return arguments.length?(s=d3.functor(e),l):s},l.scale=function(e){return arguments.length?(u=e,l):u},l.color=function(t){return arguments.length?(o=e.utils.getColor(t),l):o},l},e.models.indentedTree=function(){function m(e){return e.each(function(e){function C(e,t,n){d3.event.stopPropagation();if(d3.event.shiftKey&&!n)return d3.event.shiftKey=!1,e.values&&e.values.forEach(function(e){(e.values||e._values)&&C(e,0,!0)}),!0;if(!A(e))return!0;e.values?(e._values=e.values,e.values=null):(e.values=e._values,e._values=null),m.update()}fu
nction k(e){return e._values&&e._values.length?h:e.values&&e.values.length?p:""}function L(e){return e._values&&e._values.length}function A(e){var t=e.values||e._values;return t&&t.length}var t=1,n=d3.select(this),i=d3.layout.tree().children(function(e){return e.values}).size([r,f]);m.update=function(){n.transition().duration(600).call(m)},e[0]||(e[0]={key:a});var s=i.nodes(e[0]),g=d3.select(this).selectAll("div").data([[s]]),y=g.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),b=y.append("table"),w=g.select("table").attr("width","100%").attr("class",c);if(o){var E=b.append("thead"),S=E.append("tr");l.forEach(function(e){S.append("th").attr("width",e.width?e.width:"10%").style("text-align",e.type=="numeric"?"right":"left").append("span").text(e.label)})}var x=w.selectAll("tbody").data(function(e){return e});x.enter().append("tbody"),t=d3.max(s,function(e){return e.depth}),i.size([r,t*f]);var T=x.selectAll("tr").data(function(e){return e.filter(function(e){r
eturn u&&!e.children?u(e):!0})},function(e,t){return e.id||e.id||++v});T.exit().remove(),T.select("img.nv-treeicon").attr("src",k).classed("folded",L);var N=T.enter().append("tr");l.forEach(function(e,t){var n=N.append("td").style("padding-left",function(e){return(t?0:e.depth*f+12+(k(e)?0:16))+"px"},"important").style("text-align",e.type=="numeric"?"right":"left");t==0&&n.append("img").classed("nv-treeicon",!0).classed("nv-folded",L).attr("src",k).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(e){return k(e)?"inline-block":"none"}).on("click",C),n.append("span").attr("class",d3.functor(e.classes)).text(function(t){return e.format?e.format(t):t[e.key]||"-"}),e.showCount&&(n.append("span").attr("class","nv-childrenCount"),T.selectAll("span.nv-childrenCount").text(function(e){return e.values&&e.values.length||e._values&&e._values.length?"("+(e.values&&e.values.filter(function(e){return u?u(e):!0}).length||e._values&&e._values.filt
er(function(e){return u?u(e):!0}).length||0)+")":""})),e.click&&n.select("span").on("click",e.click)}),T.order().on("click",function(e){d.elementClick({row:this,data:e,pos:[e.x,e.y]})}).on("dblclick",function(e){d.elementDblclick({row:this,data:e,pos:[e.x,e.y]})}).on("mouseover",function(e){d.elementMouseover({row:this,data:e,pos:[e.x,e.y]})}).on("mouseout",function(e){d.elementMouseout({row:this,data:e,pos:[e.x,e.y]})})}),m}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e4),o=!0,u=!1,a="No Data Available.",f=20,l=[{key:"key",label:"Name",type:"text"}],c=null,h="images/grey-plus.png",p="images/grey-minus.png",d=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),v=0;return m.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!=
"undefined"?e.left:t.left,m):t},m.width=function(e){return arguments.length?(n=e,m):n},m.height=function(e){return arguments.length?(r=e,m):r},m.color=function(t){return arguments.length?(i=e.utils.getColor(t),scatter.color(i),m):i},m.id=function(e){return arguments.length?(s=e,m):s},m.header=function(e){return arguments.length?(o=e,m):o},m.noData=function(e){return arguments.length?(a=e,m):a},m.filterZero=function(e){return arguments.length?(u=e,m):u},m.columns=function(e){return arguments.length?(l=e,m):l},m.tableClass=function(e){return arguments.length?(c=e,m):c},m.iconOpen=function(e){return arguments.length?(h=e,m):h},m.iconClose=function(e){return arguments.length?(p=e,m):p},m},e.models.legend=function(){function a(f){return f.each(function(a){var f=n-t.left-t.right,l=d3.select(this),c=l.selectAll("g.nv-legend").data([a]),h=c.enter().append("g").attr("class","nvd3 nv-legend").append("g"),p=c.select("g");c.attr("transform","translate("+t.left+","+t.top+")");var d=p.sel
ectAll(".nv-series").data(function(e){return e}),v=d.enter().append("g").attr("class","nv-series").on("mouseover",function(e,t){u.legendMouseover(e,t)}).on("mouseout",function(e,t){u.legendMouseout(e,t)}).on("click",function(e,t){u.legendClick(e,t)}).on("dblclick",function(e,t){u.legendDblclick(e,t)});v.append("circle").style("stroke-width",2).attr("r",5),v.append("text").attr("text-anchor","start").attr("dy",".32em").attr("dx","8"),d.classed("disabled",function(e){return e.disabled}),d.exit().remove(),d.select("circle").style("fill",function(e,t){return e.color||s(e,t)}).style("stroke",function(e,t){return e.color||s(e,t)}),d.select("text").text(i);if(o){var m=[];d.each(function(t,n){var r=d3.select(this).select("text"),i=r.node().getComputedTextLength()||e.utils.calcApproxTextWidth(r);m.push(i+28)});var g=0,y=0,b=[];while(y<f&&g<m.length)b[g]=m[g],y+=m[g++];while(y>f&&g>1){b=[],g--;for(k=0;k<m.length;k++)m[k]>(b[k%g]||0)&&(b[k%g]=m[k]);y=b.reduce(function(e,t,n,r){return e
+t})}var w=[];for(var E=0,S=0;E<g;E++)w[E]=S,S+=b[E];d.attr("transform",function(e,t){return"translate("+w[t%g]+","+(5+Math.floor(t/g)*20)+")"}),p.attr("transform","translate("+(n-t.right-y)+","+t.top+")"),r=t.top+t.bottom+Math.ceil(m.length/g)*20}else{var x=5,T=5,N=0,C;d.attr("transform",function(e,r){var i=d3.select(this).select("text").node().getComputedTextLength()+28;return C=T,n<t.left+t.right+C+i&&(T=C=5,x+=20),T+=i,T>N&&(N=T),"translate("+C+","+x+")"}),p.attr("transform","translate("+(n-t.right-N)+","+t.top+")"),r=t.top+t.bottom+x+15}}),a}var t={top:5,right:0,bottom:5,left:0},n=400,r=20,i=function(e){return e.key},s=e.utils.defaultColor(),o=!0,u=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout");return a.dispatch=u,a.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefin
ed"?e.left:t.left,a):t},a.width=function(e){return arguments.length?(n=e,a):n},a.height=function(e){return arguments.length?(r=e,a):r},a.key=function(e){return arguments.length?(i=e,a):i},a.color=function(t){return arguments.length?(s=e.utils.getColor(t),a):s},a.align=function(e){return arguments.length?(o=e,a):o},a},e.models.line=function(){function m(e){return e.each(function(e){var m=r-n.left-n.right,g=i-n.top-n.bottom,b=d3.select(this);c=t.xScale(),h=t.yScale(),d=d||c,v=v||h;var w=b.selectAll("g.nv-wrap.nv-line").data([e]),E=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),S=E.append("defs"),T=E.append("g"),N=w.select("g");T.append("g").attr("class","nv-groups"),T.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+n.left+","+n.top+")"),t.width(m).height(g);var C=w.select(".nv-scatterWrap");d3.transition(C).call(t),S.append("clipPath").attr("id","nv-edge-clip-"+t.id()).append("rect"),w.select("#nv-edge-clip-"+t.id()+" rect").attr("width",
m).attr("height",g),N.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":""),C.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":"");var k=w.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});k.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(k.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),k.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return s(e,t)}).style("stroke",function(e,t){return s(e,t)}),d3.transition(k).style("stroke-opacity",1).style("fill-opacity",.5);var L=k.selectAll("path.nv-area").data(function(e){return f(e)?[e]:[]});L.enter().append("path").attr("class","nv-area").attr("d",function(e){return d3.svg.area().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y0(function(e,t){return v(u(e,t))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?
0:h.domain()[1]:h.domain()[0])}).apply(this,[e.values])}),d3.transition(k.exit().selectAll("path.nv-area")).attr("d",function(e){return d3.svg.area().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y0(function(e,t){return v(u(e,t))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[e.values])}),d3.transition(L).attr("d",function(e){return d3.svg.area().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y0(function(e,t){return v(u(e,t))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[e.values])});var A=k.selectAll("path.nv-line").data(function(e){return[e.values]});A.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y(function(e,t){return v(u(e,t))})),d3.transition(k.exit().selectAll("path.nv-line")).attr("d",d3.svg.line().interpolate(p).defined(a).x(function(e
,t){return c(o(e,t))}).y(function(e,t){return h(u(e,t))})),d3.transition(A).attr("d",d3.svg.line().interpolate(p).defined(a).x(function(e,t){return c(o(e,t))}).y(function(e,t){return h(u(e,t))})),d=c.copy(),v=h.copy()}),m}var t=e.models.scatter(),n={top:0,right:0,bottom:0,left:0},r=960,i=500,s=e.utils.defaultColor(),o=function(e){return e.x},u=function(e){return e.y},a=function(e,t){return!isNaN(u(e,t))&&u(e,t)!==null},f=function(e){return e.area},l=!1,c,h,p="linear";t.size(16).sizeDomain([16,256]);var d,v;return m.dispatch=t.dispatch,m.scatter=t,d3.rebind(m,t,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","forceX","forceY","forceSize","clipVoronoi","clipRadius","padData"),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function
(e){return arguments.length?(r=e,m):r},m.height=function(e){return arguments.length?(i=e,m):i},m.x=function(e){return arguments.length?(o=e,t.x(e),m):o},m.y=function(e){return arguments.length?(u=e,t.y(e),m):u},m.clipEdge=function(e){return arguments.length?(l=e,m):l},m.color=function(n){return arguments.length?(s=e.utils.getColor(n),t.color(s),m):s},m.interpolate=function(e){return arguments.length?(p=e,m):p},m.defined=function(e){return arguments.length?(a=e,m):a},m.isArea=function(e){return arguments.length?(f=d3.functor(e),m):f},m},e.models.lineChart=function(){function b(e){return e.each(function(c){var w=d3.select(this),E=this,S=(u||parseInt(w.style("width"))||960)-s.left-s.right,T=(a||parseInt(w.style("height"))||400)-s.top-s.bottom;b.update=function(){b(e)},b.container=this,d.disabled=c.map(function(e){return!!e.disabled});if(!v){var N;v={};for(N in d)d[N]instanceof Array?v[N]=d[N].slice(0):v[N]=d[N]}if(!c||!c.length||!c.filter(function(e){return e.values.length}).le
ngth){var C=w.selectAll(".nv-noData").data([m]);return C.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),C.attr("x",s.left+S/2).attr("y",s.top+T/2).text(function(e){return e}),b}w.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale();var k=w.selectAll("g.nv-wrap.nv-lineChart").data([c]),L=k.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),A=k.select("g");L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-linesWrap"),L.append("g").attr("class","nv-legendWrap"),f&&(i.width(S),A.select(".nv-legendWrap").datum(c).call(i),s.top!=i.height()&&(s.top=i.height(),T=(a||parseInt(w.style("height"))||400)-s.top-s.bottom),k.select(".nv-legendWrap").attr("transform","translate(0,"+ -s.top+")")),k.attr("transform","translate("+s.left+","+s.top+")"),t.width(S).height(T).color(c.map(function(e,t){return e.color||o(e,t)}).filter(function(e,t){re
turn!c[t].disabled}));var O=A.select(".nv-linesWrap").datum(c.filter(function(e){return!e.disabled}));d3.transition(O).call(t),n.scale(h).ticks(S/100).tickSize(-T,0),A.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")"),d3.transition(A.select(".nv-x.nv-axis")).call(n),r.scale(p).ticks(T/36).tickSize(-S,0),d3.transition(A.select(".nv-y.nv-axis")).call(r),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,c.filter(function(e){return!e.disabled}).length||c.map(function(e){return e.disabled=!1,k.selectAll(".nv-series").classed("disabled",!1),e}),d.disabled=c.map(function(e){return!!e.disabled}),g.stateChange(d),e.transition().call(b)}),g.on("tooltipShow",function(e){l&&y(e,E.parentNode)}),g.on("changeState",function(t){typeof t.disabled!="undefined"&&(c.forEach(function(e,n){e.disabled=t.disabled[n]}),d.disabled=t.disabled),e.call(b)})}),b}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s={top:30,right:20,bottom:5
0,left:60},o=e.utils.defaultColor(),u=null,a=null,f=!0,l=!0,c=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},h,p,d={},v=null,m="No Data Available.",g=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.orient("bottom").tickPadding(7),r.orient("left");var y=function(i,s){if(s){var o=d3.select(s).select("svg"),u=o.node()?o.attr("viewBox"):null;if(u){u=u.split(" ");var a=parseInt(o.style("width"))/u[2];i.pos[0]=i.pos[0]*a,i.pos[1]=i.pos[1]*a}}var f=i.pos[0]+(s.offsetLeft||0),l=i.pos[1]+(s.offsetTop||0),h=n.tickFormat()(t.x()(i.point,i.pointIndex)),p=r.tickFormat()(t.y()(i.point,i.pointIndex)),d=c(i.series.key,h,p,i,b);e.tooltip.show([f,l],d,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+s.left,e.pos[1]+s.top],g.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){g.tooltipHide(e)}),g.on("tooltipHide",function(){l&&e.tooltip.cleanup()}),b.dispatch=g,b.lines=t,b.legend=i,b.xAxis=n,b
.yAxis=r,d3.rebind(b,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate"),b.margin=function(e){return arguments.length?(s.top=typeof e.top!="undefined"?e.top:s.top,s.right=typeof e.right!="undefined"?e.right:s.right,s.bottom=typeof e.bottom!="undefined"?e.bottom:s.bottom,s.left=typeof e.left!="undefined"?e.left:s.left,b):s},b.width=function(e){return arguments.length?(u=e,b):u},b.height=function(e){return arguments.length?(a=e,b):a},b.color=function(t){return arguments.length?(o=e.utils.getColor(t),i.color(o),b):o},b.showLegend=function(e){return arguments.length?(f=e,b):f},b.tooltips=function(e){return arguments.length?(l=e,b):l},b.tooltipContent=function(e){return arguments.length?(c=e,b):c},b.state=function(e){return arguments.length?(d=e,b):d},b.defaultState=function(e){return arguments.length?(v=e,b):v},b.noData=function(e){return arguments.length?(m=e,b):m},b},e.models.lin
ePlusBarChart=function(){function T(e){return e.each(function(l){var c=d3.select(this),v=this,N=(a||parseInt(c.style("width"))||960)-u.left-u.right,C=(f||parseInt(c.style("height"))||400)-u.top-u.bottom;T.update=function(){T(e)},T.container=this,b.disabled=l.map(function(e){return!!e.disabled});if(!w){var k;w={};for(k in b)b[k]instanceof Array?w[k]=b[k].slice(0):w[k]=b[k]}if(!l||!l.length||!l.filter(function(e){return e.values.length}).length){var L=c.selectAll(".nv-noData").data([E]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",u.left+N/2).attr("y",u.top+C/2).text(function(e){return e}),T}c.selectAll(".nv-noData").remove();var A=l.filter(function(e){return!e.disabled&&e.bar}),O=l.filter(function(e){return!e.bar});m=O.filter(function(e){return!e.disabled}).length&&O.filter(function(e){return!e.disabled})[0].values.length?t.xScale():n.xScale(),g=n.yScale(),y=t.yScale();var M=d3.select(this).selectAl
l("g.nv-wrap.nv-linePlusBar").data([l]),_=M.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),D=M.select("g");_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y1 nv-axis"),_.append("g").attr("class","nv-y2 nv-axis"),_.append("g").attr("class","nv-barsWrap"),_.append("g").attr("class","nv-linesWrap"),_.append("g").attr("class","nv-legendWrap"),p&&(o.width(N/2),D.select(".nv-legendWrap").datum(l.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(o),u.top!=o.height()&&(u.top=o.height(),C=(f||parseInt(c.style("height"))||400)-u.top-u.bottom),D.select(".nv-legendWrap").attr("transform","translate("+N/2+","+ -u.top+")")),M.attr("transform","translate("+u.left+","+u.top+")"),t.width(N).height(C).color(l.map(function(e,t){return e.color||h(e,t)}).filter(function(e,t){return!l[t].disabled&&!l[t].bar})),n.width(N).height(C).color(l.map
(function(e,t){return e.color||h(e,t)}).filter(function(e,t){return!l[t].disabled&&l[t].bar}));var P=D.select(".nv-barsWrap").datum(A.length?A:[{values:[]}]),H=D.select(".nv-linesWrap").datum(O[0]&&!O[0].disabled?O:[{values:[]}]);d3.transition(P).call(n),d3.transition(H).call(t),r.scale(m).ticks(N/100).tickSize(-C,0),D.select(".nv-x.nv-axis").attr("transform","translate(0,"+g.range()[0]+")"),d3.transition(D.select(".nv-x.nv-axis")).call(r),i.scale(g).ticks(C/36).tickSize(-N,0),d3.transition(D.select(".nv-y1.nv-axis")).style("opacity",A.length?1:0).call(i),s.scale(y).ticks(C/36).tickSize(A.length?0:-N,0),D.select(".nv-y2.nv-axis").style("opacity",O.length?1:0).attr("transform","translate("+N+",0)"),d3.transition(D.select(".nv-y2.nv-axis")).call(s),o.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,l.filter(function(e){return!e.disabled}).length||l.map(function(e){return e.disabled=!1,M.selectAll(".nv-series").classed("disabled",!1),e}),b.disabled=l.map(function(
e){return!!e.disabled}),S.stateChange(b),e.transition().call(T)}),S.on("tooltipShow",function(e){d&&x(e,v.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(l.forEach(function(e,n){e.disabled=t.disabled[n]}),b.disabled=t.disabled),e.call(T)})}),T}var t=e.models.line(),n=e.models.historicalBar(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.legend(),u={top:30,right:60,bottom:50,left:60},a=null,f=null,l=function(e){return e.x},c=function(e){return e.y},h=e.utils.defaultColor(),p=!0,d=!0,v=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},m,g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.padData(!0),t.clipEdge(!1).padData(!0),r.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),s.orient("right");var x=function(n,o){var u=n.pos[0]+(o.offsetLeft||0),a=n.pos[1]+(o.offsetTop||0),f=r.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?
i:s).tickFormat()(t.y()(n.point,n.pointIndex)),c=v(n.series.key,f,l,n,T);e.tooltip.show([u,a],c,n.value<0?"n":"s",null,o)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),n.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),n.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){d&&e.tooltip.cleanup()}),T.dispatch=S,T.legend=o,T.lines=t,T.bars=n,T.xAxis=r,T.y1Axis=i,T.y2Axis=s,d3.rebind(T,t,"defined","size","clipVoronoi","interpolate"),T.x=function(e){return arguments.length?(l=e,t.x(e),n.x(e),T):l},T.y=function(e){return arguments.length?(c=e,t.y(e),n.y(e),T):c},T.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefi
ned"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,T):u},T.width=function(e){return arguments.length?(a=e,T):a},T.height=function(e){return arguments.length?(f=e,T):f},T.color=function(t){return arguments.length?(h=e.utils.getColor(t),o.color(h),T):h},T.showLegend=function(e){return arguments.length?(p=e,T):p},T.tooltips=function(e){return arguments.length?(d=e,T):d},T.tooltipContent=function(e){return arguments.length?(v=e,T):v},T.state=function(e){return arguments.length?(b=e,T):b},T.defaultState=function(e){return arguments.length?(w=e,T):w},T.noData=function(e){return arguments.length?(E=e,T):E},T},e.models.lineWithFocusChart=function(){function C(e){return e.each(function(S){function R(e){var t=+(e=="e"),n=t?1:-1,r=M/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function U(){a.empty()||a.extent(w),I.data([a.empty()?g.domain():w]).
each(function(e,t){var n=g(e[0])-v.range()[0],r=v.range()[1]-g(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",g(e[1])).attr("width",r<0?0:r)})}function z(){w=a.empty()?null:a.extent(),extent=a.empty()?g.domain():a.extent(),T.brush({extent:extent,brush:a}),U();var e=H.select(".nv-focus .nv-linesWrap").datum(S.filter(function(e){return!e.disabled}).map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=extent[0]&&t.x()(e,n)<=extent[1]})}}));d3.transition(e).call(t),d3.transition(H.select(".nv-focus .nv-x.nv-axis")).call(r),d3.transition(H.select(".nv-focus .nv-y.nv-axis")).call(i)}var k=d3.select(this),L=this,A=(h||parseInt(k.style("width"))||960)-f.left-f.right,O=(p||parseInt(k.style("height"))||400)-f.top-f.bottom-d,M=d-l.top-l.bottom;C.update=function(){C(e)},C.container=this;if(!S||!S.length||!S.filter(function(e){return e.values.length}).length){var _=k.selectAll(".nv-noData").data(
[x]);return _.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),_.attr("x",f.left+A/2).attr("y",f.top+O/2).text(function(e){return e}),C}k.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale(),g=n.xScale(),y=n.yScale();var D=k.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([S]),P=D.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),H=D.select("g");P.append("g").attr("class","nv-legendWrap");var B=P.append("g").attr("class","nv-focus");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-linesWrap");var j=P.append("g").attr("class","nv-context");j.append("g").attr("class","nv-x nv-axis"),j.append("g").attr("class","nv-y nv-axis"),j.append("g").attr("class","nv-linesWrap"),j.append("g").attr("class","nv-brushBackground"),j.append("g").attr("class","nv-x nv-brush"),b&&(u.width(A),H.select(".nv-legendWrap").datum(S).call(u),
f.top!=u.height()&&(f.top=u.height(),O=(p||parseInt(k.style("height"))||400)-f.top-f.bottom-d),H.select(".nv-legendWrap").attr("transform","translate(0,"+ -f.top+")")),D.attr("transform","translate("+f.left+","+f.top+")"),t.width(A).height(O).color(S.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!S[t].disabled})),n.defined(t.defined()).width(A).height(M).color(S.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!S[t].disabled})),H.select(".nv-context").attr("transform","translate(0,"+(O+f.bottom+l.top)+")");var F=H.select(".nv-context .nv-linesWrap").datum(S.filter(function(e){return!e.disabled}));d3.transition(F).call(n),r.scale(v).ticks(A/100).tickSize(-O,0),i.scale(m).ticks(O/36).tickSize(-A,0),H.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+O+")"),a.x(g).on("brush",z),w&&a.extent(w);var I=H.select(".nv-brushBackground").selectAll("g").data([w||a.extent()]),q=I.enter().append("g");q.append("rect").attr("class
","left").attr("x",0).attr("y",0).attr("height",M),q.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M),gBrush=H.select(".nv-x.nv-brush").call(a),gBrush.selectAll("rect").attr("height",M),gBrush.selectAll(".resize").append("path").attr("d",R),z(),s.scale(g).ticks(A/100).tickSize(-M,0),H.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.transition(H.select(".nv-context .nv-x.nv-axis")).call(s),o.scale(y).ticks(M/36).tickSize(-A,0),d3.transition(H.select(".nv-context .nv-y.nv-axis")).call(o),H.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),u.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,S.filter(function(e){return!e.disabled}).length||S.map(function(e){return e.disabled=!1,D.selectAll(".nv-series").classed("disabled",!1),e}),e.transition().call(C)}),T.on("tooltipShow",function(e){E&&N(e,L.parentNode)})}),C}var t=e.models.line(),n=e.models.line(),r=e.models.
axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.axis(),u=e.models.legend(),a=d3.svg.brush(),f={top:30,right:30,bottom:30,left:60
+},l={top:0,right:30,bottom:20,left:60},c=e.utils.defaultColor(),h=null,p=null,d=100,v,m,g,y,b=!0,w=null,E=!0,S=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},x="No Data Available.",T=d3.dispatch("tooltipShow","tooltipHide","brush");t.clipEdge(!0),n.interactive(!1),r.orient("bottom").tickPadding(5),i.orient("left"),s.orient("bottom").tickPadding(5),o.orient("left");var N=function(n,s){var o=n.pos[0]+(s.offsetLeft||0),u=n.pos[1]+(s.offsetTop||0),a=r.tickFormat()(t.x()(n.point,n.pointIndex)),f=i.tickFormat()(t.y()(n.point,n.pointIndex)),l=S(n.series.key,a,f,n,C);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+f.left,e.pos[1]+f.top],T.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){E&&e.tooltip.cleanup()}),C.dispatch=T,C.legend=u,C.lines=t,C.lines2=n,C.xAxis=r,C.yAxis=i,C.x2Axis=s,C.y2Axis=o,d3.rebind(C,t,"defined","isArea","
size","xDomain","yDomain","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),C.x=function(e){return arguments.length?(t.x(e),n.x(e),C):t.x},C.y=function(e){return arguments.length?(t.y(e),n.y(e),C):t.y},C.margin=function(e){return arguments.length?(f.top=typeof e.top!="undefined"?e.top:f.top,f.right=typeof e.right!="undefined"?e.right:f.right,f.bottom=typeof e.bottom!="undefined"?e.bottom:f.bottom,f.left=typeof e.left!="undefined"?e.left:f.left,C):f},C.margin2=function(e){return arguments.length?(l=e,C):l},C.width=function(e){return arguments.length?(h=e,C):h},C.height=function(e){return arguments.length?(p=e,C):p},C.height2=function(e){return arguments.length?(d=e,C):d},C.color=function(t){return arguments.length?(c=e.utils.getColor(t),u.color(c),C):c},C.showLegend=function(e){return arguments.length?(b=e,C):b},C.tooltips=function(e){return arguments.length?(E=e,C):E},C.tooltipContent=function(e){return arguments.length?(S=e,C):S},C.interpolate=function(e){retur
n arguments.length?(t.interpolate(e),n.interpolate(e),C):t.interpolate()},C.noData=function(e){return arguments.length?(x=e,C):x},C.xTickFormat=function(e){return arguments.length?(r.tickFormat(e),s.tickFormat(e),C):r.tickFormat()},C.yTickFormat=function(e){return arguments.length?(i.tickFormat(e),o.tickFormat(e),C):i.tickFormat()},C},e.models.linePlusBarWithFocusChart=function(){function H(e){return e.each(function(N){function nt(e){var t=+(e=="e"),n=t?1:-1,r=q/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function rt(){h.empty()||h.extent(x),Z.data([h.empty()?k.domain():x]).each(function(e,t){var n=k(e[0])-k.range()[0],r=k.range()[1]-k(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",k(e[1])).attr("width",r<0?0:r)})}function it(){x=h.empty()?null:h.extent(),S=h.empty()?k.domain():h.extent(),D.brush({e
xtent:S,brush:h}),rt(),r.width(F).height(I).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&N[t].bar})),t.width(F).height(I).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&!N[t].bar}));var e=J.select(".nv-focus .nv-barsWrap").datum(U.length?U.map(function(e,t){return{key:e.key,values:e.values.filter(function(e,t){return r.x()(e,t)>=S[0]&&r.x()(e,t)<=S[1]})}}):[{values:[]}]),n=J.select(".nv-focus .nv-linesWrap").datum(z[0].disabled?[{values:[]}]:z.map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=S[0]&&t.x()(e,n)<=S[1]})}}));U.length?C=r.xScale():C=t.xScale(),s.scale(C).ticks(F/100).tickSize(-I,0),s.domain([Math.ceil(S[0]),Math.floor(S[1])]),d3.transition(J.select(".nv-x.nv-axis")).call(s),d3.transition(e).call(r),d3.transition(n).call(t),J.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L.range()[0]+")"),u.scale(L).ticks(I/36
).tickSize(-F,0),J.select(".nv-focus .nv-y1.nv-axis").style("opacity",U.length?1:0),a.scale(A).ticks(I/36).tickSize(U.length?0:-F,0),J.select(".nv-focus .nv-y2.nv-axis").style("opacity",z.length?1:0).attr("transform","translate("+C.range()[1]+",0)"),d3.transition(J.select(".nv-focus .nv-y1.nv-axis")).call(u),d3.transition(J.select(".nv-focus .nv-y2.nv-axis")).call(a)}var B=d3.select(this),j=this,F=(v||parseInt(B.style("width"))||960)-p.left-p.right,I=(m||parseInt(B.style("height"))||400)-p.top-p.bottom-g,q=g-d.top-d.bottom;H.update=function(){H(e)},H.container=this;if(!N||!N.length||!N.filter(function(e){return e.values.length}).length){var R=B.selectAll(".nv-noData").data([_]);return R.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),R.attr("x",p.left+F/2).attr("y",p.top+I/2).text(function(e){return e}),H}B.selectAll(".nv-noData").remove();var U=N.filter(function(e){return!e.disabled&&e.bar}),z=N.filter(function(e){retur
n!e.bar});C=r.xScale(),k=o.scale(),L=r.yScale(),A=t.yScale(),O=i.yScale(),M=n.yScale();var W=N.filter(function(e){return!e.disabled&&e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})}),X=N.filter(function(e){return!e.disabled&&!e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})});C.range([0,F]),k.domain(d3.extent(d3.merge(W.concat(X)),function(e){return e.x})).range([0,F]);var V=B.selectAll("g.nv-wrap.nv-linePlusBar").data([N]),$=V.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),J=V.select("g");$.append("g").attr("class","nv-legendWrap");var K=$.append("g").attr("class","nv-focus");K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y1 nv-axis"),K.append("g").attr("class","nv-y2 nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-linesWrap");var Q=$.append("g").attr("class","nv-context");Q.append("g").attr("class","nv-x nv-ax
is"),Q.append("g").attr("class","nv-y1 nv-axis"),Q.append("g").attr("class","nv-y2 nv-axis"),Q.append("g").attr("class","nv-barsWrap"),Q.append("g").attr("class","nv-linesWrap"),Q.append("g").attr("class","nv-brushBackground"),Q.append("g").attr("class","nv-x nv-brush"),E&&(c.width(F/2),J.select(".nv-legendWrap").datum(N.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(c),p.top!=c.height()&&(p.top=c.height(),I=(m||parseInt(B.style("height"))||400)-p.top-p.bottom-g),J.select(".nv-legendWrap").attr("transform","translate("+F/2+","+ -p.top+")")),V.attr("transform","translate("+p.left+","+p.top+")"),i.width(F).height(q).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&N[t].bar})),n.width(F).height(q).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&!N[t].bar}));var G=J.select(".nv-context
.nv-barsWrap").datum(U.length?U:[{values:[]}]),Y=J.select(".nv-context .nv-linesWrap").datum(z[0].disabled?[{values:[]}]:z);J.select(".nv-context").attr("transform","translate(0,"+(I+p.bottom+d.top)+")"),d3.transition(G).call(i),d3.transition(Y).call(n),h.x(k).on("brush",it),x&&h.extent(x);var Z=J.select(".nv-brushBackground").selectAll("g").data([x||h.extent()]),et=Z.enter().append("g");et.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",q),et.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",q);var tt=J.select(".nv-x.nv-brush").call(h);tt.selectAll("rect").attr("height",q),tt.selectAll(".resize").append("path").attr("d",nt),o.ticks(F/100).tickSize(-q,0),J.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+O.range()[0]+")"),d3.transition(J.select(".nv-context .nv-x.nv-axis")).call(o),f.scale(O).ticks(q/36).tickSize(-F,0),J.select(".nv-context .nv-y1.nv-axis").style("opacity",U.length?1:0).attr("transform","t
ranslate(0,"+k.range()[0]+")"),d3.transition(J.select(".nv-context .nv-y1.nv-axis")).call(f),l.scale(M).ticks(q/36).tickSize(U.length?0:-F,0),J.select(".nv-context .nv-y2.nv-axis").style("opacity",z.length?1:0).attr("transform","translate("+k.range()[1]+",0)"),d3.transition(J.select(".nv-context .nv-y2.nv-axis")).call(l),c.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,N.filter(function(e){return!e.disabled}).length||N.map(function(e){return e.disabled=!1,V.selectAll(".nv-series").classed("disabled",!1),e}),e.call(H)}),D.on("tooltipShow",function(e){T&&P(e,j.parentNode)}),it()}),H}var t=e.models.line(),n=e.models.line(),r=e.models.historicalBar(),i=e.models.historicalBar(),s=e.models.axis(),o=e.models.axis(),u=e.models.axis(),a=e.models.axis(),f=e.models.axis(),l=e.models.axis(),c=e.models.legend(),h=d3.svg.brush(),p={top:30,right:30,bottom:30,left:60},d={top:0,right:30,bottom:20,left:60},v=null,m=null,g=100,y=function(e){return e.x},b=function(e){return e.y}
,w=e.utils.defaultColor(),E=!0,S,x=null,T=!0,N=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},C,k,L,A,O,M,_="No Data Available.",D=d3.dispatch("tooltipShow","tooltipHide","brush");t.clipEdge(!0),n.interactive(!1),s.orient("bottom").tickPadding(5),u.orient("left"),a.orient("right"),o.orient("bottom").tickPadding(5),f.orient("left"),l.orient("right");var P=function(n,r){S&&(n.pointIndex+=Math.ceil(S[0]));var i=n.pos[0]+(r.offsetLeft||0),o=n.pos[1]+(r.offsetTop||0),f=s.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?u:a).tickFormat()(t.y()(n.point,n.pointIndex)),c=N(n.series.key,f,l,n,H);e.tooltip.show([i,o],c,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),r.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),r.dispatch.on("e
lementMouseout.tooltip",function(e){D.tooltipHide(e)}),D.on("tooltipHide",function(){T&&e.tooltip.cleanup()}),H.dispatch=D,H.legend=c,H.lines=t,H.lines2=n,H.bars=r,H.bars2=i,H.xAxis=s,H.x2Axis=o,H.y1Axis=u,H.y2Axis=a,H.y3Axis=f,H.y4Axis=l,d3.rebind(H,t,"defined","size","clipVoronoi","interpolate"),H.x=function(e){return arguments.length?(y=e,t.x(e),r.x(e),H):y},H.y=function(e){return arguments.length?(b=e,t.y(e),r.y(e),H):b},H.margin=function(e){return arguments.length?(p.top=typeof e.top!="undefined"?e.top:p.top,p.right=typeof e.right!="undefined"?e.right:p.right,p.bottom=typeof e.bottom!="undefined"?e.bottom:p.bottom,p.left=typeof e.left!="undefined"?e.left:p.left,H):p},H.width=function(e){return arguments.length?(v=e,H):v},H.height=function(e){return arguments.length?(m=e,H):m},H.color=function(t){return arguments.length?(w=e.utils.getColor(t),c.color(w),H):w},H.showLegend=function(e){return arguments.length?(E=e,H):E},H.tooltips=function(e){return arguments.length?(T=e,H
):T},H.tooltipContent=function(e){return arguments.length?(N=e,H):N},H.noData=function(e){return arguments.length?(_=e,H):_},H.brushExtent=function(e){return arguments.length?(x=e,H):x},H},e.models.multiBar=function(){function S(e){return e.each(function(e){var S=n-t.left-t.right,T=r-t.top-t.bottom,N=d3.select(this);p&&e.length&&(p=[{values:e[0].values.map(function(e){return{x:e.x,y:0,series:e.series,size:.01}})}]),c&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(!e.length&&p?p:e)),e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e}),c&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i,i-=t.size):(t.y1=t.size+r,r+=t.size)})});var C=g&&y?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});i.domain(d3.merge(C).map(function(e){return e.x})).rangeBands([0,S],.1),s.domain(y||d3.extent(d3.merge(C).map(fu
nction(e){return c?e.y>0?e.y1:e.y1+e.y:e.y}).concat(f))).range([T,0]);if(i.domain()[0]===i.domain()[1]||s.domain()[0]===s.domain()[1])singlePoint=!0;i.domain()[0]===i.domain()[1]&&(i.domain()[0]?i.domain([i.domain()[0]-i.domain()[0]*.01,i.domain()[1]+i.domain()[1]*.01]):i.domain([-1,1])),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]+s.domain()[0]*.01,s.domain()[1]-s.domain()[1]*.01]):s.domain([-1,1])),w=w||i,E=E||s;var k=N.selectAll("g.nv-wrap.nv-multibar").data([e]),L=k.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),A=L.append("defs"),O=L.append("g"),M=k.select("g");O.append("g").attr("class","nv-groups"),k.attr("transform","translate("+t.left+","+t.top+")"),A.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),k.select("#nv-edge-clip-"+o+" rect").attr("width",S).attr("height",T),M.attr("clip-path",l?"url(#nv-edge-clip-"+o+")":"");var _=k.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){retur
n e.key});_.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),_.exit().selectAll("rect.nv-bar").transition().delay(function(t,n){return n*m/e[0].values.length}).attr("y",function(e){return c?E(e.y0):E(0)}).attr("height",0).remove(),_.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return h(e,t)}).style("stroke",function(e,t){return h(e,t)}),d3.transition(_).style("stroke-opacity",1).style("fill-opacity",.75);var D=_.selectAll("rect.nv-bar").data(function(t){return p&&!e.length?p.values:t.values});D.exit().remove();var P=D.enter().append("rect").attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(t,n,r){return c?0:r*i.rangeBand()/e.length}).attr("y",function(e){return E(c?e.y0:0)}).attr("height",0).attr("width",i.rangeBand()/(c?1:e.length));D.style("fill",function(e,t,n){return h(e,n,t)}).style("stroke",function(e,t,n){ret
urn h(e,n,t)}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),b.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),b.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){b.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){b.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),D.attr("class",function(e,t){return a(e,t)<0?"n
v-bar negative":"nv-bar positive"}).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"}),d&&(v||(v=e.map(function(){return!0})),D.style("fill",function(e,t,n){return d3.rgb(d(e,t)).darker(v.map(function(e,t){return t}).filter(function(e,t){return!v[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(d(e,t)).darker(v.map(function(e,t){return t}).filter(function(e,t){return!v[t]})[n]).toString()})),c?D.transition().delay(function(t,n){return n*m/e[0].values.length}).attr("y",function(e,t){return s(c?e.y1:0)}).attr("height",function(e,t){return Math.max(Math.abs(s(e.y+(c?e.y0:0))-s(c?e.y0:0)),1)}).each("end",function(){d3.transition(d3.select(this)).attr("x",function(t,n){return c?0:t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/(c?1:e.length))}):d3.transition(D).delay(function(t,n){return n*m/e[0].values.length}).attr("x",function(t,n){return t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/e.length).each("end",function()
{d3.transition(d3.select(this)).attr("y",function(e,t){return a(e,t)<0?s(0):s(0)-s(a(e,t))<1?s(0)-1:s(a(e,t))||0}).attr("height",function(e,t){return Math.max(Math.abs(s(a(e,t))-s(0)),1)||0})}),w=i.copy(),E=s.copy()}),S}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=d3.scale.ordinal(),s=d3.scale.linear(),o=Math.floor(Math.random()*1e4),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=!0,c=!1,h=e.utils.defaultColor(),p=!1,d=null,v,m=1200,g,y,b=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),w,E;return S.dispatch=b,S.x=function(e){return arguments.length?(u=e,S):u},S.y=function(e){return arguments.length?(a=e,S):a},S.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,S):t},S.width=function(e){return arguments.length?(n=e,S):
n},S.height=function(e){return arguments.length?(r=e,S):r},S.xScale=function(e){return arguments.length?(i=e,S):i},S.yScale=function(e){return arguments.length?(s=e,S):s},S.xDomain=function(e){return arguments.length?(g=e,S):g},S.yDomain=function(e){return arguments.length?(y=e,S):y},S.forceY=function(e){return arguments.length?(f=e,S):f},S.stacked=function(e){return arguments.length?(c=e,S):c},S.clipEdge=function(e){return arguments.length?(l=e,S):l},S.color=function(t){return arguments.length?(h=e.utils.getColor(t),S):h},S.barColor=function(t){return arguments.length?(d=e.utils.getColor(t),S):d},S.disabled=function(e){return arguments.length?(v=e,S):v},S.id=function(e){return arguments.length?(o=e,S):o},S.hideable=function(e){return arguments.length?(p=e,S):p},S.delay=function(e){return arguments.length?(m=e,S):m},S},e.models.multiBarChart=function(){function N(e){return e.each(function(m){var C=d3.select(this),k=this,L=(u||parseInt(C.style("width"))||960)-o.left-o.right,A
=(a||parseInt(C.style("height"))||400)-o.top-o.bottom;N.update=function(){e.transition().call(N)},N.container=this,b.disabled=m.map(function(e){return!!e.disabled});if(!w){var O;w={};for(O in b)b[O]instanceof Array?w[O]=b[O].slice(0):w[O]=b[O]}if(!m||!m.length||!m.filter(function(e){return e.values.length}).length){var M=C.selectAll(".nv-noData").data([E]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",o.left+L/2).attr("y",o.top+A/2).text(function(e){return e}),N}C.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var _=C.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([m]),D=_.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),P=_.select("g");D.append("g").attr("class","nv-x nv-axis"),D.append("g").attr("class","nv-y nv-axis"),D.append("g").attr("class","nv-barsWrap"),D.append("g").attr("class","nv-legendWrap"),D.append("g").attr("class","nv-controlsWrap"),
c&&(i.width(L-x()),t.barColor()&&m.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),P.select(".nv-legendWrap").datum(m).call(i),o.top!=i.height()&&(o.top=i.height(),A=(a||parseInt(C.style("height"))||400)-o.top-o.bottom),P.select(".nv-legendWrap").attr("transform","translate("+x()+","+ -o.top+")"));if(l){var H=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(x()).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(H).attr("transform","translate(0,"+ -o.top+")").call(s)}_.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(m.map(function(e){return e.disabled})).width(L).height(A).color(m.map(function(e,t){return e.color||f(e,t)}).filter(function(e,t){return!m[t].disabled}));var B=P.select(".nv-barsWrap").datum(m.filter(function(e){return!e.disabled}));d3.transition(B).call(t),n.scale(g).ticks(L/100).tickSize(-A,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.tr
ansition(P.select(".nv-x.nv-axis")).call(n);var j=P.select(".nv-x.nv-axis > g").selectAll("g");j.selectAll("line, text").style("opacity",1);if(p){var F=function(e,t){return"translate("+e+","+t+")"},I=5,q=17;j.selectAll("text").attr("transform",function(e,t,n){return F(0,n%2==0?I:q)});var R=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;P.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(e,t){return F(0,t===0||R%2!==0?q:I)})}h&&j.filter(function(e,t){return t%Math.ceil(m[0].values.length/(L/100))!==0}).selectAll("text, line").style("opacity",0),d&&j.selectAll("text").attr("transform","rotate("+d+" 0,0)").attr("text-anchor",d>0?"start":"end"),P.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1),r.scale(y).ticks(A/36).tickSize(-L,0),d3.transition(P.select(".nv-y.nv-axis")).call(r),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,m.filter(function(e){return!e.disabled}).length||m.map(function(e){return e
.disabled=!1,_.selectAll(".nv-series").classed("disabled",!1),e}),b.disabled=m.map(function(e){return!!e.disabled}),S.stateChange(b),e.transition().call(N)}),s.dispatch.on("legendClick",function(n,r){if(!n.disabled)return;H=H.map(function(e){return e.disabled=!0,e}),n.disabled=!1;switch(n.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}b.stacked=t.stacked(),S.stateChange(b),e.transition().call(N)}),S.on("tooltipShow",function(e){v&&T(e,k.parentNode)}),S.on("changeState",function(n){typeof n.disabled!="undefined"&&(m.forEach(function(e,t){e.disabled=n.disabled[t]}),b.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),b.stacked=n.stacked),e.call(N)})}),N}var t=e.models.multiBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!1,d=0,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},g,y,b={s
tacked:!1},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=function(){return l?180:0};t.stacked(!1),n.orient("bottom").tickPadding(7).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("left").tickFormat(d3.format(",.1f"));var T=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,N);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),N.dispatch=S,N.multibar=t,N.legend=i,N.xAxis=n,N.yAxis=r,d3.rebind(N,t,"x","y","xDomain","yDomain","forceX","forceY","clipEdge","id","stacked","delay","barColor"),N.margin=function(e){return ar
guments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,N):o},N.width=function(e){return arguments.length?(u=e,N):u},N.height=function(e){return arguments.length?(a=e,N):a},N.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),N):f},N.showControls=function(e){return arguments.length?(l=e,N):l},N.showLegend=function(e){return arguments.length?(c=e,N):c},N.reduceXTicks=function(e){return arguments.length?(h=e,N):h},N.rotateLabels=function(e){return arguments.length?(d=e,N):d},N.staggerLabels=function(e){return arguments.length?(p=e,N):p},N.tooltip=function(e){return arguments.length?(m=e,N):m},N.tooltips=function(e){return arguments.length?(v=e,N):v},N.tooltipContent=function(e){return arguments.length?(m=e,N):m},N.state=function(e){return arguments.length?(b=e,N):b},N.defaultState=function(e){re
turn arguments.length?(w=e,N):w},N.noData=function(e){return arguments.length?(E=e,N):E},N},e.models.multiBarHorizontal=function(){function x(e){return e.each(function(e){var i=n-t.left-t.right,g=r-t.top-t.bottom,x=d3.select(this);p&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(e)),e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e}),p&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i-t.size,i-=t.size):(t.y1=r,r+=t.size)})});var T=y&&b?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});s.domain(y||d3.merge(T).map(function(e){return e.x})).rangeBands([0,g],.1),o.domain(b||d3.extent(d3.merge(T).map(function(e){return p?e.y>0?e.y1+e.y:e.y1:e.y}).concat(f))),d&&!p?o.range([o.domain()[0]<0?v:0,i-(o.domain()[1]>0?v:0)]):o.range([0,i]),E=E||s,S=S||d3.scale.linear().domain(o.domain()).range([o(0),o(0)])
;var N=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-groups"),N.attr("transform","translate("+t.left+","+t.top+")");var O=N.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(O.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),O.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return l(e,t)}).style("stroke",function(e,t){return l(e,t)}),d3.transition(O).style("stroke-opacity",1).style("fill-opacity",.75);var M=O.selectAll("g.nv-bar").data(function(e){return e.values});M.exit().remove();var _=M.enter().append("g").attr("transform",function(t,n,r){return"tran
slate("+S(p?t.y0:0)+","+(p?0:r*s.rangeBand()/e.length+s(u(t,n)))+")"});_.append("rect").attr("width",0).attr("height",s.rangeBand()/(p?1:e.length)),M.on("mouseover",function(t,n){d3.select(this).classed("hover",!0),w.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[o(a(t,n)+(p?t.y0:0)),s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),w.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){w.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){w.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(
p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),_.append("text"),d&&!p?(M.select("text").attr("text-anchor",function(e,t){return a(e,t)<0?"end":"start"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return m(a(e,t))}),d3.transition(M).select("text").attr("x",function(e,t){return a(e,t)<0?-4:o(a(e,t))-o(0)+4})):M.selectAll("text").text(""),M.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}),c&&(h||(h=e.map(function(){return!0})),M.style("fill",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()})),p?d3.transition(M).attr("transform",function(e,t){return"translate("+o(e.y1)+","+s(u(e,t))+")"}).select("rect").attr("width",function(e,t){return Math.abs(o(a(e,t)+e.y0)
-o(e.y0))}).attr("height",s.rangeBand()):d3.transition(M).attr("transform",function(t,n){return"translate("+(a(t,n)<0?o(a(t,n)):o(0))+","+(t.series*s.rangeBand()/e.length+s(u(t,n)))+")"}).select("rect").attr("height",s.rangeBand()/e.length).attr("width",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)}),E=s.copy(),S=o.copy()}),x}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=null,h,p=!1,d=!1,v=60,m=d3.format(",.2f"),g=1200,y,b,w=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),E,S;return x.dispatch=w,x.x=function(e){return arguments.length?(u=e,x):u},x.y=function(e){return arguments.length?(a=e,x):a},x.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bott
om!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,x):t},x.width=function(e){return arguments.length?(n=e,x):n},x.height=function(e){return arguments.length?(r=e,x):r},x.xScale=function(e){return arguments.length?(s=e,x):s},x.yScale=function(e){return arguments.length?(o=e,x):o},x.xDomain=function(e){return arguments.length?(y=e,x):y},x.yDomain=function(e){return arguments.length?(b=e,x):b},x.forceY=function(e){return arguments.length?(f=e,x):f},x.stacked=function(e){return arguments.length?(p=e,x):p},x.color=function(t){return arguments.length?(l=e.utils.getColor(t),x):l},x.barColor=function(t){return arguments.length?(c=e.utils.getColor(t),x):c},x.disabled=function(e){return arguments.length?(h=e,x):h},x.id=function(e){return arguments.length?(i=e,x):i},x.delay=function(e){return arguments.length?(g=e,x):g},x.showValues=function(e){return arguments.length?(d=e,x):d},x.valueFormat=function(e){return arguments.length?(m=e,x):m},x.valuePadding=f
unction(e){return arguments.length?(v=e,x):v},x},e.models.multiBarHorizontalChart=function(){function x(e){return e.each(function(h){var d=d3.select(this),T=this,N=(u||parseInt(d.style("width"))||960)-o.left-o.right,C=(a||parseInt(d.style("height"))||400)-o.top-o.bottom;x.update=function(){e.transition().call(x)},x.container=this,g.disabled=h.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!h||!h.length||!h.filter(function(e){return e.values.length}).length){var L=d.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",o.left+N/2).attr("y",o.top+C/2).text(function(e){return e}),x}d.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();var A=d.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([h]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),M=A.sel
ect("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-barsWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),c&&(i.width(N-E()),t.barColor()&&h.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),M.select(".nv-legendWrap").datum(h).call(i),o.top!=i.height()&&(o.top=i.height(),C=(a||parseInt(d.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate("+E()+","+ -o.top+")"));if(l){var _=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(E()).color(["#444","#444","#444"]),M.select(".nv-controlsWrap").datum(_).attr("transform","translate(0,"+ -o.top+")").call(s)}A.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(h.map(function(e){return e.disabled})).width(N).height(C).color(h.map(function(e,t){return e.color||f(e,t)}).filter(function(e,t){return!h[t].disabled}
));var D=M.select(".nv-barsWrap").datum(h.filter(function(e){return!e.disabled}));d3.transition(D).call(t),n.scale(v).ticks(C/24).tickSize(-N,0),d3.transition(M.select(".nv-x.nv-axis")).call(n);var P=M.select(".nv-x.nv-axis").selectAll("g");P.selectAll("line, text").style("opacity",1),r.scale(m).ticks(N/100).tickSize(-C,0),M.select(".nv-y.nv-axis").attr("transform","translate(0,"+C+")"),d3.transition(M.select(".nv-y.nv-axis")).call(r),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,h.filter(function(e){return!e.disabled}).length||h.map(function(e){return e.disabled=!1,A.selectAll(".nv-series").classed("disabled",!1),e}),g.disabled=h.map(function(e){return!!e.disabled}),w.stateChange(g),e.transition().call(x)}),s.dispatch.on("legendClick",function(n,r){if(!n.disabled)return;_=_.map(function(e){return e.disabled=!0,e}),n.disabled=!1;switch(n.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}g.stacked=t.stacked(),w.stateChange(g),e.transition()
.call(x)}),w.on("tooltipShow",function(e){p&&S(e,T.parentNode)}),w.on("changeState",function(n){typeof n.disabled!="undefined"&&(h.forEach
+(function(e,t){e.disabled=n.disabled[t]}),g.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),g.stacked=n.stacked),e.call(x)})}),x}var t=e.models.multiBarHorizontal(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend().height(30),s=e.models.legend().height(30),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!1,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+" - "+t+"</h3>"+"<p>"+n+"</p>"},v,m,g={stacked:h},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=function(){return l?180:0};t.stacked(h),n.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("bottom").tickFormat(d3.format(",.1f"));var S=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=d(i.series.key,a,f,i,x);e.tooltip.show([o,u],l,i.v
alue<0?"e":"w",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],w.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){p&&e.tooltip.cleanup()}),x.dispatch=w,x.multibar=t,x.legend=i,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"x","y","xDomain","yDomain","forceX","forceY","clipEdge","id","delay","showValues","valueFormat","stacked","barColor"),x.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,x):o},x.width=function(e){return arguments.length?(u=e,x):u},x.height=function(e){return arguments.length?(a=e,x):a},x.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),x):f},x.showControls=function(e){return arguments.length?(l=e,x):l},x.showLegend=function(
e){return arguments.length?(c=e,x):c},x.tooltip=function(e){return arguments.length?(d=e,x):d},x.tooltips=function(e){return arguments.length?(p=e,x):p},x.tooltipContent=function(e){return arguments.length?(d=e,x):d},x.state=function(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments.length?(b=e,x):b},x},e.models.multiChart=function(){function T(e){return e.each(function(u){var f=d3.select(this),N=this,C=(r||parseInt(f.style("width"))||960)-t.left-t.right,k=(i||parseInt(f.style("height"))||400)-t.top-t.bottom,L=u.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==1}),A=u.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==2}),O=u.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==1}),M=u.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==2}),_=u.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==1}),D=u.filter(function(e){return!e.di
sabled&&e.type=="area"&&e.yAxis==2}),P=u.filter(function(e){return!e.disabled&&e.yAxis==1}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})}),H=u.filter(function(e){return!e.disabled&&e.yAxis==2}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})});a.domain(d3.extent(d3.merge(P.concat(H)),function(e){return e.x})).range([0,C]);var B=f.selectAll("g.wrap.multiChart").data([u]),j=B.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");j.append("g").attr("class","x axis"),j.append("g").attr("class","y1 axis"),j.append("g").attr("class","y2 axis"),j.append("g").attr("class","lines1Wrap"),j.append("g").attr("class","lines2Wrap"),j.append("g").attr("class","bars1Wrap"),j.append("g").attr("class","bars2Wrap"),j.append("g").attr("class","stack1Wrap"),j.append("g").attr("class","stack2Wrap"),j.append("g").attr("class","legendWrap");var F=B.select("g");s&&(E.width(C/2),F.select(".legendWrap").datum(u.map(function(e){return e.
originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.yAxis==1?"":" (right axis)"),e})).call(E),t.top!=E.height()&&(t.top=E.height(),k=(i||parseInt(f.style("height"))||400)-t.top-t.bottom),F.select(".legendWrap").attr("transform","translate("+C/2+","+ -t.top+")")),h.width(C).height(k).interpolate("monotone").color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==1&&u[t].type=="line"})),p.width(C).height(k).interpolate("monotone").color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==2&&u[t].type=="line"})),d.width(C).height(k).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==1&&u[t].type=="bar"})),v.width(C).height(k).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==2&&u[t].type=="bar"})),m.width(C).height(k
).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==1&&u[t].type=="area"})),g.width(C).height(k).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==2&&u[t].type=="area"})),F.attr("transform","translate("+t.left+","+t.top+")");var I=F.select(".lines1Wrap").datum(L),q=F.select(".bars1Wrap").datum(O),R=F.select(".stack1Wrap").datum(_),U=F.select(".lines2Wrap").datum(A),z=F.select(".bars2Wrap").datum(M),W=F.select(".stack2Wrap").datum(D),X=_.length?_.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[],V=D.length?D.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[];l.domain(d3.extent(d3.merge(P).concat(X),function(e){return e.y})).range([0,k]),c.domain(d3.extent(d3.merge(H).concat(V),functio
n(e){return e.y})).range([0,k]),h.yDomain(l.domain()),d.yDomain(l.domain()),m.yDomain(l.domain()),p.yDomain(c.domain()),v.yDomain(c.domain()),g.yDomain(c.domain()),_.length&&d3.transition(R).call(m),D.length&&d3.transition(W).call(g),O.length&&d3.transition(q).call(d),M.length&&d3.transition(z).call(v),L.length&&d3.transition(I).call(h),A.length&&d3.transition(U).call(p),y.ticks(C/100).tickSize(-k,0),F.select(".x.axis").attr("transform","translate(0,"+k+")"),d3.transition(F.select(".x.axis")).call(y),b.ticks(k/36).tickSize(-C,0),d3.transition(F.select(".y1.axis")).call(b),w.ticks(k/36).tickSize(-C,0),d3.transition(F.select(".y2.axis")).call(w),F.select(".y2.axis").style("opacity",H.length?1:0).attr("transform","translate("+a.range()[1]+",0)"),E.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,u.filter(function(e){return!e.disabled}).length||u.map(function(e){return e.disabled=!1,B.selectAll(".series").classed("disabled",!1),e}),e.transition().call(T)}),S.on("to
oltipShow",function(e){o&&x(e,N.parentNode)})}),T.update=function(){T(e)},T.container=this,T}var t={top:30,right:20,bottom:50,left:60},n=d3.scale.category20().range(),r=null,i=null,s=!0,o=!0,u=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},a,f,a=d3.scale.linear(),l=d3.scale.linear(),c=d3.scale.linear(),h=e.models.line().yScale(l),p=e.models.line().yScale(c),d=e.models.multiBar().stacked(!1).yScale(l),v=e.models.multiBar().stacked(!1).yScale(c),m=e.models.stackedArea().yScale(l),g=e.models.stackedArea().yScale(c),y=e.models.axis().scale(a).orient("bottom").tickPadding(5),b=e.models.axis().scale(l).orient("left"),w=e.models.axis().scale(c).orient("right"),E=e.models.legend().height(30),S=d3.dispatch("tooltipShow","tooltipHide"),x=function(t,n){var r=t.pos[0]+(n.offsetLeft||0),i=t.pos[1]+(n.offsetTop||0),s=y.tickFormat()(h.x()(t.point,t.pointIndex)),o=(t.series.yAxis==2?w:b).tickFormat()(h.y()(t.point,t.pointIndex)),a=u(t.series.key,s,o,t,T);e.tooltip.show(
[r,i],a,undefined,undefined,n.offsetParent)};return h.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),h.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),p.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),p.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),m.dispatch.on("tooltipShow",function(e){if(!Math.round(m.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipS
how(e)}),m.dispatch.on("tooltipHide",function(e){S.tooltipHide(e)}),g.dispatch.on("tooltipShow",function(e){if(!Math.round(g.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),g.dispatch.on("tooltipHide",function(e){S.tooltipHide(e)}),h.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),h.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),p.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),p.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){o&&e.tooltip.cleanup()}),T.dispatch=S,T.lines1=h,T.lines2=p,T.bars1=d,T.bars2=v,T.stack1=m,T.stack2=g,T.xAxis=y,T.yAxis1=b,T.yAxis2=w,T.x=function(e){return arguments.length?(getX=e,h.x(e),d.x(e),T):getX},T.y=function(e){return arguments.length?(getY
=e,h.y(e),d.y(e),T):getY},T.margin=function(e){return arguments.length?(t=e,T):t},T.width=function(e){return arguments.length?(r=e,T):r},T.height=function(e){return arguments.length?(i=e,T):i},T.color=function(e){return arguments.length?(n=e,E.color(e),T):n},T.showLegend=function(e){return arguments.length?(s=e,T):s},T.tooltips=function(e){return arguments.length?(o=e,T):o},T.tooltipContent=function(e){return arguments.length?(u=e,T):u},T},e.models.ohlcBar=function(){function E(e){return e.each(function(e){var g=n-t.left-t.right,E=r-t.top-t.bottom,S=d3.select(this);s.domain(y||d3.extent(e[0].values.map(u).concat(p))),v?s.range([g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range([0,g]),o.domain(b||[d3.min(e[0].values.map(h).concat(d)),d3.max(e[0].values.map(c).concat(d))]).range([E,0]);if(s.domain()[0]===s.domain()[1]||o.domain()[0]===o.domain()[1])singlePoint=!0;s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.0
1,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var T=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([e[0].values]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),C=N.append("defs"),k=N.append("g"),L=T.select("g");k.append("g").attr("class","nv-ticks"),T.attr("transform","translate("+t.left+","+t.top+")"),S.on("click",function(e,t){w.chartClick({data:e,index:t,pos:d3.event,id:i})}),C.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),T.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",E),L.attr("clip-path",m?"url(#nv-chart-clip-path-"+i+")":"");var A=T.select(".nv-ticks").selectAll(".nv-tick").data(function(e){return e});A.exit().remove();var O=A.enter().append("path").attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+
n+"-"+t}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"}).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),w.elementMouseover({point:t,series:e[0],pos:[s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),w.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){w.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){w.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});A.attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" n
v-tick-"+n+"-"+t}),d3.transition(A).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"})}),E}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=function(e){return e.open},l=function(e){return e.close},c=function(e){return e.high},h=function(e){return e.low},p=[],d=[],v=!1,m=!0,g=e.utils.defaultColor(),y,b,w=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return E.dispatch=w,E.x=function(e){return arguments.length?(u=e,E):u},E.y=function(e){return arguments.length?(a=e,E):a},E.open=function(e){return arguments.length?(f=e,E):f},E.close=function(e){return arguments.length?(l=e,E):l},E.hi
gh=function(e){return arguments.length?(c=e,E):c},E.low=function(e){return arguments.length?(h=e,E):h},E.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.xScale=function(e){return arguments.length?(s=e,E):s},E.yScale=function(e){return arguments.length?(o=e,E):o},E.xDomain=function(e){return arguments.length?(y=e,E):y},E.yDomain=function(e){return arguments.length?(b=e,E):b},E.forceX=function(e){return arguments.length?(p=e,E):p},E.forceY=function(e){return arguments.length?(d=e,E):d},E.padData=function(e){return arguments.length?(v=e,E):v},E.clipEdge=function(e){return arguments.length?(m=e,E):m},E.color=function(t){return arguments.length?(g=e.utils.getColor(t),E):
g},E.id=function(e){return arguments.length?(i=e,E):i},E},e.models.pie=function(){function E(e){return e.each(function(e){function P(e){var t=(e.startAngle+e.endAngle)*90/Math.PI-90;return t>90?t-180:t}function H(e){v||(e.innerRadius=0);var t=d3.interpolate(this._current,e);return this._current=t(0),function(e){return L(t(e))}}function B(e){e.innerRadius=0;var t=d3.interpolate({startAngle:0,endAngle:0},e);return function(e){return L(t(e))}}var u=n-t.left-t.right,l=r-t.top-t.bottom,E=Math.min(u,l)/2,S=E-E/5,x=d3.select(this),T=x.selectAll(".nv-wrap.nv-pie").data([i(e[0])]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+a),C=N.append("g"),k=T.select("g");C.append("g").attr("class","nv-pie"),T.attr("transform","translate("+t.left+","+t.top+")"),k.select(".nv-pie").attr("transform","translate("+u/2+","+l/2+")"),x.on("click",function(e,t){w.chartClick({data:e,index:t,pos:d3.event,id:a})});var L=d3.svg.arc().outerRadius(S);g&&L.startAngle(g),y&&L.endAngle(y),
v&&L.innerRadius(E*b);var A=d3.layout.pie().sort(null).value(function(e){return e.disabled?0:o(e)}),O=T.select(".nv-pie").selectAll(".nv-slice").data(A);O.exit().remove();var M=O.enter().append("g").attr("class","nv-slice").on("mouseover",function(e,t){d3.select(this).classed("hover",!0),w.elementMouseover({label:s(e.data),value:o(e.data),point:e.data,pointIndex:t,pos:[d3.event.pageX,d3.event.pageY],id:a})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),w.elementMouseout({label:s(e.data),value:o(e.data),point:e.data,index:t,id:a})}).on("click",function(e,t){w.elementClick({label:s(e.data),value:o(e.data),point:e.data,index:t,pos:d3.event,id:a}),d3.event.stopPropagation()}).on("dblclick",function(e,t){w.elementDblClick({label:s(e.data),value:o(e.data),point:e.data,index:t,pos:d3.event,id:a}),d3.event.stopPropagation()});O.attr("fill",function(e,t){return f(e,t)}).attr("stroke",function(e,t){return f(e,t)});var _=M.append("path").each(function(e){this._curren
t=e});d3.transition(O.select("path")).attr("d",L).attrTween("d",H);if(c){var D=d3.svg.arc().innerRadius(0);h&&(D=L),p&&(D=d3.svg.arc().outerRadius(L.outerRadius())),M.append("g").classed("nv-label",!0).each(function(e,t){var n=d3.select(this);n.attr("transform",function(e){if(m){e.outerRadius=S+10,e.innerRadius=S+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+D.centroid(e)+") rotate("+t+")"}return e.outerRadius=E+10,e.innerRadius=E+15,"translate("+D.centroid(e)+")"}),n.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),n.append("text").style("text-anchor",m?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")}),O.select(".nv-label").transition().attr("transform",function(e){if(m){e.outerRadius=S+10,e.innerRadius=S+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+D.centroid(e)+
") rotate("+t+")"}return e.outerRadius=E+10,e.innerRadius=E+15,"translate("+D.centroid(e)+")"}),O.each(function(e,t){var n=d3.select(this);n.select(".nv-label text").style("text-anchor",m?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").text(function(e,t){var n=(e.endAngle-e.startAngle)/(2*Math.PI);return e.value&&n>d?s(e.data):""});var r=n.select("text").node().getBBox();n.select(".nv-label rect").attr("width",r.width+10).attr("height",r.height+10).attr("transform",function(){return"translate("+[r.x-5,r.y-5]+")"})})}}),E}var t={top:0,right:0,bottom:0,left:0},n=500,r=500,i=function(e){return e.values},s=function(e){return e.x},o=function(e){return e.y},u=function(e){return e.description},a=Math.floor(Math.random()*1e4),f=e.utils.defaultColor(),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d=.02,v=!1,m=!1,g=!1,y=!1,b=.5,w=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return E.dispatch=w,E.margin=function(e){return arguments.le
ngth?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.values=function(e){return arguments.length?(i=e,E):i},E.x=function(e){return arguments.length?(s=e,E):s},E.y=function(e){return arguments.length?(o=d3.functor(e),E):o},E.description=function(e){return arguments.length?(u=e,E):u},E.showLabels=function(e){return arguments.length?(c=e,E):c},E.labelSunbeamLayout=function(e){return arguments.length?(m=e,E):m},E.donutLabelsOutside=function(e){return arguments.length?(p=e,E):p},E.pieLabelsOutside=function(e){return arguments.length?(h=e,E):h},E.donut=function(e){return arguments.length?(v=e,E):v},E.donutRatio=function(e){return arguments.length?(b=e,E):b},E.startAngle=function(e){return arguments.length?(g=e,E):g
},E.endAngle=function(e){return arguments.length?(y=e,E):y},E.id=function(e){return arguments.length?(a=e,E):a},E.color=function(t){return arguments.length?(f=e.utils.getColor(t),E):f},E.valueFormat=function(e){return arguments.length?(l=e,E):l},E.labelThreshold=function(e){return arguments.length?(d=e,E):d},E},e.models.pieChart=function(){function v(e){return e.each(function(u){var a=d3.select(this),f=this,d=(i||parseInt(a.style("width"))||960)-r.left-r.right,m=(s||parseInt(a.style("height"))||400)-r.top-r.bottom;v.update=function(){v(e)},v.container=this,l.disabled=u[0].map(function(e){return!!e.disabled});if(!c){var g;c={};for(g in l)l[g]instanceof Array?c[g]=l[g].slice(0):c[g]=l[g]}if(!u[0]||!u[0].length){var y=a.selectAll(".nv-noData").data([h]);return y.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),y.attr("x",r.left+d/2).attr("y",r.top+m/2).text(function(e){return e}),v}a.selectAll(".nv-noData").remove();var b=a.
selectAll("g.nv-wrap.nv-pieChart").data([u]),w=b.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),E=b.select("g");w.append("g").attr("class","nv-pieWrap"),w.append("g").attr("class","nv-legendWrap"),o&&(n.width(d).key(t.x()),b.select(".nv-legendWrap").datum(t.values()(u[0])).call(n),r.top!=n.height()&&(r.top=n.height(),m=(s||parseInt(a.style("height"))||400)-r.top-r.bottom),b.select(".nv-legendWrap").attr("transform","translate(0,"+ -r.top+")")),b.attr("transform","translate("+r.left+","+r.top+")"),t.width(d).height(m);var S=E.select(".nv-pieWrap").datum(u);d3.transition(S).call(t),n.dispatch.on("legendClick",function(n,r,i){n.disabled=!n.disabled,t.values()(u[0]).filter(function(e){return!e.disabled}).length||t.values()(u[0]).map(function(e){return e.disabled=!1,b.selectAll(".nv-series").classed("disabled",!1),e}),l.disabled=u[0].map(function(e){return!!e.disabled}),p.stateChange(l),e.transition().call(v)}),t.dispatch.on("elementMouseout.tooltip",fun
ction(e){p.tooltipHide(e)}),p.on("changeState",function(t){typeof t.disabled!="undefined"&&(u[0].forEach(function(e,n){e.disabled=t.disabled[n]}),l.disabled=t.disabled),e.call(v)})}),v}var t=e.models.pie(),n=e.models.legend(),r={top:30,right:20,bottom:20,left:20},i=null,s=null,o=!0,u=e.utils.defaultColor(),a=!0,f=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+t+"</p>"},l={},c=null,h="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),d=function(n,r){var i=t.description()(n.point)||t.x()(n.point),s=n.pos[0]+(r&&r.offsetLeft||0),o=n.pos[1]+(r&&r.offsetTop||0),u=t.valueFormat()(t.y()(n.point)),a=f(i,u,n,v);e.tooltip.show([s,o],a,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+r.left,e.pos[1]+r.top],p.tooltipShow(e)}),p.on("tooltipShow",function(e){a&&d(e)}),p.on("tooltipHide",function(){a&&e.tooltip.cleanup()}),v.legend=n,v.dispatch=p,v.pie=t,d3.rebind(v,t,"valueFormat","values","x","
y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","donut","donutRatio","labelThreshold"),v.margin=function(e){return arguments.length?(r.top=typeof e.top!="undefined"?e.top:r.top,r.right=typeof e.right!="undefined"?e.right:r.right,r.bottom=typeof e.bottom!="undefined"?e.bottom:r.bottom,r.left=typeof e.left!="undefined"?e.left:r.left,v):r},v.width=function(e){return arguments.length?(i=e,v):i},v.height=function(e){return arguments.length?(s=e,v):s},v.color=function(r){return arguments.length?(u=e.utils.getColor(r),n.color(u),t.color(u),v):u},v.showLegend=function(e){return arguments.length?(o=e,v):o},v.tooltips=function(e){return arguments.length?(a=e,v):a},v.tooltipContent=function(e){return arguments.length?(f=e,v):f},v.state=function(e){return arguments.length?(l=e,v):l},v.defaultState=function(e){return arguments.length?(c=e,v):c},v.noData=function(e){return arguments.length?(h=e,v):h},v},e.models.scatter=function(){function B(e){return e.each(fun
ction(e){function V(){if(!g)return!1;var i,a=d3.merge(e.map(function(e,t){return e.values.map(function(e,n){var r=f(e,n)+Math.random()*1e-10,i=l(e,n)+Math.random()*1e-10;return[o(r),u(i),t,n,e]}).filter(function(e,t){return y(e[4],t)})}));if(O===!0){if(S){var c=q.select("defs").selectAll(".nv-point-clips").data([s]).enter();c.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+s);var h=q.select("#nv-points-clip-"+s).selectAll("circle").data(a);h.enter().append("circle").attr("r",x),h.exit().remove(),h.attr("cx",function(e){return e[0]}).attr("cy",function(e){return e[1]}),q.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+s+")")}a.push([o.range()[0]-20,u.range()[0]-20,null,null]),a.push([o.range()[1]+20,u.range()[1]+20,null,null]),a.push([o.range()[0]-20,u.range()[0]+20,null,null]),a.push([o.range()[1]+20,u.range()[1]-20,null,null]);var p=d3.geom.polygon([[-10,-10],[-10,r+10],[n+10,r+10],[n+10,-10]]),d=d3.geom.voronoi(a).map(functio
n(e,t){return{data:p.clip(e),series:a[t][2],point:a[t][3]}}),v=q.select(".nv-point-paths").selectAll("path").data(d);v.enter().append("path").attr("class",function(e,t){return"nv-path-"+t}),v.exit().remove(),v.attr("d",function(e){return e.data.length===0?"M 0 0":"M"+e.data.join("L")+"Z"}),v.on("click",function(n){if(H)return 0;var r=e[n.series],i=r.values[n.point];A.elementClick({point:i,series:r,pos:[o(f(i,n.point))+t.left,u(l(i,n.point))+t.top],seriesIndex:n.series,pointIndex:n.point})}).on("mouseover",function(n){if(H)return 0;var r=e[n.series],i=r.values[n.point];A.elementMouseover({point:i,series:r,pos:[o(f(i,n.point))+t.left,u(l(i,n.point))+t.top],seriesIndex:n.series,pointIndex:n.point})}).on("mouseout",function(t,n){if(H)return 0;var r=e[t.series],i=r.values[t.point];A.elementMouseout({point:i,series:r,seriesIndex:t.series,pointIndex:t.point})})}else q.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(n,r){if(H||!e[n.series])retu
rn 0;var i=e[n.series],s=i.values[r];A.elementClick({point:s,series:i,pos:[o(f(s,r))+t.left,u(l(s,r))+t.top],seriesIndex:n.series,pointIndex:r})}).on("mouseover",function(n,r){if(H||!e[n.series])return 0;var i=e[n.series],s=i.values[r];A.elementMouseover({point:s,series:i,pos:[o(f(s,r))+t.left,u(l(s,r))+t.top],seriesIndex:n.series,pointIndex:r})}).on("mouseout",function(t,n){if(H||!e[t.series])return 0;var r=e[t.series],i=r.values[n];A.elementMouseout({point:i,series:r,seriesIndex:t.series,pointIndex:n})});H=!1}var B=n-t.left-t.right,j=r-t.top-t.bottom,F=d3.select(this);e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e});var I=T&&N&&C?[]:d3.merge(e.map(function(e){return e.values.map(function(e,t){return{x:f(e,t),y:l(e,t),size:c(e,t)}})}));o.domain(T||d3.extent(I.map(function(e){return e.x}).concat(d))),b&&e[0]?o.range([(B*w+B)/(2*e[0].values.length),B-B*(1+w)/(2*e[0].values.length)]):o.range([0,B]),u.domain(N||d3.extent(I.map(function(e)
{return e.y}).concat(v))).range([j,0]),a.domain(C||d3.extent(I.map(function(e){return e.size}).concat(m))).range(k||[16,256]);if(o.domain()[0]===o.domain()[1]||u.domain()[0]===u.domain()[1])L=!0;o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]-o.domain()[0]*.01,o.domain()[1]+o.domain()[1]*.01]):o.domain([-1,1])),u.domain()[0]===u.domain()[1]&&(u.domain()[0]?u.domain([u.domain()[0]+u.domain()[0]*.01,u.domain()[1]-u.domain()[1]*.01]):u.domain([-1,1])),isNaN(o.domain()[0])&&o.domain([-1,1]),isNaN(u.domain()[0])&&u.domain([-1,1]),M=M||o,_=_||u,D=D||a;var q=F.selectAll("g.nv-wrap.nv-scatter").data([e]),R=q.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+s+(L?" nv-single-point":"")),U=R.append("defs"),W=R.append("g"),X=q.select("g");W.append("g").attr("class","nv-groups"),W.append("g").attr("class","nv-point-paths"),q.attr("transform","translate("+t.left+","+t.top+")"),U.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),q.sele
ct("#nv-edge-clip-"+s+" rect").attr("width",B).attr("height",j),X.attr("clip-path",E?"url(#nv-edge-clip-"+s+")":""),H=!0;var $=q.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});$.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition($.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),$.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),d3.transition($).style("fill",function(e,t){return i(e,t)}).style("stroke",function(e,t){return i(e,t)}).style("stroke-opacity",1).style("fill-opacity",.5);if(p){var J=$.selectAll("circle.nv-point").data(function(e){return e.values});J.enter().append("circle").attr("cx",function(e,t){return M(f(e,t))}).attr("cy",function(e,t){return _(l(e,t))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)}),J.exit().remove(),d3.transition($.exit().selectAll("path.nv-point")).attr("cx",fu
nction(e,t){return o(f(e,t))}).attr("cy",function(e,t){return u(l(e,t))}).remove(),J.attr("class",function(e,t){return"nv-point nv-point-"+t}),d3.transition(J).attr("cx",function(e,t){return o(f(e,t))}).attr("cy",function(e,t){return u(l(e,t))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)})}else{var J=$.selectAll("path.nv-point").data(function(e){return e.values});J.enter().append("path").attr("transform",function(e,t){return"translate("+M(f(e,t))+","+_(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))})),J.exit().remove(),d3.transition($.exit().selectAll("path.nv-point")).attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).remove(),J.attr("class",function(e,t){return"nv-point nv-point-"+t}),d3.transition(J).attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))}))}clearTimeout(P),P=setTimeout(V,300),M=o.cop
y(),_=u.copy(),D=a.copy()}),B}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=d3.scale.linear(),u=d3.scale.linear(),a=d3.scale.linear(),f=function(e){return e.x},l=function(e){return e.y},c=function(e){return e.size||1},h=function(e){return e.shape||"circle"},p=!0,d=[],v=[],m=[],g=!0,y=function(e){return!e.notActive},b=!1,w=.1,E=!1,S=!0,x=function(){return 25},T=null,N=null,C=null,k=null,L=!1,A=d3.dispatch("elementClick","elementMouseover","elementMouseout"),O=!0,M,_,D,P,H=!1;return A.on("elementMouseover.point",function(e){g&&d3.select(".nv-chart-"+s+" .nv-series-"+e.seriesIndex+" .nv-point-"+e.pointIndex).classed("hover",!0)}),A.on("elementMouseout.point",function(e){g&&d3.select(".nv-chart-"+s+" .nv-series-"+e.seriesIndex+" .nv-point-"+e.pointIndex).classed("hover",!1)}),B.dispatch=A,B.x=function(e){return arguments.length?(f=d3.functor(e),B):f},B.y=function(e){return arguments.length?(l=d3.functor(e),B):l},B.si
ze=function(e){return arguments.length?(c=d3.functor(e),B):c},B.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,B):t},B.width=function(e){return arguments.length?(n=e,B):n},B.height=function(e){return arguments.length?(r=e,B):r},B.xScale=function(e){return arguments.length?(o=e,B):o},B.yScale=function(e){return arguments.length?(u=e,B):u},B.zScale=function(e){return arguments.length?(a=e,B):a},B.xDomain=function(e){return arguments.length?(T=e,B):T},B.yDomain=function(e){return arguments.length?(N=e,B):N},B.sizeDomain=function(e){return arguments.length?(C=e,B):C},B.sizeRange=function(e){return arguments.length?(k=e,B):k},B.forceX=function(e){return arguments.length?(d=e,B):d},B.forceY=function(e){return arguments.length?(v=e,B):v},B.forceSize=function(e){return arguments.length?(m=
e,B):m},B.interactive=function(e){return arguments.length?(g=e,B):g},B.pointActive=function(e){return arguments.length?(y=e,B):y},B.padData=function(e){return arguments.length?(b=e,B):b},B.padDataOuter=function(e){return arguments.length?(w=e,B):w},B.clipEdge=function(e){return arguments.length?(E=e,B):E},B.clipVoronoi=function(e){return arguments.length?(S=e,B):S},B.useVoronoi=function(e){return arguments.length?(O=e,O===!1&&(S=!1),B):O},B.clipRadius=function(e){return arguments.length?(x=e,B):x},B.color=function(t){return arguments.length?(i=e.utils.getColor(t),B):i},B.shape=function(e){return arguments.length?(h=e,B):h},B.onlyCircles=function(e){return arguments.length?(p=e,B):p},B.id=function(e){return arguments.length?(s=e,B):s},B.singlePoint=function(e){return arguments.length?(L=e,B):L},B},e.models.scatterChart=function(){function P(e){return e.each(function(x){function X(){if(E)return U.select(".nv-point-paths").style("pointer-events","all"),!1;U.select(".nv-point-pa
ths").style("pointer-events","none");var e=d3.mouse(this);h.distortion(w).focus(e[0]),p.distortion(w).focus(e[1]),U.select(".nv-scatterWrap"
+).call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r),U.select(".nv-distributionX").datum(x.filter(function(e){return!e.disabled})).call(o),U.select(".nv-distributionY").datum(x.filter(function(e){return!e.disabled})).call(u)}var T=d3.select(this),N=this,H=(f||parseInt(T.style("width"))||960)-a.left-a.right,B=(l||parseInt(T.style("height"))||400)-a.top-a.bottom;P.update=function(){P(e)},P.container=this,C.disabled=x.map(function(e){return!!e.disabled});if(!k){var j;k={};for(j in C)C[j]instanceof Array?k[j]=C[j].slice(0):k[j]=C[j]}if(!x||!x.length||!x.filter(function(e){return e.values.length}).length){var F=T.selectAll(".nv-noData").data([A]);return F.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),F.attr("x",a.left+H/2).attr("y",a.top+B/2).text(function(e){return e}),P}T.selectAll(".nv-noData").remove(),O=O||h,M=M||p;var I=T.selectAll("g.nv-wrap.nv-scatterChart").data([x]),q=I.enter().append("g")
.attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),R=q.append("g"),U=I.select("g");R.append("rect").attr("class","nvd3 nv-background"),R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-scatterWrap"),R.append("g").attr("class","nv-distWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),y&&(i.width(H/2),I.select(".nv-legendWrap").datum(x).call(i),a.top!=i.height()&&(a.top=i.height(),B=(l||parseInt(T.style("height"))||400)-a.top-a.bottom),I.select(".nv-legendWrap").attr("transform","translate("+H/2+","+ -a.top+")")),b&&(s.width(180).color(["#444"]),U.select(".nv-controlsWrap").datum(D).attr("transform","translate(0,"+ -a.top+")").call(s)),I.attr("transform","translate("+a.left+","+a.top+")"),t.width(H).height(B).color(x.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!x[t].disabled})),I.select(".nv-scatterWrap").datum(x.filter(functio
n(e){return!e.disabled})).call(t);if(d){var z=h.domain()[1]-h.domain()[0];h.domain([h.domain()[0]-d*z,h.domain()[1]+d*z])}if(v){var W=p.domain()[1]-p.domain()[0];p.domain([p.domain()[0]-v*W,p.domain()[1]+v*W])}n.scale(h).ticks(n.ticks()&&n.ticks().length?n.ticks():H/100).tickSize(-B,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n),r.scale(p).ticks(r.ticks()&&r.ticks().length?r.ticks():B/36).tickSize(-H,0),U.select(".nv-y.nv-axis").call(r),m&&(o.getData(t.x()).scale(h).width(H).color(x.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!x[t].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),U.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(x.filter(function(e){return!e.disabled})).call(o)),g&&(u.getData(t.y()).scale(p).width(B).color(x.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!x[t].disabled})),R.select(".nv-distWrap").append
("g").attr("class","nv-distributionY"),U.select(".nv-distributionY").attr("transform","translate(-"+u.size()+",0)").datum(x.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(U.select(".nv-background").attr("width",H).attr("height",B),U.select(".nv-background").on("mousemove",X),U.select(".nv-background").on("click",function(){E=!E}),t.dispatch.on("elementClick.freezeFisheye",function(){E=!E})),s.dispatch.on("legendClick",function(i,s){i.disabled=!i.disabled,w=i.disabled?0:2.5,U.select(".nv-background").style("pointer-events",i.disabled?"none":"all"),U.select(".nv-point-paths").style("pointer-events",i.disabled?"all":"none"),i.disabled?(h.distortion(w).focus(0),p.distortion(w).focus(0),U.select(".nv-scatterWrap").call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r)):E=!1,P(e)}),i.dispatch.on("legendClick",function(t,n,r){t.disabled=!t.disabled,x.filter(function(e){return!e.disabled}).length||x.map(function(e){return e.disabled=!1,I.selectAll
(".nv-series").classed("disabled",!1),e}),C.disabled=x.map(function(e){return!!e.disabled}),L.stateChange(C),P(e)}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-B),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],L.tooltipShow(e)}),L.on("tooltipShow",function(e){S&&_(e,N.parentNode)}),L.on("changeState",function(t){typeof t.disabled!="undefined"&&(x.forEach(function(e,n){e.disabled=t.disabled[n]}),C.disabled=t.disabled),e.call(P)}),O=h.copy(),M=p.copy()}),P}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.
fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=0,v=0,m=!1,g=!1,y=!0,b=!!d3.fisheye,w=0,E=!1,S=!0,x=function(e,t,n){return"<strong>"+t+"</strong>"},T=function(e,t,n){return"<strong>"+n+"</strong>"},N=null,C={},k=null,L=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),A="No Data Available.";t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient("left").tickPadding(10),o.axis("x"),u.axis("y");var O,M,_=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));x!=null&&e.tooltip.show([f,l],x(i.series.key,v,m,i,P),"n",1,s,"x-nvtooltip"),T!=null&&e.tooltip.show([c,d],T(i.series.key,v,m,i,P),"e",1,s,"y-nvtooltip"),N!=null&&e.tooltip.show([o,u],N(i.series.key,v,m,i,P),i.value<0?"n":"s",null,
s)},D=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){L.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),L.on("tooltipHide",function(){S&&e.tooltip.cleanup()}),P.dispatch=L,P.scatter=t,P.legend=i,P.controls=s,P.xAxis=n,P.yAxis=r,P.distX=o,P.distY=u,d3.rebind(P,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),P.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,P):a},P.width=function(e){return arguments.length?(f=e,P):f},P.he
ight=function(e){return arguments.length?(l=e,P):l},P.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),P):c},P.showDistX=function(e){return arguments.length?(m=e,P):m},P.showDistY=function(e){return arguments.length?(g=e,P):g},P.showControls=function(e){return arguments.length?(b=e,P):b},P.showLegend=function(e){return arguments.length?(y=e,P):y},P.fisheye=function(e){return arguments.length?(w=e,P):w},P.xPadding=function(e){return arguments.length?(d=e,P):d},P.yPadding=function(e){return arguments.length?(v=e,P):v},P.tooltips=function(e){return arguments.length?(S=e,P):S},P.tooltipContent=function(e){return arguments.length?(N=e,P):N},P.tooltipXContent=function(e){return arguments.length?(x=e,P):x},P.tooltipYContent=function(e){return arguments.length?(T=e,P):T},P.state=function(e){return arguments.length?(C=e,P):C},P.defaultState=function(e){return arguments.length?(k=e,P):k},P.noData=function(e){return arguments.length?(A=e
,P):A},P},e.models.scatterPlusLineChart=function(){function _(e){return e.each(function(E){function z(){if(b)return q.select(".nv-point-paths").style("pointer-events","all"),!1;q.select(".nv-point-paths").style("pointer-events","none");var e=d3.mouse(this);h.distortion(y).focus(e[0]),p.distortion(y).focus(e[1]),q.select(".nv-scatterWrap").datum(E.filter(function(e){return!e.disabled})).call(t),q.select(".nv-x.nv-axis").call(n),q.select(".nv-y.nv-axis").call(r),q.select(".nv-distributionX").datum(E.filter(function(e){return!e.disabled})).call(o),q.select(".nv-distributionY").datum(E.filter(function(e){return!e.disabled})).call(u)}var S=d3.select(this),x=this,D=(f||parseInt(S.style("width"))||960)-a.left-a.right,P=(l||parseInt(S.style("height"))||400)-a.top-a.bottom;_.update=function(){_(e)},_.container=this,T.disabled=E.map(function(e){return!!e.disabled});if(!N){var H;N={};for(H in T)T[H]instanceof Array?N[H]=T[H].slice(0):N[H]=T[H]}if(!E||!E.length||!E.filter(function(e){re
turn e.values.length}).length){var B=S.selectAll(".nv-noData").data([k]);return B.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),B.attr("x",a.left+D/2).attr("y",a.top+P/2).text(function(e){return e}),_}S.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale(),L=L||h,A=A||p;var j=S.selectAll("g.nv-wrap.nv-scatterChart").data([E]),F=j.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),I=F.append("g"),q=j.select("g");I.append("rect").attr("class","nvd3 nv-background"),I.append("g").attr("class","nv-x nv-axis"),I.append("g").attr("class","nv-y nv-axis"),I.append("g").attr("class","nv-scatterWrap"),I.append("g").attr("class","nv-regressionLinesWrap"),I.append("g").attr("class","nv-distWrap"),I.append("g").attr("class","nv-legendWrap"),I.append("g").attr("class","nv-controlsWrap"),j.attr("transform","translate("+a.left+","+a.top+")"),m&&(i.width(D/2),j.select(".nv-legendWrap").datum(E).call(i
),a.top!=i.height()&&(a.top=i.height(),P=(l||parseInt(S.style("height"))||400)-a.top-a.bottom),j.select(".nv-legendWrap").attr("transform","translate("+D/2+","+ -a.top+")")),g&&(s.width(180).color(["#444"]),q.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+ -a.top+")").call(s)),t.width(D).height(P).color(E.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!E[t].disabled})),j.select(".nv-scatterWrap").datum(E.filter(function(e){return!e.disabled})).call(t),j.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+t.id()+")");var R=j.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(e){return e}),U=R.enter().append("g").attr("class","nv-regLines").append("line").attr("class","nv-regLine").style("stroke-opacity",0);R.selectAll(".nv-regLines line").attr("x1",h.range()[0]).attr("x2",h.range()[1]).attr("y1",function(e,t){return p(h.domain()[0]*e.slope+e.intercept)}).attr("y2",function(e,t){return p(h.d
omain()[1]*e.slope+e.intercept)}).style("stroke",function(e,t,n){return c(e,n)}).style("stroke-opacity",function(e,t){return e.disabled||typeof e.slope=="undefined"||typeof e.intercept=="undefined"?0:1}),n.scale(h).ticks(n.ticks()?n.ticks():D/100).tickSize(-P,0),q.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n),r.scale(p).ticks(r.ticks()?r.ticks():P/36).tickSize(-D,0),q.select(".nv-y.nv-axis").call(r),d&&(o.getData(t.x()).scale(h).width(D).color(E.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!E[t].disabled})),I.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),q.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(E.filter(function(e){return!e.disabled})).call(o)),v&&(u.getData(t.y()).scale(p).width(P).color(E.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!E[t].disabled})),I.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),q.s
elect(".nv-distributionY").attr("transform","translate(-"+u.size()+",0)").datum(E.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(q.select(".nv-background").attr("width",D).attr("height",P),q.select(".nv-background").on("mousemove",z),q.select(".nv-background").on("click",function(){b=!b}),t.dispatch.on("elementClick.freezeFisheye",function(){b=!b})),s.dispatch.on("legendClick",function(i,s){i.disabled=!i.disabled,y=i.disabled?0:2.5,q.select(".nv-background").style("pointer-events",i.disabled?"none":"all"),q.select(".nv-point-paths").style("pointer-events",i.disabled?"all":"none"),i.disabled?(h.distortion(y).focus(0),p.distortion(y).focus(0),q.select(".nv-scatterWrap").call(t),q.select(".nv-x.nv-axis").call(n),q.select(".nv-y.nv-axis").call(r)):b=!1,_(e)}),i.dispatch.on("legendClick",function(t,n,r){t.disabled=!t.disabled,E.filter(function(e){return!e.disabled}).length||E.map(function(e){return e.disabled=!1,j.selectAll(".nv-series").classed("disabled",!1),e}),
T.disabled=E.map(function(e){return!!e.disabled}),C.stateChange(T),_(e)}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-P),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],C.tooltipShow(e)}),C.on("tooltipShow",function(e){w&&O(e,x.parentNode)}),C.on("changeState",function(t){typeof t.disabled!="undefined"&&(E.forEach(function(e,n){e.disabled=t.disabled[n]}),T.disabled=t.disabled),e.call(_)}),L=h.copy(),A=p.copy()}),_}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).
distortion(0):t.yScale(),d=!1,v=!1,m=!0,g=!!d3.fisheye,y=0,b=!1,w=!0,E=function(e,t,n){return"<strong>"+t+"</strong>"},S=function(e,t,n){return"<strong>"+n+"</strong>"},x=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+r+"</p>"},T={},N=null,C=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),k="No Data Available.";t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient("left").tickPadding(10),o.axis("x"),u.axis("y");var L,A,O=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));E!=null&&e.tooltip.show([f,l],E(i.series.key,v,m,i,_),"n",1,s,"x-nvtooltip"),S!=null&&e.tooltip.show([c,d],S(i.series.key,v,m,i,_),"e",1,s,"y-nvtooltip"),x!=null&&e.tooltip.show([o,u],x(i.series.key,v,m,i.point.tooltip,i,_),i.val
ue<0?"n":"s",null,s)},M=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){C.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),C.on("tooltipHide",function(){w&&e.tooltip.cleanup()}),_.dispatch=C,_.scatter=t,_.legend=i,_.controls=s,_.xAxis=n,_.yAxis=r,_.distX=o,_.distY=u,d3.rebind(_,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),_.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,_):a},_.width=function(e){return arguments.leng
th?(f=e,_):f},_.height=function(e){return arguments.length?(l=e,_):l},_.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),_):c},_.showDistX=function(e){return arguments.length?(d=e,_):d},_.showDistY=function(e){return arguments.length?(v=e,_):v},_.showControls=function(e){return arguments.length?(g=e,_):g},_.showLegend=function(e){return arguments.length?(m=e,_):m},_.fisheye=function(e){return arguments.length?(y=e,_):y},_.tooltips=function(e){return arguments.length?(w=e,_):w},_.tooltipContent=function(e){return arguments.length?(x=e,_):x},_.tooltipXContent=function(e){return arguments.length?(E=e,_):E},_.tooltipYContent=function(e){return arguments.length?(S=e,_):S},_.state=function(e){return arguments.length?(T=e,_):T},_.defaultState=function(e){return arguments.length?(N=e,_):N},_.noData=function(e){return arguments.length?(k=e,_):k},_},e.models.sparkline=function(){function h(e){return e.each(function(e){var i=n-t.left-t.r
ight,h=r-t.top-t.bottom,p=d3.select(this);s.domain(l||d3.extent(e,u)).range([0,i]),o.domain(c||d3.extent(e,a)).range([h,0]);var d=p.selectAll("g.nv-wrap.nv-sparkline").data([e]),v=d.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline"),m=v.append("g"),g=d.select("g");d.attr("transform","translate("+t.left+","+t.top+")");var b=d.selectAll("path").data(function(e){return[e]});b.enter().append("path"),b.exit().remove(),b.style("stroke",function(e,t){return e.color||f(e,t)}).attr("d",d3.svg.line().x(function(e,t){return s(u(e,t))}).y(function(e,t){return o(a(e,t))}));var w=d.selectAll("circle.nv-point").data(function(e){function n(t){if(t!=-1){var n=e[t];return n.pointIndex=t,n}return null}var t=e.map(function(e,t){return a(e,t)}),r=n(t.lastIndexOf(o.domain()[1])),i=n(t.indexOf(o.domain()[0])),s=n(t.length-1);return[i,r,s].filter(function(e){return e!=null})});w.enter().append("circle"),w.exit().remove(),w.attr("cx",function(e,t){return s(u(e,e.pointIndex))}).attr("cy",f
unction(e,t){return o(a(e,e.pointIndex))}).attr("r",2).attr("class",function(e,t){return u(e,e.pointIndex)==s.domain()[1]?"nv-point nv-currentValue":a(e,e.pointIndex)==o.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),h}var t={top:2,right:0,bottom:2,left:0},n=400,r=32,i=!0,s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=e.utils.getColor(["#000"]),l,c;return h.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,h):t},h.width=function(e){return arguments.length?(n=e,h):n},h.height=function(e){return arguments.length?(r=e,h):r},h.x=function(e){return arguments.length?(u=d3.functor(e),h):u},h.y=function(e){return arguments.length?(a=d3.functor(e),h):a},h.xScale=function(e){return arguments.length?(s=e,h):s},h.yScale=function(e){ret
urn arguments.length?(o=e,h):o},h.xDomain=function(e){return arguments.length?(l=e,h):l},h.yDomain=function(e){return arguments.length?(c=e,h):c},h.animate=function(e){return arguments.length?(i=e,h):i},h.color=function(t){return arguments.length?(f=e.utils.getColor(t),h):f},h},e.models.sparklinePlus=function(){function v(e){return e.each(function(c){function O(){if(a)return;var e=C.selectAll(".nv-hoverValue").data(u),r=e.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);e.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),e.attr("transform",function(e){return"translate("+s(t.x()(c[e],e))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1);if(!u.length)return;r.append("line").attr("x1",0).attr("y1",-n.top).attr("x2",0).attr("y2",b),r.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-n.top).attr("text-anchor","end").attr("dy",".9em"),C.sel
ect(".nv-hoverValue .nv-xValue").text(f(t.x()(c[u[0]],u[0]))),r.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-n.top).attr("text-anchor","start").attr("dy",".9em"),C.select(".nv-hoverValue .nv-yValue").text(l(t.y()(c[u[0]],u[0])))}function M(){function r(e,n){var r=Math.abs(t.x()(e[0],0)-n),i=0;for(var s=0;s<e.length;s++)Math.abs(t.x()(e[s],s)-n)<r&&(r=Math.abs(t.x()(e[s],s)-n),i=s);return i}if(a)return;var e=d3.mouse(this)[0]-n.left;u=[r(c,Math.round(s.invert(e)))],O()}var m=d3.select(this),g=(r||parseInt(m.style("width"))||960)-n.left-n.right,b=(i||parseInt(m.style("height"))||400)-n.top-n.bottom;v.update=function(){v(e)},v.container=this;if(!c||!c.length){var w=m.selectAll(".nv-noData").data([d]);return w.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),w.attr("x",n.left+g/2).attr("y",n.top+b/2).text(function(e){return e}),v}m.selectAll(".nv-noData").remove();var E=t.y()(c[c.length-1],c.length-1);s=t.xS
cale(),o=t.yScale();var S=m.selectAll("g.nv-wrap.nv-sparklineplus").data([c]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-sparklineWrap"),N.append("g").attr("class","nv-valueWrap"),N.append("g").attr("class","nv-hoverArea"),S.attr("transform","translate("+n.left+","+n.top+")");var k=C.select(".nv-sparklineWrap");t.width(g).height(b),k.call(t);var L=C.select(".nv-valueWrap"),A=L.selectAll(".nv-currentValue").data([E]);A.enter().append("text").attr("class","nv-currentValue").attr("dx",p?-8:8).attr("dy",".9em").style("text-anchor",p?"end":"start"),A.attr("x",g+(p?n.right:0)).attr("y",h?function(e){return o(e)}:0).style("fill",t.color()(c[c.length-1],c.length-1)).text(l(E)),N.select(".nv-hoverArea").append("rect").on("mousemove",M).on("click",function(){a=!a}).on("mouseout",function(){u=[],O()}),C.select(".nv-hoverArea rect").attr("transform",function(e){return"translate("+ -n.left+","+ -n.t
op+")"}).attr("width",g+n.left+n.right).attr("height",b+n.top)}),v}var t=e.models.sparkline(),n={top:15,right:100,bottom:10,left:50},r=null,i=null,s,o,u=[],a=!1,f=d3.format(",r"),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d="No Data Available.";return v.sparkline=t,d3.rebind(v,t,"x","y","xScale","yScale","color"),v.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,v):n},v.width=function(e){return arguments.length?(r=e,v):r},v.height=function(e){return arguments.length?(i=e,v):i},v.xTickFormat=function(e){return arguments.length?(f=e,v):f},v.yTickFormat=function(e){return arguments.length?(l=e,v):l},v.showValue=function(e){return arguments.length?(c=e,v):c},v.alignValue=function(e){return arguments.length?(h=e,v):h},v.rightAlignValue=function(e){return arguments.length?(p=e,v):p},v.noData=func
tion(e){return arguments.length?(d=e,v):d},v},e.models.stackedArea=function(){function g(e){return e.each(function(e){var a=n-t.left-t.right,g=r-t.top-t.bottom,b=d3.select(this);p=v.xScale(),d=v.yScale(),e=e.map(function(e,t){return e.values=e.values.map(function(t,n){return t.index=n,t.stackedY=e.disabled?0:u(t,n),t}),e}),e=d3.layout.stack().order(l).offset(f).values(function(e){return e.values}).x(o).y(function(e){return e.stackedY}).out(function(e,t,n){e.display={y:n,y0:t}})(e);var w=b.selectAll("g.nv-wrap.nv-stackedarea").data([e]),E=w.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),S=E.append("defs"),T=E.append("g"),N=w.select("g");T.append("g").attr("class","nv-areaWrap"),T.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+t.left+","+t.top+")"),v.width(a).height(g).x(o).y(function(e){return e.display.y+e.display.y0}).forceY([0]).color(e.map(function(e,t){return e.color||i(e,t)}).filter(function(t,n){return!e[n].disabled}));var C
=N.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled}));C.call(v),S.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),w.select("#nv-edge-clip-"+s+" rect").attr("width",a).attr("height",g),N.attr("clip-path",h?"url(#nv-edge-clip-"+s+")":"");var k=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y+e.display.y0)}).interpolate(c),L=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y0)}),A=N.select(".nv-areaWrap").selectAll("path.nv-area").data(function(e){return e});A.enter().append("path").attr("class",function(e,t){return"nv-area nv-area-"+t}).on("mouseover",function(e,t){d3.select(this).classed("hover",!0),m.areaMouseover({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:t})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),m.areaMouseout({point:e,series:e.key,po
s:[d3.event.pageX,d3.event.pageY],seriesIndex:t})}).on("click",function(e,t){d3.select(this).classed("hover",!1),m.areaClick({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:t})}),A.exit().attr("d",function(e,t){return L(e.values,t)}).remove(),A.style("fill",function(e,t){return e.color||i(e,t)}).style("stroke",function(e,t){return e.color||i(e,t)}),A.attr("d",function(e,t){return k(e.values,t)}),v.dispatch.on("elementMouseover.area",function(e){N.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!0)}),v.dispatch.on("elementMouseout.area",function(e){N.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!1)})}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=function(e){return e.x},u=function(e){return e.y},a="stack",f="zero",l="default",c="linear",h=!1,p,d,v=e.models.scatter(),m=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout");
return v.size(2.2).sizeDomain([2.2,2.2]),v.dispatch.on("elementClick.area",function(e){m.areaClick(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],m.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){m.tooltipHide(e)}),g.dispatch=m,g.scatter=v,d3.rebind(g,v,"interactive","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","forceX","forceY","forceSize","clipVoronoi","clipRadius"),g.x=function(e){return arguments.length?(o=d3.functor(e),g):o},g.y=function(e){return arguments.length?(u=d3.functor(e),g):u},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.clipEdge=function(e){return argume
nts.length?(h=e,g):h},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),g):i},g.offset=function(e){return arguments.length?(f=e,g):f},g.order=function(e){return arguments.length?(l=e,g):l},g.style=function(e){if(!arguments.length)return a;a=e;switch(a){case"stack":g.offset("zero"),g.order("default");break;case"stream":g.offset("wiggle"),g.order("inside-out");break;case"stream-center":g.offset("silhouette"),g.order("inside-out");break;case"expand":g.offset("expand"),g.order("default")}return g},g.interpolate=function(e){return arguments.length?(c=e,c):c},g},e.models.stackedAreaChart=function(){function x(e){return e.each(function(f){var p=d3.select(this),T=this,N=(u||parseInt(p.style("width"))||960)-o.left-o.right,C=(a||parseInt(p.style("height"))||400)-o.top-o.bottom;x.update=function(){x(e)},x.container=this,g.disabled=f.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!f||!f.length||!f.f
ilter(function(e){return e.values.length}).length){var L=p.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",o.left+N/2).attr("y",o.top+C/2).text(function(e){return e}),x}p.selectAll(".nv-noData").remove(),d=t.xScale(),v=t.yScale();var A=p.selectAll("g.nv-wrap.nv-stackedAreaChart").data([f]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),M=A.select("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),c&&(i.width(N-E),M.select(".nv-legendWrap").datum(f).call(i),o.top!=i.height()&&(o.top=i.height(),C=(a||parseInt(p.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate("+E+","+ -o.top+")"));if(l){var _=[{key:"Stacked",disabled
:t.offset()!="zero"},{key:"Stream",disabled:t.offset()!="wiggle"},{key:"Expanded",disabled:t.offset()!="expand"}];s.width(E).color(["#444","#444","#444"]),M.select(".nv-controlsWrap").datum(_).call(s),o.top!=Math.max(s.height(),i.height())&&(o.top=Math.max(s.height(),i.height()),C=(a||parseInt(p.style("height"))||400)-o.top-o.bottom),M.select(".nv-controlsWrap").attr("transform","translate(0,"+ -o.top+")")}A.attr("transform","translate("+o.left+","+o.top+")"),t.width(N).height(C);var D=M.select(".nv-stackedWrap").datum(f);D.call(t),n.scale(d).ticks(N/100).tickSize(-C,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+C+")"),M.select(".nv-x.nv-axis").transition().duration(0).call(n),r.scale(v).ticks(t.offset()=="wiggle"?0:C/36).tickSize(-N,0).setTickFormat(t.offset()=="expand"?d3.format("%"):m),M.select(".nv-y.nv-axis").transition().duration(0).call(r),t.dispatch.on("areaClick.toggle",function(t){f.filter(function(e){return!e.disabled}).length===1?f=f.map(function(e
){return e.disabled=!1,e}):f=f.map(function(e,n){return e.disabled=n!=t.seriesIndex,e}),g.disabled=f.map(function(e){return!!e.disabled}),w.stateChange(g),x(e)}),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,f.filter(function(e){return!e.disabled}).length||f.map(function(e){return e.disabled=!1,e}),g.disabled=f.map(function(e){return!!e.disabled}),w.stateChange(g),x(e)}),s.dispatch.on("legendClick",function(n,r){if(!n.disabled)return;_=_.map(function(e){return e.disabled=!0,e}),n.disabled=!1;switch(n.key){case"Stacked":t.style("stack");break;case"Stream":t.style("stream");break;case"Expanded":t.style("expand")}g.style=t.style(),w.stateChange(g),x(e)}),w.on("tooltipShow",function(e){h&&S(e,T.parentNode)}),w.on("changeState",function(n){typeof n.disabled!="undefined"&&(f.forEach(function(e,t){e.disabled=n.disabled[t]}),g.disabled=n.disabled),typeof n.style!="undefined"&&t.style(n.style),e.call(x)})}),x}var t=e.models.stackedArea(),n=e.models.axis(),r=e.model
s.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:25,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},d,v,m=d3.format(",.2f"),g={style:t.style()},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=250;n.orient("bottom").tickPadding(7),r.orient("left"),t.scatter.pointActive(function(e){return!!Math.round(t.y()(e)*100)});var S=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=p(i.series.key,a,f,i,x);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("tooltipShow",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],w.tooltipShow(e)}),t.dispatch.on("tooltipHide",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){h&&e.tooltip.cleanup()}),x.dispatch=w,x.stacked=t,x.legend=i,x.c
ontrols=s,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"x","y","size","xScale","yScale","xDomain","yDomain","sizeDomain","interactive","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),x.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,x):o},x.width=function(e){return arguments.length?(u=e,x):getWidth},x.height=function(e){return arguments.length?(a=e,x):getHeight},x.color=function(n){return arguments.length?(f=e.utils.getColor(n),i.color(f),t.color(f),x):f},x.showControls=function(e){return arguments.length?(l=e,x):l},x.showLegend=function(e){return arguments.length?(c=e,x):c},x.tooltip=function(e){return arguments.length?(p=e,x):p},x.tooltips=function(e){return arguments.length?(h=e,x):h},x.tooltipContent=function(e){return arguments.length?(p=e,x):p},x.state=fu
nction(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments
+.length?(b=e,x):b},r.setTickFormat=r.tickFormat,r.tickFormat=function(e){return arguments.length?(m=e,r):m},x}})();
\ No newline at end of file
commit 5910881f73a934e84dd80572b40142154483e2eb
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 14:14:40 2013 -0700
Update the d3 javascript libraries to 3.1.10.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js
old mode 100644
new mode 100755
index 04cba44..94cb5d4
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js
@@ -1,17 +1,11 @@
d3 = function() {
- var Ï = Math.PI, ε = 1e-6, d3 = {
- version: "3.0.6"
- }, d3_radians = Ï / 180, d3_degrees = 180 / Ï, d3_document = document, d3_window = window;
- function d3_target(d) {
- return d.target;
- }
- function d3_source(d) {
- return d.source;
- }
- var d3_format_decimalPoint = ".", d3_format_thousandsSeparator = ",", d3_format_grouping = [ 3, 3 ];
+ var d3 = {
+ version: "3.1.10"
+ };
if (!Date.now) Date.now = function() {
return +new Date();
};
+ var d3_document = document, d3_window = window;
try {
d3_document.createElement("div").style.setProperty("opacity", 0, "");
} catch (error) {
@@ -20,133 +14,12 @@ d3 = function() {
d3_style_setProperty.call(this, name, value + "", priority);
};
}
- function d3_class(ctor, properties) {
- try {
- for (var key in properties) {
- Object.defineProperty(ctor.prototype, key, {
- value: properties[key],
- enumerable: false
- });
- }
- } catch (e) {
- ctor.prototype = properties;
- }
- }
- var d3_array = d3_arraySlice;
- function d3_arrayCopy(pseudoarray) {
- var i = -1, n = pseudoarray.length, array = [];
- while (++i < n) array.push(pseudoarray[i]);
- return array;
- }
- function d3_arraySlice(pseudoarray) {
- return Array.prototype.slice.call(pseudoarray);
- }
- try {
- d3_array(d3_document.documentElement.childNodes)[0].nodeType;
- } catch (e) {
- d3_array = d3_arrayCopy;
- }
- var d3_arraySubclass = [].__proto__ ? function(array, prototype) {
- array.__proto__ = prototype;
- } : function(array, prototype) {
- for (var property in prototype) array[property] = prototype[property];
- };
- d3.map = function(object) {
- var map = new d3_Map();
- for (var key in object) map.set(key, object[key]);
- return map;
- };
- function d3_Map() {}
- d3_class(d3_Map, {
- has: function(key) {
- return d3_map_prefix + key in this;
- },
- get: function(key) {
- return this[d3_map_prefix + key];
- },
- set: function(key, value) {
- return this[d3_map_prefix + key] = value;
- },
- remove: function(key) {
- key = d3_map_prefix + key;
- return key in this && delete this[key];
- },
- keys: function() {
- var keys = [];
- this.forEach(function(key) {
- keys.push(key);
- });
- return keys;
- },
- values: function() {
- var values = [];
- this.forEach(function(key, value) {
- values.push(value);
- });
- return values;
- },
- entries: function() {
- var entries = [];
- this.forEach(function(key, value) {
- entries.push({
- key: key,
- value: value
- });
- });
- return entries;
- },
- forEach: function(f) {
- for (var key in this) {
- if (key.charCodeAt(0) === d3_map_prefixCode) {
- f.call(this, key.substring(1), this[key]);
- }
- }
- }
- });
- var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
- function d3_identity(d) {
- return d;
- }
- function d3_true() {
- return true;
- }
- function d3_functor(v) {
- return typeof v === "function" ? v : function() {
- return v;
- };
- }
- d3.functor = d3_functor;
- 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 arguments.length ? target : value;
- };
- }
d3.ascending = function(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.mean = function(array, f) {
- var n = array.length, a, m = 0, i = -1, j = 0;
- if (arguments.length === 1) {
- while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
- } else {
- while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
- }
- return j ? m : undefined;
- };
- d3.median = function(array, f) {
- if (arguments.length > 1) array = array.map(f);
- array = array.filter(d3_number);
- return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
- };
d3.min = function(array, f) {
var i = -1, n = array.length, a, b;
if (arguments.length === 1) {
@@ -186,37 +59,6 @@ d3 = function() {
}
return [ a, c ];
};
- 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());
- };
- },
- irwinHall: function(m) {
- return function() {
- for (var s = 0, j = 0; j < m; j++) s += Math.random();
- return s / m;
- };
- }
- };
- function d3_number(x) {
- return x != null && !isNaN(x);
- }
d3.sum = function(array, f) {
var s = 0, n = array.length, a, i = -1;
if (arguments.length === 1) {
@@ -226,33 +68,27 @@ d3 = function() {
}
return s;
};
+ function d3_number(x) {
+ return x != null && !isNaN(x);
+ }
+ d3.mean = function(array, f) {
+ var n = array.length, a, m = 0, i = -1, j = 0;
+ if (arguments.length === 1) {
+ while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
+ } else {
+ while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
+ }
+ return j ? m : undefined;
+ };
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.shuffle = function(array) {
- var m = array.length, t, i;
- while (m) {
- i = Math.random() * m-- | 0;
- t = array[m], array[m] = array[i], array[i] = t;
- }
- return array;
- };
- d3.transpose = function(matrix) {
- return d3.zip.apply(d3, matrix);
- };
- 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;
+ d3.median = function(array, f) {
+ if (arguments.length > 1) array = array.map(f);
+ array = array.filter(d3_number);
+ return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
};
- function d3_zipLength(d) {
- return d.length;
- }
d3.bisector = function(f) {
return {
left: function(a, x, lo, hi) {
@@ -280,65 +116,38 @@ d3 = function() {
});
d3.bisectLeft = d3_bisector.left;
d3.bisect = d3.bisectRight = d3_bisector.right;
- d3.nest = function() {
- var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
- function map(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, valuesByKey = new d3_Map(), values, o = {};
- while (++i < n) {
- if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
- values.push(object);
- } else {
- valuesByKey.set(keyValue, [ object ]);
- }
- }
- valuesByKey.forEach(function(keyValue, values) {
- o[keyValue] = map(values, depth);
- });
- return o;
+ d3.shuffle = function(array) {
+ var m = array.length, t, i;
+ while (m) {
+ i = Math.random() * m-- | 0;
+ t = array[m], array[m] = array[i], array[i] = t;
}
- function entries(map, depth) {
- if (depth >= keys.length) return map;
- var a = [], sortKey = sortKeys[depth++], key;
- for (key in map) {
- a.push({
- key: key,
- values: entries(map[key], depth)
- });
+ return array;
+ };
+ d3.permute = function(array, indexes) {
+ var permutes = [], i = -1, n = indexes.length;
+ while (++i < n) permutes[i] = array[indexes[i]];
+ return permutes;
+ };
+ 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];
}
- if (sortKey) a.sort(function(a, b) {
- return sortKey(a.key, b.key);
- });
- return a;
}
- nest.map = function(array) {
- return map(array, 0);
- };
- nest.entries = function(array) {
- return entries(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;
+ return zips;
};
- d3.keys = function(map) {
- var keys = [];
- for (var key in map) keys.push(key);
- return keys;
+ 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 = [];
@@ -353,17 +162,9 @@ d3 = function() {
});
return entries;
};
- d3.permute = function(array, indexes) {
- var permutes = [], i = -1, n = indexes.length;
- while (++i < n) permutes[i] = array[indexes[i]];
- return permutes;
- };
d3.merge = function(arrays) {
return Array.prototype.concat.apply([], arrays);
};
- function d3_collapse(s) {
- return s.trim().replace(/\s+/g, " ");
- }
d3.range = function(start, stop, step) {
if (arguments.length < 3) {
step = 1;
@@ -383,124 +184,179 @@ d3 = function() {
while (x * k % 1) k *= 10;
return k;
}
- d3.requote = function(s) {
- return s.replace(d3_requote_re, "\\$&");
- };
- var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
- d3.round = function(x, n) {
- return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
+ function d3_class(ctor, properties) {
+ try {
+ for (var key in properties) {
+ Object.defineProperty(ctor.prototype, key, {
+ value: properties[key],
+ enumerable: false
+ });
+ }
+ } catch (e) {
+ ctor.prototype = properties;
+ }
+ }
+ d3.map = function(object) {
+ var map = new d3_Map();
+ for (var key in object) map.set(key, object[key]);
+ return map;
};
- d3.xhr = function(url, mimeType, callback) {
- var xhr = {}, dispatch = d3.dispatch("progress", "load", "error"), headers = {}, response = d3_identity, request = new (d3_window.XDomainRequest && /^(http(s)?:)?\/\//.test(url) ? XDomainRequest : XMLHttpRequest)();
- "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
- request.readyState > 3 && respond();
- };
- function respond() {
- var s = request.status;
- !s && request.responseText || s >= 200 && s < 300 || s === 304 ? dispatch.load.call(xhr, response.call(xhr, request)) : dispatch.error.call(xhr, request);
+ function d3_Map() {}
+ d3_class(d3_Map, {
+ has: function(key) {
+ return d3_map_prefix + key in this;
+ },
+ get: function(key) {
+ return this[d3_map_prefix + key];
+ },
+ set: function(key, value) {
+ return this[d3_map_prefix + key] = value;
+ },
+ remove: function(key) {
+ key = d3_map_prefix + key;
+ return key in this && delete this[key];
+ },
+ keys: function() {
+ var keys = [];
+ this.forEach(function(key) {
+ keys.push(key);
+ });
+ return keys;
+ },
+ values: function() {
+ var values = [];
+ this.forEach(function(key, value) {
+ values.push(value);
+ });
+ return values;
+ },
+ entries: function() {
+ var entries = [];
+ this.forEach(function(key, value) {
+ entries.push({
+ key: key,
+ value: value
+ });
+ });
+ return entries;
+ },
+ forEach: function(f) {
+ for (var key in this) {
+ if (key.charCodeAt(0) === d3_map_prefixCode) {
+ f.call(this, key.substring(1), this[key]);
+ }
+ }
}
- request.onprogress = function(event) {
- var o = d3.event;
- d3.event = event;
- try {
- dispatch.progress.call(xhr, request);
- } finally {
- d3.event = o;
+ });
+ var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
+ 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);
};
- 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;
+ nest.entries = function(array) {
+ return entries(map(d3.map, array, 0), 0);
};
- xhr.mimeType = function(value) {
- if (!arguments.length) return mimeType;
- mimeType = value == null ? null : value + "";
- return xhr;
+ nest.key = function(d) {
+ keys.push(d);
+ return nest;
};
- xhr.response = function(value) {
- response = value;
- return xhr;
+ nest.sortKeys = function(order) {
+ sortKeys[keys.length - 1] = order;
+ return nest;
};
- [ "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 (callback != null) xhr.on("error", callback).on("load", function(request) {
- callback(null, request);
- });
- request.send(data == null ? null : data);
- return xhr;
+ nest.sortValues = function(order) {
+ sortValues = order;
+ return nest;
};
- xhr.abort = function() {
- request.abort();
- return xhr;
+ nest.rollup = function(f) {
+ rollup = f;
+ return nest;
};
- d3.rebind(xhr, dispatch, "on");
- if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType,
- mimeType = null;
- 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;
- }
- d3.text = function() {
- return d3.xhr.apply(d3, arguments).response(d3_text);
- };
- function d3_text(request) {
- return request.responseText;
- }
- d3.json = function(url, callback) {
- return d3.xhr(url, "application/json", callback).response(d3_json);
- };
- function d3_json(request) {
- return JSON.parse(request.responseText);
- }
- d3.html = function(url, callback) {
- return d3.xhr(url, "text/html", callback).response(d3_html);
- };
- function d3_html(request) {
- var range = d3_document.createRange();
- range.selectNode(d3_document.body);
- return range.createContextualFragment(request.responseText);
- }
- d3.xml = function() {
- return d3.xhr.apply(d3, arguments).response(d3_xml);
+ return nest;
};
- function d3_xml(request) {
- return request.responseXML;
- }
- 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.set = function(array) {
+ var set = new d3_Set();
+ if (array) for (var i = 0; i < array.length; i++) set.add(array[i]);
+ return set;
};
- d3.ns = {
- prefix: d3_nsPrefix,
- qualify: function(name) {
- var i = name.indexOf(":"), prefix = name;
- if (i >= 0) {
- prefix = name.substring(0, i);
- name = name.substring(i + 1);
+ function d3_Set() {}
+ d3_class(d3_Set, {
+ has: function(value) {
+ return d3_map_prefix + value in this;
+ },
+ add: function(value) {
+ this[d3_map_prefix + value] = true;
+ return value;
+ },
+ remove: function(value) {
+ value = d3_map_prefix + value;
+ return value in this && delete this[value];
+ },
+ values: function() {
+ var values = [];
+ this.forEach(function(value) {
+ values.push(value);
+ });
+ return values;
+ },
+ forEach: function(f) {
+ for (var value in this) {
+ if (value.charCodeAt(0) === d3_map_prefixCode) {
+ f.call(this, value.substring(1));
+ }
}
- return d3_nsPrefix.hasOwnProperty(prefix) ? {
- space: d3_nsPrefix[prefix],
- local: name
- } : name;
}
+ });
+ 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;
+ };
+ }
d3.dispatch = function() {
var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
@@ -509,11 +365,17 @@ d3 = function() {
function d3_dispatch() {}
d3_dispatch.prototype.on = function(type, listener) {
var i = type.indexOf("."), name = "";
- if (i > 0) {
+ if (i >= 0) {
name = type.substring(i + 1);
type = type.substring(0, i);
}
- return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
+ 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();
@@ -537,251 +399,25 @@ d3 = function() {
};
return event;
}
- d3.format = function(specifier) {
- var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", basePrefix = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false;
- if (precision) precision = +precision.substring(1);
- if (zfill || fill === "0" && align === "=") {
- zfill = fill = "0";
- align = "=";
- if (comma) width -= Math.floor((width - 1) / 4);
+ d3.event = null;
+ function d3_eventCancel() {
+ d3.event.stopPropagation();
+ d3.event.preventDefault();
+ }
+ function d3_eventSource() {
+ var e = d3.event, s;
+ while (s = e.sourceEvent) e = s;
+ return e;
+ }
+ function d3_eventSuppress(target, type) {
+ function off() {
+ target.on(type, null);
}
- 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 (basePrefix) basePrefix = "0" + type.toLowerCase();
-
- case "c":
- case "d":
- integer = true;
- precision = 0;
- break;
-
- case "s":
- scale = -1;
- type = "r";
- break;
- }
- if (basePrefix === "#") basePrefix = "";
- if (type == "r" && !precision) type = "g";
- type = d3_format_types.get(type) || d3_format_typeDefault;
- var zcomma = zfill && comma;
- return function(value) {
- if (integer && value % 1) return "";
- var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign;
- if (scale < 0) {
- var prefix = d3.formatPrefix(value, precision);
- value = prefix.scale(value);
- suffix = prefix.symbol;
- } else {
- value *= scale;
- }
- value = type(value, precision);
- if (!zfill && comma) value = d3_format_group(value);
- var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
- if (zcomma) value = d3_format_group(padding + value);
- if (d3_format_decimalPoint) value.replace(".", d3_format_decimalPoint);
- negative += basePrefix;
- 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)) + suffix;
- };
- };
- var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/;
- 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_precision(x, p) {
- return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
- }
- function d3_format_typeDefault(x) {
- return x + "";
- }
- var d3_format_group = d3_identity;
- if (d3_format_grouping) {
- var d3_format_groupingLength = d3_format_grouping.length;
- d3_format_group = function(value) {
- var i = value.lastIndexOf("."), f = i >= 0 ? "." + value.substring(i + 1) : (i = value.length,
- ""), t = [], j = 0, g = d3_format_grouping[0];
- while (i > 0 && g > 0) {
- t.push(value.substring(i -= g, i + g));
- g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength];
- }
- return t.reverse().join(d3_format_thousandsSeparator || "") + f;
- };
- }
- 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 <= 0 ? i + 1 : i - 1) / 3) * 3));
- }
- return d3_formatPrefixes[8 + i / 3];
- };
- function d3_formatPrefix(d, i) {
- var k = Math.pow(10, Math.abs(8 - i) * 3);
- return {
- scale: i > 8 ? function(d) {
- return d / k;
- } : function(d) {
- return d * k;
- },
- symbol: d
- };
- }
- 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.substring(0, i) : name, m = i >= 0 ? name.substring(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, Array.prototype.slice.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 * Ï / 2);
- }
- 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 / (2 * Ï) * 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) * 2 * Ï / 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.event = null;
- function d3_eventCancel() {
- d3.event.stopPropagation();
- d3.event.preventDefault();
- }
- function d3_eventSource() {
- var e = d3.event, s;
- while (s = e.sourceEvent) e = s;
- return e;
+ target.on(type, function() {
+ d3_eventCancel();
+ off();
+ }, true);
+ setTimeout(off, 0);
}
function d3_eventDispatch(target) {
var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
@@ -800,368 +436,1032 @@ d3 = function() {
};
return dispatch;
}
- d3.transform = function(string) {
- var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
- return (d3.transform = function(string) {
- 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 + ")";
+ d3.mouse = function(container) {
+ return d3_mousePoint(container, d3_eventSource());
};
- 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;
+ var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;
+ function d3_mousePoint(container, e) {
+ 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(d3_document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0);
+ 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 ];
}
- return k;
+ var rect = container.getBoundingClientRect();
+ return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
}
- function d3_transformCombine(a, b, k) {
- a[0] += k * b[0];
- a[1] += k * b[1];
- return a;
+ var d3_array = d3_arraySlice;
+ function d3_arrayCopy(pseudoarray) {
+ var i = -1, n = pseudoarray.length, array = [];
+ while (++i < n) array.push(pseudoarray[i]);
+ return array;
}
- var d3_transformIdentity = {
- a: 1,
- b: 0,
- c: 0,
- d: 1,
- e: 0,
- f: 0
+ function d3_arraySlice(pseudoarray) {
+ return Array.prototype.slice.call(pseudoarray);
+ }
+ try {
+ d3_array(d3_document.documentElement.childNodes)[0].nodeType;
+ } catch (e) {
+ d3_array = d3_arrayCopy;
+ }
+ var d3_arraySubclass = [].__proto__ ? function(array, prototype) {
+ array.__proto__ = prototype;
+ } : function(array, prototype) {
+ for (var property in prototype) array[property] = prototype[property];
};
- d3.interpolate = function(a, b) {
- var i = d3.interpolators.length, f;
- while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
- return f;
+ 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;
+ }) : [];
};
- d3.interpolateNumber = function(a, b) {
- b -= a;
- return function(t) {
- return a + b * t;
+ d3.behavior.drag = function() {
+ var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null;
+ function drag() {
+ this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown);
+ }
+ function mousedown() {
+ var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0;
+ var w = d3.select(d3_window).on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
+ if (origin) {
+ offset = origin.apply(target, arguments);
+ offset = [ offset.x - origin_[0], offset.y - origin_[1] ];
+ } else {
+ offset = [ 0, 0 ];
+ }
+ if (touchId == null) d3_eventCancel();
+ event_({
+ type: "dragstart"
+ });
+ function point() {
+ var p = target.parentNode;
+ return touchId != null ? d3.touches(p).filter(function(p) {
+ return p.identifier === touchId;
+ })[0] : d3.mouse(p);
+ }
+ function dragmove() {
+ if (!target.parentNode) return dragend();
+ var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1];
+ moved |= dx | dy;
+ origin_ = p;
+ d3_eventCancel();
+ event_({
+ type: "drag",
+ x: p[0] + offset[0],
+ y: p[1] + offset[1],
+ dx: dx,
+ dy: dy
+ });
+ }
+ function dragend() {
+ event_({
+ type: "dragend"
+ });
+ if (moved) {
+ d3_eventCancel();
+ if (d3.event.target === eventTarget) d3_eventSuppress(w, "click");
+ }
+ w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null);
+ }
+ }
+ drag.origin = function(x) {
+ if (!arguments.length) return origin;
+ origin = x;
+ return drag;
};
+ return d3.rebind(drag, event, "on");
};
- d3.interpolateRound = function(a, b) {
- b -= a;
- return function(t) {
- return Math.round(a + b * t);
+ function d3_selection(groups) {
+ d3_arraySubclass(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_selectRoot = d3_document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, 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 = function(s, n) {
+ return Sizzle.uniqueSort(Sizzle(s, n));
};
+ d3_selectMatches = Sizzle.matchesSelector;
+ }
+ d3.selection = function() {
+ return d3_selectionRoot;
};
- d3.interpolateString = function(a, b) {
- var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
- d3_interpolate_number.lastIndex = 0;
- for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
- if (m.index) s.push(b.substring(s0, s1 = m.index));
- q.push({
- i: s.length,
- x: m[0]
- });
- s.push(null);
- s0 = d3_interpolate_number.lastIndex;
- }
- if (s0 < b.length) s.push(b.substring(s0));
- for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
- o = q[i];
- if (o.x == m[0]) {
- if (o.i) {
- if (s[o.i + 1] == null) {
- s[o.i - 1] += o.x;
- s.splice(o.i, 1);
- for (j = i + 1; j < n; ++j) q[j].i--;
- } else {
- s[o.i - 1] += o.x + s[o.i + 1];
- s.splice(o.i, 2);
- for (j = i + 1; j < n; ++j) q[j].i -= 2;
- }
+ var d3_selectionPrototype = d3.selection.prototype = [];
+ d3_selectionPrototype.select = function(selector) {
+ var subgroups = [], subgroup, subnode, group, node;
+ if (typeof selector !== "function") 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));
+ if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
} else {
- if (s[o.i + 1] == null) {
- s[o.i] = o.x;
- } else {
- s[o.i] = o.x + s[o.i + 1];
- s.splice(o.i + 1, 1);
- for (j = i + 1; j < n; ++j) q[j].i--;
- }
+ subgroup.push(null);
}
- q.splice(i, 1);
- n--;
- i--;
- } else {
- o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
}
}
- while (i < n) {
- o = q.pop();
- if (s[o.i + 1] == null) {
- s[o.i] = o.x;
- } else {
- s[o.i] = o.x + s[o.i + 1];
- s.splice(o.i + 1, 1);
+ return d3_selection(subgroups);
+ };
+ function d3_selection_selector(selector) {
+ return function() {
+ return d3_select(selector, this);
+ };
+ }
+ d3_selectionPrototype.selectAll = function(selector) {
+ var subgroups = [], subgroup, node;
+ if (typeof selector !== "function") 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)));
+ subgroup.parentNode = node;
+ }
}
- n--;
- }
- if (s.length === 1) {
- return s[0] == null ? q[0].x : function() {
- return b;
- };
}
- return function(t) {
- for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
- return s.join("");
+ return d3_selection(subgroups);
+ };
+ function d3_selection_selectorAll(selector) {
+ return 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.interpolateTransform = function(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("");
- };
- };
- d3.interpolateRgb = function(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.interpolateHsl = function(a, b) {
- a = d3.hsl(a);
- b = d3.hsl(b);
- var h0 = a.h, s0 = a.s, l0 = a.l, h1 = b.h - h0, s1 = b.s - s0, l1 = b.l - l0;
- if (h1 > 180) h1 -= 360; else if (h1 < -180) h1 += 360;
- return function(t) {
- return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t) + "";
- };
- };
- d3.interpolateLab = function(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.interpolateHcl = function(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 (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.interpolateArray = function(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;
- };
- };
- d3.interpolateObject = function(a, b) {
- var i = {}, c = {}, k;
- for (k in a) {
- if (k in b) {
- i[k] = d3_interpolateByName(k)(a[k], b[k]);
- } else {
- c[k] = a[k];
+ d3.ns = {
+ prefix: d3_nsPrefix,
+ qualify: function(name) {
+ var i = name.indexOf(":"), prefix = name;
+ if (i >= 0) {
+ prefix = name.substring(0, i);
+ name = name.substring(i + 1);
}
+ return d3_nsPrefix.hasOwnProperty(prefix) ? {
+ space: d3_nsPrefix[prefix],
+ local: name
+ } : name;
}
- for (k in b) {
- if (!(k in a)) {
- c[k] = b[k];
+ };
+ 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 function(t) {
- for (k in i) c[k] = i[k](t);
- return c;
- };
- };
- var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
- function d3_interpolateByName(name) {
- return name == "transform" ? d3.interpolateTransform : d3.interpolate;
- }
- d3.interpolators = [ d3.interpolateObject, function(a, b) {
- return b instanceof Array && d3.interpolateArray(a, b);
- }, function(a, b) {
- return (typeof a === "string" || typeof b === "string") && d3.interpolateString(a + "", b + "");
- }, function(a, b) {
- return (typeof b === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Color) && d3.interpolateRgb(a, b);
- }, function(a, b) {
- return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b);
- } ];
- function d3_uninterpolateNumber(a, b) {
- b = b - (a = +a) ? 1 / (b - a) : 0;
- return function(x) {
- return (x - a) * b;
- };
- }
- function d3_uninterpolateClamp(a, b) {
- b = b - (a = +a) ? 1 / (b - a) : 0;
- return function(x) {
- return Math.max(0, Math.min(1, (x - a) * b));
- };
- }
- function d3_Color() {}
- d3_Color.prototype.toString = function() {
- return this.rgb() + "";
- };
- d3.rgb = function(r, g, b) {
- return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
+ return this.each(d3_selection_attr(name, value));
};
- function d3_rgb(r, g, b) {
- return new d3_Rgb(r, g, b);
+ 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_Rgb(r, g, b) {
- this.r = r;
- this.g = g;
- this.b = b;
+ function d3_collapse(s) {
+ return s.trim().replace(/\s+/g, " ");
}
- 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 d3_rgb(i, i, i);
- if (r && r < i) r = i;
- if (g && g < i) g = i;
- if (b && b < i) b = i;
- return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k)));
- };
- d3_rgbPrototype.darker = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(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);
+ d3.requote = function(s) {
+ return s.replace(d3_requote_re, "\\$&");
};
- 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, name;
- 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]));
+ var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+ d3_selectionPrototype.classed = function(name, value) {
+ if (arguments.length < 2) {
+ if (typeof name === "string") {
+ var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).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;
}
- if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);
- if (format != null && format.charAt(0) === "#") {
- if (format.length === 4) {
- r = format.charAt(1);
- r += r;
- g = format.charAt(2);
- g += g;
- b = format.charAt(3);
- b += b;
- } else if (format.length === 7) {
- r = format.substring(1, 3);
- g = format.substring(3, 5);
- b = format.substring(5, 7);
- }
- r = parseInt(r, 16);
- g = parseInt(g, 16);
- b = parseInt(b, 16);
- }
- return rgb(r, g, b);
+ return this.each(d3_selection_classed(name, value));
+ };
+ function d3_selection_classedRe(name) {
+ return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
}
- 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 {
- s = h = 0;
+ function d3_selection_classed(name, value) {
+ name = name.trim().split(/\s+/).map(d3_selection_classedName);
+ var n = name.length;
+ function classedConstant() {
+ var i = -1;
+ while (++i < n) name[i](this, value);
}
- return 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 classedFunction() {
+ var i = -1, x = value.apply(this, arguments);
+ while (++i < n) name[i](this, x);
+ }
+ return typeof value === "function" ? classedFunction : classedConstant;
}
- function d3_rgb_xyz(r) {
- return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
+ 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.ns.qualify(name);
+ function append() {
+ return this.appendChild(d3_document.createElementNS(this.namespaceURI, name));
+ }
+ function appendNS() {
+ return this.appendChild(d3_document.createElementNS(name.space, name.local));
+ }
+ return this.select(name.local ? appendNS : append);
+ };
+ d3_selectionPrototype.insert = function(name, before) {
+ name = d3.ns.qualify(name);
+ if (typeof before !== "function") before = d3_selection_selector(before);
+ function insert(d, i) {
+ return this.insertBefore(d3_document.createElementNS(this.namespaceURI, name), before.call(this, d, i));
+ }
+ function insertNS(d, i) {
+ return this.insertBefore(d3_document.createElementNS(name.space, name.local), before.call(this, d, i));
+ }
+ return this.select(name.local ? insertNS : insert);
+ };
+ d3_selectionPrototype.remove = function() {
+ return this.each(function() {
+ 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(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;
+ for (i = -1; ++i < n; ) {
+ keyValue = key.call(node = group[i], node.__data__, i);
+ if (nodeByKeyValue.has(keyValue)) {
+ exitNodes[i] = node;
+ } else {
+ nodeByKeyValue.set(keyValue, node);
+ }
+ keyValues.push(keyValue);
+ }
+ for (i = -1; ++i < m; ) {
+ keyValue = key.call(groupData, nodeData = groupData[i], i);
+ if (node = nodeByKeyValue.get(keyValue)) {
+ updateNodes[i] = node;
+ node.__data__ = nodeData;
+ } else if (!dataByKeyValue.has(keyValue)) {
+ enterNodes[i] = d3_selection_dataNode(nodeData);
+ }
+ dataByKeyValue.set(keyValue, nodeData);
+ nodeByKeyValue.remove(keyValue);
+ }
+ for (i = -1; ++i < n; ) {
+ if (nodeByKeyValue.has(keyValues[i])) {
+ 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)) {
+ 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__);
+ };
+ }
+ function d3_noop() {}
+ 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.substring(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);
+ }
+ };
+ }
+ 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;
+ };
+ function d3_selection_enter(selection) {
+ d3_arraySubclass(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.insert = d3_selectionPrototype.insert;
+ d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
+ d3_selection_enterPrototype.node = d3_selectionPrototype.node;
+ 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));
+ subnode.__data__ = node.__data__;
+ } else {
+ subgroup.push(null);
+ }
+ }
+ }
+ return d3_selection(subgroups);
+ };
+ d3_selectionPrototype.transition = function() {
+ var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit);
+ transition.time = Date.now();
+ 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, id, transition);
+ subgroup.push(node);
+ }
+ }
+ return d3_transition(subgroups, id);
+ };
+ d3.select = function(node) {
+ var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ];
+ group.parentNode = d3_selectRoot;
+ return d3_selection([ group ]);
+ };
+ d3.selectAll = function(nodes) {
+ var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes);
+ group.parentNode = d3_selectRoot;
+ return d3_selection([ group ]);
+ };
+ var d3_selectionRoot = d3.select(d3_selectRoot);
+ d3.behavior.zoom = function() {
+ var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime;
+ function zoom() {
+ this.on("mousedown.zoom", mousedown).on("mousemove.zoom", mousemove).on(d3_behavior_zoomWheel + ".zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart);
+ }
+ zoom.translate = function(x) {
+ if (!arguments.length) return translate;
+ translate = x.map(Number);
+ rescale();
+ return zoom;
+ };
+ zoom.scale = function(x) {
+ if (!arguments.length) return scale;
+ scale = +x;
+ rescale();
+ return zoom;
+ };
+ zoom.scaleExtent = function(x) {
+ if (!arguments.length) return scaleExtent;
+ scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);
+ return zoom;
+ };
+ zoom.x = function(z) {
+ if (!arguments.length) return x1;
+ x1 = z;
+ x0 = z.copy();
+ translate = [ 0, 0 ];
+ scale = 1;
+ return zoom;
+ };
+ zoom.y = function(z) {
+ if (!arguments.length) return y1;
+ y1 = z;
+ y0 = z.copy();
+ translate = [ 0, 0 ];
+ scale = 1;
+ return zoom;
+ };
+ function location(p) {
+ return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ];
+ }
+ function point(l) {
+ return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ];
+ }
+ function scaleTo(s) {
+ scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+ }
+ function translateTo(p, l) {
+ l = point(l);
+ translate[0] += p[0] - l[0];
+ translate[1] += p[1] - l[1];
+ }
+ function rescale() {
+ if (x1) x1.domain(x0.range().map(function(x) {
+ return (x - translate[0]) / scale;
+ }).map(x0.invert));
+ if (y1) y1.domain(y0.range().map(function(y) {
+ return (y - translate[1]) / scale;
+ }).map(y0.invert));
+ }
+ function dispatch(event) {
+ rescale();
+ d3.event.preventDefault();
+ event({
+ type: "zoom",
+ scale: scale,
+ translate: translate
+ });
+ }
+ function mousedown() {
+ var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(d3_window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target));
+ d3_window.focus();
+ d3_eventCancel();
+ function mousemove() {
+ moved = 1;
+ translateTo(d3.mouse(target), l);
+ dispatch(event_);
+ }
+ function mouseup() {
+ if (moved) d3_eventCancel();
+ w.on("mousemove.zoom", null).on("mouseup.zoom", null);
+ if (moved && d3.event.target === eventTarget) d3_eventSuppress(w, "click.zoom");
+ }
+ }
+ function mousewheel() {
+ if (!translate0) translate0 = location(d3.mouse(this));
+ scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);
+ translateTo(d3.mouse(this), translate0);
+ dispatch(event.of(this, arguments));
+ }
+ function mousemove() {
+ translate0 = null;
+ }
+ function dblclick() {
+ var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2;
+ scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
+ translateTo(p, l);
+ dispatch(event.of(this, arguments));
+ }
+ function touchstart() {
+ var touches = d3.touches(this), now = Date.now();
+ scale0 = scale;
+ translate0 = {};
+ touches.forEach(function(t) {
+ translate0[t.identifier] = location(t);
+ });
+ d3_eventCancel();
+ if (touches.length === 1) {
+ if (now - touchtime < 500) {
+ var p = touches[0], l = location(touches[0]);
+ scaleTo(scale * 2);
+ translateTo(p, l);
+ dispatch(event.of(this, arguments));
+ }
+ touchtime = now;
+ }
+ }
+ function touchmove() {
+ var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier];
+ if (p1 = touches[1]) {
+ var p1, l1 = translate0[p1.identifier];
+ p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
+ l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
+ scaleTo(d3.event.scale * scale0);
+ }
+ translateTo(p0, l0);
+ touchtime = null;
+ dispatch(event.of(this, arguments));
+ }
+ 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");
+ function d3_Color() {}
+ d3_Color.prototype.toString = function() {
+ return this.rgb() + "";
+ };
+ d3.hsl = function(h, s, l) {
+ return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
+ };
+ function d3_hsl(h, s, l) {
+ return new d3_Hsl(h, s, l);
+ }
+ function d3_Hsl(h, s, l) {
+ this.h = h;
+ this.s = s;
+ this.l = l;
+ }
+ var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();
+ d3_hslPrototype.brighter = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return d3_hsl(this.h, this.s, this.l / k);
+ };
+ d3_hslPrototype.darker = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return 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 d3_rgb(vv(h + 120), vv(h), vv(h - 120));
+ }
+ var Ï = Math.PI, ε = 1e-6, d3_radians = Ï / 180, d3_degrees = 180 / Ï;
+ function d3_sgn(x) {
+ return x > 0 ? 1 : x < 0 ? -1 : 0;
+ }
+ function d3_acos(x) {
+ return Math.acos(Math.max(-1, Math.min(1, x)));
+ }
+ function d3_asin(x) {
+ return x > 1 ? Ï / 2 : x < -1 ? -Ï / 2 : Math.asin(x);
+ }
+ function d3_sinh(x) {
+ return (Math.exp(x) - Math.exp(-x)) / 2;
+ }
+ function d3_cosh(x) {
+ return (Math.exp(x) + Math.exp(-x)) / 2;
+ }
+ function d3_haversin(x) {
+ return (x = Math.sin(x / 2)) * x;
+ }
+ d3.hcl = function(h, c, l) {
+ return arguments.length === 1 ? h instanceof d3_Hcl ? 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) : d3_hcl(+h, +c, +l);
+ };
+ function d3_hcl(h, c, l) {
+ return new d3_Hcl(h, c, l);
+ }
+ function d3_Hcl(h, c, l) {
+ this.h = h;
+ this.c = c;
+ this.l = l;
+ }
+ var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();
+ d3_hclPrototype.brighter = function(k) {
+ return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
+ };
+ d3_hclPrototype.darker = function(k) {
+ return 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 d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
+ }
+ d3.lab = function(l, a, b) {
+ return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
+ };
+ function d3_lab(l, a, b) {
+ return new d3_Lab(l, a, b);
+ }
+ function d3_Lab(l, a, b) {
+ this.l = l;
+ this.a = a;
+ this.b = 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 d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+ };
+ d3_labPrototype.darker = function(k) {
+ return 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 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 ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : 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 = function(r, g, b) {
+ return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
+ };
+ function d3_rgb(r, g, b) {
+ return new d3_Rgb(r, g, b);
+ }
+ function d3_Rgb(r, g, b) {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ }
+ 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 d3_rgb(i, i, i);
+ if (r && r < i) r = i;
+ if (g && g < i) g = i;
+ if (b && b < i) b = i;
+ return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k)));
+ };
+ d3_rgbPrototype.darker = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(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, name;
+ 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 (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);
+ if (format != null && format.charAt(0) === "#") {
+ if (format.length === 4) {
+ r = format.charAt(1);
+ r += r;
+ g = format.charAt(2);
+ g += g;
+ b = format.charAt(3);
+ b += b;
+ } else if (format.length === 7) {
+ r = format.substring(1, 3);
+ g = format.substring(3, 5);
+ b = format.substring(5, 7);
+ }
+ r = parseInt(r, 16);
+ g = parseInt(g, 16);
+ b = parseInt(b, 16);
+ }
+ 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 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);
@@ -1319,2595 +1619,3537 @@ d3 = function() {
d3_rgb_names.forEach(function(key, value) {
d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb));
});
- d3.hsl = function(h, s, l) {
- return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
- };
- function d3_hsl(h, s, l) {
- return new d3_Hsl(h, s, l);
- }
- function d3_Hsl(h, s, l) {
- this.h = h;
- this.s = s;
- this.l = l;
- }
- var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();
- d3_hslPrototype.brighter = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return d3_hsl(this.h, this.s, this.l / k);
- };
- d3_hslPrototype.darker = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return 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 = h % 360;
- if (h < 0) h += 360;
- s = 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 d3_rgb(vv(h + 120), vv(h), vv(h - 120));
- }
- d3.hcl = function(h, c, l) {
- return arguments.length === 1 ? h instanceof d3_Hcl ? 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) : d3_hcl(+h, +c, +l);
- };
- function d3_hcl(h, c, l) {
- return new d3_Hcl(h, c, l);
- }
- function d3_Hcl(h, c, l) {
- this.h = h;
- this.c = c;
- this.l = l;
- }
- var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();
- d3_hclPrototype.brighter = function(k) {
- return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
- };
- d3_hclPrototype.darker = function(k) {
- return 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) {
- return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
- }
- d3.lab = function(l, a, b) {
- return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
- };
- function d3_lab(l, a, b) {
- return new d3_Lab(l, a, b);
- }
- function d3_Lab(l, a, b) {
- this.l = l;
- this.a = a;
- this.b = 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 d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
- };
- d3_labPrototype.darker = function(k) {
- return 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 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 d3_hcl(Math.atan2(b, a) / Ï * 180, Math.sqrt(a * a + b * b), 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));
- }
- function d3_selection(groups) {
- d3_arraySubclass(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_selectRoot = d3_document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, 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 = function(s, n) {
- return Sizzle.uniqueSort(Sizzle(s, n));
- };
- d3_selectMatches = Sizzle.matchesSelector;
- }
- var d3_selectionPrototype = [];
- d3.selection = function() {
- return d3_selectionRoot;
- };
- d3.selection.prototype = d3_selectionPrototype;
- d3_selectionPrototype.select = function(selector) {
- var subgroups = [], subgroup, subnode, group, node;
- if (typeof selector !== "function") 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));
- if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
- } else {
- subgroup.push(null);
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_selection_selector(selector) {
- return function() {
- return d3_select(selector, this);
- };
- }
- d3_selectionPrototype.selectAll = function(selector) {
- var subgroups = [], subgroup, node;
- if (typeof selector !== "function") 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)));
- subgroup.parentNode = node;
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_selection_selectorAll(selector) {
- return function() {
- return d3_selectAll(selector, this);
- };
- }
- 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;
- }
- d3_selectionPrototype.classed = function(name, value) {
- if (arguments.length < 2) {
- if (typeof name === "string") {
- var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1;
- if (value = node.classList) {
- while (++i < n) if (!value.contains(name[i])) return false;
- } else {
- value = node.className;
- if (value.baseVal != null) value = value.baseVal;
- 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_functor(v) {
+ return typeof v === "function" ? v : function() {
+ return v;
+ };
}
- function d3_selection_classed(name, value) {
- name = name.trim().split(/\s+/).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;
+ d3.functor = d3_functor;
+ function d3_identity(d) {
+ return d;
}
- 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.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c;
- if (value) {
- re.lastIndex = 0;
- if (!re.test(cv)) {
- cv = d3_collapse(cv + " " + name);
- if (cb) c.baseVal = cv; else node.className = cv;
- }
- } else if (cv) {
- cv = d3_collapse(cv.replace(re, " "));
- if (cb) c.baseVal = cv; else node.className = cv;
- }
+ 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);
};
}
- 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;
+ function d3_xhr(url, mimeType, response, callback) {
+ var xhr = {}, dispatch = d3.dispatch("progress", "load", "error"), headers = {}, request = new (d3_window.XDomainRequest && /^(http(s)?:)?\/\//.test(url) ? XDomainRequest : XMLHttpRequest)();
+ "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
+ request.readyState > 3 && respond();
+ };
+ function respond() {
+ var status = request.status, result;
+ if (!status && request.responseText || 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);
}
- 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;
+ 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.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 (callback != null) xhr.on("error", callback).on("load", function(request) {
+ callback(null, 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));
}
- 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;
+ function d3_xhr_fixCallback(callback) {
+ return callback.length === 1 ? function(error, request) {
+ callback(error == null ? request : null);
+ } : callback;
}
- 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.ns.qualify(name);
- function append() {
- return this.appendChild(d3_document.createElementNS(this.namespaceURI, name));
- }
- function appendNS() {
- return this.appendChild(d3_document.createElementNS(name.space, name.local));
- }
- return this.select(name.local ? appendNS : append);
- };
- d3_selectionPrototype.insert = function(name, before) {
- name = d3.ns.qualify(name);
- function insert() {
- return this.insertBefore(d3_document.createElementNS(this.namespaceURI, name), d3_select(before, this));
+ function d3_dsv(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, callback);
+ xhr.row = function(_) {
+ return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
+ };
+ return xhr.row(row);
}
- function insertNS() {
- return this.insertBefore(d3_document.createElementNS(name.space, name.local), d3_select(before, this));
+ function response(request) {
+ return dsv.parse(request.responseText);
}
- return this.select(name.local ? insertNS : insert);
- };
- d3_selectionPrototype.remove = function() {
- return this.each(function() {
- 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 typedResponse(f) {
+ return function(request) {
+ return dsv.parse(request.responseText, f);
+ };
}
- 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(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;
- for (i = -1; ++i < n; ) {
- keyValue = key.call(node = group[i], node.__data__, i);
- if (nodeByKeyValue.has(keyValue)) {
- exitNodes[i] = node;
- } else {
- nodeByKeyValue.set(keyValue, node);
- }
- keyValues.push(keyValue);
- }
- for (i = -1; ++i < m; ) {
- keyValue = key.call(groupData, nodeData = groupData[i], i);
- if (node = nodeByKeyValue.get(keyValue)) {
- updateNodes[i] = node;
- node.__data__ = nodeData;
- } else if (!dataByKeyValue.has(keyValue)) {
- enterNodes[i] = d3_selection_dataNode(nodeData);
- }
- dataByKeyValue.set(keyValue, nodeData);
- nodeByKeyValue.remove(keyValue);
- }
- for (i = -1; ++i < n; ) {
- if (nodeByKeyValue.has(keyValues[i])) {
- exitNodes[i] = group[i];
+ 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;
+ }
}
- }
- } 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);
+ 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.substring(j + 1, i).replace(/""/g, '"');
}
- for (;i < m; ++i) {
- enterNodes[i] = d3_selection_dataNode(groupData[i]);
- }
- for (;i < n; ++i) {
- exitNodes[i] = group[i];
+ 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.substring(j, I - k);
}
+ return text.substring(j);
}
- 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);
+ while ((t = token()) !== EOF) {
+ var a = [];
+ while (t !== EOL && t !== EOF) {
+ a.push(t);
+ t = token();
+ }
+ if (f && !(a = f(a, n++))) continue;
+ rows.push(a);
}
- }
- update.enter = function() {
- return enter;
+ return rows;
};
- update.exit = function() {
- return exit;
+ 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");
};
- return update;
- };
- function d3_selection_dataNode(data) {
- return {
- __data__: data
+ 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_selectionPrototype.datum = function(value) {
- return arguments.length ? this.property("__data__", value) : this.property("__data__");
+ 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 = function(callback, delay, then) {
+ if (arguments.length < 3) {
+ if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;
+ then = Date.now();
+ }
+ var time = then + delay;
+ var timer = {
+ callback: callback,
+ time: time,
+ next: null
+ };
+ if (d3_timer_queueTail) d3_timer_queueTail.next = 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);
+ }
};
- 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)) {
- subgroup.push(node);
- }
+ 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);
}
- return d3_selection(subgroups);
+ }
+ d3.timer.flush = function() {
+ d3_timer_mark();
+ d3_timer_sweep();
};
- function d3_selection_filter(selector) {
- return function() {
- return d3_selectMatches(this, selector);
- };
+ function d3_timer_mark() {
+ var now = Date.now(), timer = d3_timer_queueHead;
+ while (timer) {
+ if (now >= timer.time) timer.flush = timer.callback(now - timer.time);
+ timer = timer.next;
+ }
+ return now;
}
- 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;
- }
+ function d3_timer_sweep() {
+ var t0, t1 = d3_timer_queueHead, time = Infinity;
+ while (t1) {
+ if (t1.flush) {
+ t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next;
+ } else {
+ if (t1.time < time) time = t1.time;
+ t1 = (t0 = t1).next;
}
}
- return this;
+ d3_timer_queueTail = t0;
+ return time;
+ }
+ var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) {
+ setTimeout(callback, 17);
};
- 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();
+ var d3_format_decimalPoint = ".", d3_format_thousandsSeparator = ",", d3_format_grouping = [ 3, 3 ];
+ 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 <= 0 ? i + 1 : i - 1) / 3) * 3));
+ }
+ return d3_formatPrefixes[8 + i / 3];
};
- function d3_selection_sortComparator(comparator) {
- if (!arguments.length) comparator = d3.ascending;
- return function(a, b) {
- return !a - !b || comparator(a.__data__, b.__data__);
+ function d3_formatPrefix(d, i) {
+ var k = Math.pow(10, Math.abs(8 - i) * 3);
+ return {
+ scale: i > 8 ? function(d) {
+ return d / k;
+ } : function(d) {
+ return d * k;
+ },
+ symbol: d
};
}
- 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));
+ d3.round = function(x, n) {
+ return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
};
- function d3_selection_on(type, listener, capture) {
- var name = "__on" + type, i = type.indexOf(".");
- if (i > 0) type = type.substring(0, i);
- function onRemove() {
- var wrapper = this[name];
- if (wrapper) {
- this.removeEventListener(type, wrapper, wrapper.$);
- delete this[name];
+ d3.format = function(specifier) {
+ var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", basePrefix = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false;
+ if (precision) precision = +precision.substring(1);
+ if (zfill || fill === "0" && align === "=") {
+ zfill = fill = "0";
+ align = "=";
+ if (comma) width -= Math.floor((width - 1) / 4);
+ }
+ 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 (basePrefix) basePrefix = "0" + type.toLowerCase();
+
+ case "c":
+ case "d":
+ integer = true;
+ precision = 0;
+ break;
+
+ case "s":
+ scale = -1;
+ type = "r";
+ break;
+ }
+ if (basePrefix === "#") basePrefix = "";
+ 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) {
+ if (integer && value % 1) return "";
+ var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign;
+ if (scale < 0) {
+ var prefix = d3.formatPrefix(value, precision);
+ value = prefix.scale(value);
+ suffix = prefix.symbol;
+ } else {
+ value *= scale;
}
+ value = type(value, precision);
+ if (!zfill && comma) value = d3_format_group(value);
+ var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
+ if (zcomma) value = d3_format_group(padding + value);
+ if (d3_format_decimalPoint) value.replace(".", d3_format_decimalPoint);
+ negative += basePrefix;
+ 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)) + suffix;
+ };
+ };
+ 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 onAdd() {
- var node = this, args = d3_array(arguments);
- onRemove.call(this);
- this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture);
- wrapper._ = listener;
- function wrapper(e) {
- var o = d3.event;
- d3.event = e;
- args[0] = node.__data__;
- try {
- listener.apply(node, args);
- } finally {
- d3.event = o;
- }
+ });
+ function d3_format_precision(x, p) {
+ return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
+ }
+ function d3_format_typeDefault(x) {
+ return x + "";
+ }
+ var d3_format_group = d3_identity;
+ if (d3_format_grouping) {
+ var d3_format_groupingLength = d3_format_grouping.length;
+ d3_format_group = function(value) {
+ var i = value.lastIndexOf("."), f = i >= 0 ? "." + value.substring(i + 1) : (i = value.length,
+ ""), t = [], j = 0, g = d3_format_grouping[0];
+ while (i > 0 && g > 0) {
+ t.push(value.substring(i -= g, i + g));
+ g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength];
}
- }
- return listener ? onAdd : onRemove;
+ return t.reverse().join(d3_format_thousandsSeparator || "") + f;
+ };
}
- d3_selectionPrototype.each = function(callback) {
- return d3_selection_each(this, function(node, i, j) {
- callback.call(node, node.__data__, i, j);
- });
+ d3.geo = {};
+ 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_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);
- }
+ function d3_geo_streamGeometry(geometry, listener) {
+ if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
+ d3_geo_streamGeometryType[geometry.type](geometry, listener);
}
- 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;
- }
+ 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);
}
- return null;
};
- d3_selectionPrototype.transition = function() {
- var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit);
- transition.time = Date.now();
- 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, id, transition);
- subgroup.push(node);
- }
+ var d3_geo_streamGeometryType = {
+ Sphere: function(object, listener) {
+ listener.sphere();
+ },
+ Point: function(object, listener) {
+ var coordinate = object.coordinates;
+ listener.point(coordinate[0], coordinate[1]);
+ },
+ MultiPoint: function(object, listener) {
+ var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate;
+ while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
+ },
+ 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);
}
- return d3_transition(subgroups, id);
- };
- var d3_selectionRoot = d3_selection([ [ d3_document ] ]);
- d3_selectionRoot[0].parentNode = d3_selectRoot;
- d3.select = function(selector) {
- return typeof selector === "string" ? d3_selectionRoot.select(selector) : d3_selection([ [ selector ] ]);
};
- d3.selectAll = function(selector) {
- return typeof selector === "string" ? d3_selectionRoot.selectAll(selector) : d3_selection([ d3_array(selector) ]);
- };
- function d3_selection_enter(selection) {
- d3_arraySubclass(selection, d3_selection_enterPrototype);
- return selection;
+ 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]);
+ listener.lineEnd();
}
- 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.insert = d3_selectionPrototype.insert;
- d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
- d3_selection_enterPrototype.node = d3_selectionPrototype.node;
- 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));
- subnode.__data__ = node.__data__;
- } else {
- subgroup.push(null);
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_transition(groups, id) {
- d3_arraySubclass(groups, d3_transitionPrototype);
- groups.id = id;
- return groups;
+ 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();
}
- var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit = {
- ease: d3_ease_cubicInOut,
- delay: 0,
- duration: 250
+ d3.geo.area = function(object) {
+ d3_geo_areaSum = 0;
+ d3.geo.stream(object, d3_geo_area);
+ return d3_geo_areaSum;
};
- d3_transitionPrototype.call = d3_selectionPrototype.call;
- d3_transitionPrototype.empty = d3_selectionPrototype.empty;
- d3_transitionPrototype.node = d3_selectionPrototype.node;
- d3.transition = function(selection) {
- return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
+ var d3_geo_areaSum, d3_geo_areaRingSum;
+ var d3_geo_area = {
+ sphere: function() {
+ d3_geo_areaSum += 4 * Ï;
+ },
+ point: d3_noop,
+ lineStart: d3_noop,
+ lineEnd: d3_noop,
+ polygonStart: function() {
+ d3_geo_areaRingSum = 0;
+ 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;
+ }
};
- d3.transition.prototype = d3_transitionPrototype;
- function d3_transitionNode(node, i, id, inherit) {
- var lock = node.__transition__ || (node.__transition__ = {
- active: 0,
- count: 0
- }), transition = lock[id];
- if (!transition) {
- var time = inherit.time;
- transition = lock[id] = {
- tween: new d3_Map(),
- event: d3.dispatch("start", "end"),
- time: time,
- ease: inherit.ease,
- delay: inherit.delay,
- duration: inherit.duration
- };
- ++lock.count;
- d3.timer(function(elapsed) {
- var d = node.__data__, ease = transition.ease, event = transition.event, delay = transition.delay, duration = transition.duration, tweened = [];
- return delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time), 1;
- function start(elapsed) {
- if (lock.active > id) return stop();
- lock.active = id;
- event.start.call(node, d, i);
- transition.tween.forEach(function(key, value) {
- if (value = value.call(node, d, i)) {
- tweened.push(value);
- }
- });
- if (!tick(elapsed)) d3.timer(tick, 0, time);
- return 1;
- }
- function tick(elapsed) {
- if (lock.active !== id) return stop();
- var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length;
- while (n > 0) {
- tweened[--n].call(node, e);
- }
- if (t >= 1) {
- stop();
- event.end.call(node, d, i);
- return 1;
- }
- }
- function stop() {
- if (--lock.count) delete lock[id]; else delete node.__transition__;
- return 1;
- }
- }, 0, time);
- return transition;
+ 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, cosÏ = Math.cos(Ï), sinÏ = Math.sin(Ï), k = sinÏ0 * sinÏ, u = cosÏ0 * cosÏ + k * Math.cos(dλ), v = k * Math.sin(dλ);
+ d3_geo_areaRingSum += 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]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ];
+ }
+ function d3_geo_sphericalEqual(a, b) {
+ return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;
}
- d3_transitionPrototype.select = function(selector) {
- var id = this.id, subgroups = [], subgroup, subnode, node;
- if (typeof selector !== "function") 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))) {
- if ("__data__" in node) subnode.__data__ = node.__data__;
- d3_transitionNode(subnode, i, id, node.__transition__[id]);
- subgroup.push(subnode);
+ 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 = Math.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 {
- subgroup.push(null);
+ if (Ï < Ï0) Ï0 = Ï;
+ if (Ï > Ï1) Ï1 = Ï;
}
- }
- }
- return d3_transition(subgroups, id);
- };
- d3_transitionPrototype.selectAll = function(selector) {
- var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
- if (typeof selector !== "function") 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.__transition__[id];
- subnodes = selector.call(node, node.__data__, i);
- subgroups.push(subgroup = []);
- for (var k = -1, o = subnodes.length; ++k < o; ) {
- d3_transitionNode(subnode = subnodes[k], k, id, transition);
- subgroup.push(subnode);
+ 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, λ_ = λ;
}
- return d3_transition(subgroups, 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)) {
- subgroup.push(node);
- }
- }
+ function lineStart() {
+ bound.point = linePoint;
}
- return d3_transition(subgroups, this.id, this.time).ease(this.ease());
- };
- d3_transitionPrototype.attr = function(nameNS, value) {
- if (arguments.length < 2) {
- for (value in nameNS) this.attr(value, nameNS[value]);
- return this;
+ function lineEnd() {
+ range[0] = λ0, range[1] = λ1;
+ bound.point = point;
+ p0 = null;
}
- var interpolate = d3_interpolateByName(nameNS), name = d3.ns.qualify(nameNS);
- function attrNull() {
- this.removeAttribute(name);
+ function ringPoint(λ, Ï) {
+ if (p0) {
+ var dλ = λ - λ_;
+ dλSum += Math.abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
+ } else λ__ = λ, Ï__ = Ï;
+ d3_geo_area.point(λ, Ï);
+ linePoint(λ, Ï);
}
- function attrNullNS() {
- this.removeAttributeNS(name.space, name.local);
+ function ringStart() {
+ d3_geo_area.lineStart();
}
- return d3_transition_tween(this, "attr." + nameNS, value, function(b) {
- function attrString() {
- var a = this.getAttribute(name), i;
- return a !== b && (i = interpolate(a, b), function(t) {
- this.setAttribute(name, i(t));
- });
- }
- function attrStringNS() {
- 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 b == null ? name.local ? attrNullNS : attrNull : (b += "", name.local ? attrStringNS : attrString);
- });
- };
- 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 ringEnd() {
+ ringPoint(λ__, Ï__);
+ d3_geo_area.lineEnd();
+ if (Math.abs(dλSum) > ε) λ0 = -(λ1 = 180);
+ range[0] = λ0, range[1] = λ1;
+ p0 = null;
}
- 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));
- };
+ function angle(λ0, λ1) {
+ return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
}
- 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 compareRanges(a, b) {
+ return a[0] - b[0];
}
- var interpolate = d3_interpolateByName(name);
- function styleNull() {
- this.style.removeProperty(name);
+ function withinRange(x, range) {
+ return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
}
- return d3_transition_tween(this, "style." + name, value, function(b) {
- function styleString() {
- var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;
- return a !== b && (i = interpolate(a, b), function(t) {
- this.style.setProperty(name, i(t), priority);
- });
+ return function(feature) {
+ Ï1 = λ1 = -(λ0 = Ï0 = Infinity);
+ ranges = [];
+ d3.geo.stream(feature, bound);
+ ranges.sort(compareRanges);
+ for (var i = 1, n = ranges.length, 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);
+ }
}
- return b == null ? styleNull : (b += "", styleString);
- });
- };
- d3_transitionPrototype.styleTween = function(name, tween, priority) {
- if (arguments.length < 3) priority = "";
- return this.tween("style." + name, function(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);
- };
- });
- };
- 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;
+ 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, Ï0 ], [ λ1, Ï1 ] ];
};
- }
- d3_transitionPrototype.remove = function() {
- return this.each("end.transition", function() {
- var p;
- if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);
- });
- };
- d3_transitionPrototype.ease = function(value) {
- var id = this.id;
- if (arguments.length < 1) return this.node().__transition__[id].ease;
- if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
- return d3_selection_each(this, function(node) {
- node.__transition__[id].ease = value;
- });
- };
- d3_transitionPrototype.delay = function(value) {
- var id = this.id;
- return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
- node.__transition__[id].delay = value.call(node, node.__data__, i, j) | 0;
- } : (value |= 0, function(node) {
- node.__transition__[id].delay = value;
- }));
- };
- d3_transitionPrototype.duration = function(value) {
- var id = this.id;
- return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
- node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j) | 0);
- } : (value = Math.max(1, value | 0), function(node) {
- node.__transition__[id].duration = value;
- }));
- };
- d3_transitionPrototype.each = function(type, listener) {
- var id = this.id;
- if (arguments.length < 2) {
- var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
- d3_transitionInheritId = id;
- d3_selection_each(this, function(node, i, j) {
- d3_transitionInherit = node.__transition__[id];
- type.call(node, node.__data__, i, j);
- });
- d3_transitionInherit = inherit;
- d3_transitionInheritId = inheritId;
- } else {
- d3_selection_each(this, function(node) {
- node.__transition__[id].event.on(type, listener);
- });
+ }();
+ d3.geo.centroid = function(object) {
+ d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ d3.geo.stream(object, d3_geo_centroid);
+ var m;
+ if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) {
+ return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ];
}
- return this;
};
- d3_transitionPrototype.transition = function() {
- var id0 = this.id, id1 = ++d3_transitionId, 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 = Object.create(node.__transition__[id0]);
- transition.delay += transition.duration;
- d3_transitionNode(node, i, id1, transition);
- }
- subgroup.push(node);
+ var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ;
+ var d3_geo_centroid = {
+ sphere: function() {
+ if (d3_geo_centroidDimension < 2) {
+ d3_geo_centroidDimension = 2;
+ d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ }
+ },
+ point: d3_geo_centroidPoint,
+ lineStart: d3_geo_centroidLineStart,
+ lineEnd: d3_geo_centroidLineEnd,
+ polygonStart: function() {
+ if (d3_geo_centroidDimension < 2) {
+ d3_geo_centroidDimension = 2;
+ d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
}
+ d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
+ },
+ polygonEnd: function() {
+ d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
}
- return d3_transition(subgroups, id1);
- };
- d3_transitionPrototype.tween = function(name, tween) {
- var id = this.id;
- if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
- return d3_selection_each(this, tween == null ? function(node) {
- node.__transition__[id].tween.remove(name);
- } : function(node) {
- node.__transition__[id].tween.set(name, tween);
- });
};
- function d3_transition_tween(groups, name, value, tween) {
- var id = groups.id;
- return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
- node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
- } : (value = tween(value), function(node) {
- node.__transition__[id].tween.set(name, value);
- }));
+ function d3_geo_centroidPoint(λ, Ï) {
+ if (d3_geo_centroidDimension) return;
+ ++d3_geo_centroidW;
+ λ *= d3_radians;
+ var cosÏ = Math.cos(Ï *= d3_radians);
+ d3_geo_centroidX += (cosÏ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW;
+ d3_geo_centroidY += (cosÏ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW;
+ d3_geo_centroidZ += (Math.sin(Ï) - d3_geo_centroidZ) / d3_geo_centroidW;
}
- var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;
- d3.timer = function(callback, delay, then) {
- if (arguments.length < 3) {
- if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;
- then = Date.now();
+ function d3_geo_centroidRingStart() {
+ var λ00, Ï00;
+ d3_geo_centroidDimension = 1;
+ d3_geo_centroidLineStart();
+ d3_geo_centroidDimension = 2;
+ var linePoint = d3_geo_centroid.point;
+ d3_geo_centroid.point = function(λ, Ï) {
+ linePoint(λ00 = λ, Ï00 = Ï);
+ };
+ d3_geo_centroid.lineEnd = function() {
+ d3_geo_centroid.point(λ00, Ï00);
+ d3_geo_centroidLineEnd();
+ d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
+ };
+ }
+ function d3_geo_centroidLineStart() {
+ var x0, y0, z0;
+ if (d3_geo_centroidDimension > 1) return;
+ if (d3_geo_centroidDimension < 1) {
+ d3_geo_centroidDimension = 1;
+ d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
}
- var timer = d3_timer_byId[callback.id];
- if (timer && timer.callback === callback) {
- timer.then = then;
- timer.delay = delay;
- } else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {
- callback: callback,
- then: then,
- delay: delay,
- next: d3_timer_queue
+ 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;
};
- 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 elapsed, now = Date.now(), t1 = d3_timer_queue;
- while (t1) {
- elapsed = now - t1.then;
- if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);
- t1 = t1.next;
+ 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_centroidW += w;
+ d3_geo_centroidX += w * (x0 + (x0 = x));
+ d3_geo_centroidY += w * (y0 + (y0 = y));
+ d3_geo_centroidZ += w * (z0 + (z0 = z));
}
- var delay = d3_timer_flush() - now;
- if (delay > 24) {
- if (isFinite(delay)) {
- clearTimeout(d3_timer_timeout);
- d3_timer_timeout = setTimeout(d3_timer_step, delay);
+ }
+ function d3_geo_centroidLineEnd() {
+ d3_geo_centroid.point = d3_geo_centroidPoint;
+ }
+ function d3_true() {
+ return true;
+ }
+ function d3_geo_clipPolygon(segments, compare, inside, 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;
}
- d3_timer_interval = 0;
- } else {
- d3_timer_interval = 1;
- d3_timer_frame(d3_timer_step);
+ var a = {
+ point: p0,
+ points: segment,
+ other: null,
+ visited: false,
+ entry: true,
+ subject: true
+ }, b = {
+ point: p0,
+ points: [ p0 ],
+ other: a,
+ visited: false,
+ entry: false,
+ subject: false
+ };
+ a.other = b;
+ subject.push(a);
+ clip.push(b);
+ a = {
+ point: p1,
+ points: [ p1 ],
+ other: null,
+ visited: false,
+ entry: false,
+ subject: true
+ };
+ b = {
+ point: p1,
+ points: [ p1 ],
+ other: a,
+ visited: false,
+ entry: true,
+ subject: false
+ };
+ a.other = b;
+ subject.push(a);
+ clip.push(b);
+ });
+ clip.sort(compare);
+ d3_geo_clipPolygonLinkCircular(subject);
+ d3_geo_clipPolygonLinkCircular(clip);
+ if (!subject.length) return;
+ if (inside) for (var i = 1, e = !inside(clip[0].point), n = clip.length; i < n; ++i) {
+ clip[i].entry = e = !e;
}
- }
- d3.timer.flush = function() {
- var elapsed, now = Date.now(), t1 = d3_timer_queue;
- while (t1) {
- elapsed = now - t1.then;
- if (!t1.delay) t1.flush = t1.callback(elapsed);
- t1 = t1.next;
+ var start = subject[0], current, points, point;
+ while (1) {
+ current = start;
+ while (current.visited) if ((current = current.next) === start) return;
+ points = current.points;
+ listener.lineStart();
+ do {
+ current.visited = current.other.visited = true;
+ if (current.entry) {
+ if (current.subject) {
+ for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);
+ } else {
+ interpolate(current.point, current.next.point, 1, listener);
+ }
+ current = current.next;
+ } else {
+ if (current.subject) {
+ points = current.prev.points;
+ for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]);
+ } else {
+ interpolate(current.point, current.prev.point, -1, listener);
+ }
+ current = current.prev;
+ }
+ current = current.other;
+ points = current.points;
+ } while (!current.visited);
+ listener.lineEnd();
}
- d3_timer_flush();
- };
- function d3_timer_flush() {
- var t0 = null, t1 = d3_timer_queue, then = Infinity;
- while (t1) {
- if (t1.flush) {
- delete d3_timer_byId[t1.callback.id];
- t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
- } else {
- then = Math.min(then, t1.then + t1.delay);
- t1 = (t0 = t1).next;
- }
+ }
+ function d3_geo_clipPolygonLinkCircular(array) {
+ if (!(n = array.length)) return;
+ var n, i = 0, a = array[0], b;
+ while (++i < n) {
+ a.next = b = array[i];
+ b.prev = a;
+ a = b;
}
- return then;
+ a.next = b = array[0];
+ b.prev = a;
}
- var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) {
- setTimeout(callback, 17);
- };
- 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) {
- 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(d3_document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0);
- var ctm = svg[0][0].getScreenCTM();
- d3_mouse_bug44083 = !(ctm.f || ctm.e);
- svg.remove();
+ function d3_geo_clip(pointVisible, clipLine, interpolate) {
+ return function(listener) {
+ var line = clipLine(listener);
+ var clip = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ clip.point = pointRing;
+ clip.lineStart = ringStart;
+ clip.lineEnd = ringEnd;
+ invisible = false;
+ invisibleArea = visibleArea = 0;
+ segments = [];
+ listener.polygonStart();
+ },
+ polygonEnd: function() {
+ clip.point = point;
+ clip.lineStart = lineStart;
+ clip.lineEnd = lineEnd;
+ segments = d3.merge(segments);
+ if (segments.length) {
+ d3_geo_clipPolygon(segments, d3_geo_clipSort, null, interpolate, listener);
+ } else if (visibleArea < -ε || invisible && invisibleArea < -ε) {
+ listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd();
+ }
+ listener.polygonEnd();
+ segments = null;
+ },
+ sphere: function() {
+ listener.polygonStart();
+ listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd();
+ listener.polygonEnd();
+ }
+ };
+ function point(λ, Ï) {
+ if (pointVisible(λ, Ï)) listener.point(λ, Ï);
}
- if (d3_mouse_bug44083) {
- point.x = e.pageX;
- point.y = e.pageY;
- } else {
- point.x = e.clientX;
- point.y = e.clientY;
+ function pointLine(λ, Ï) {
+ line.point(λ, Ï);
+ }
+ function lineStart() {
+ clip.point = pointLine;
+ line.lineStart();
+ }
+ function lineEnd() {
+ clip.point = point;
+ line.lineEnd();
+ }
+ var segments, visibleArea, invisibleArea, invisible;
+ var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring;
+ function pointRing(λ, Ï) {
+ ringListener.point(λ, Ï);
+ ring.push([ λ, Ï ]);
+ }
+ 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;
+ if (!n) {
+ invisible = true;
+ invisibleArea += d3_geo_clipAreaRing(ring, -1);
+ ring = null;
+ return;
+ }
+ ring = null;
+ if (clean & 1) {
+ segment = ringSegments[0];
+ visibleArea += d3_geo_clipAreaRing(segment, 1);
+ var n = segment.length - 1, i = -1, point;
+ 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()));
}
- point = point.matrixTransform(container.getScreenCTM().inverse());
- return [ point.x, point.y ];
+ };
+ }
+ function d3_geo_clipAreaRing(ring, invisible) {
+ if (!(n = ring.length)) return 0;
+ var n, i = 0, area = 0, p = ring[0], λ = p[0], Ï = p[1], cosÏ = Math.cos(Ï), x0 = Math.atan2(invisible * Math.sin(λ) * cosÏ, Math.sin(Ï)), y0 = 1 - invisible * Math.cos(λ) * cosÏ, x1 = x0, x, y;
+ while (++i < n) {
+ p = ring[i];
+ cosÏ = Math.cos(Ï = p[1]);
+ x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosÏ, Math.sin(Ï));
+ y = 1 - invisible * Math.cos(λ) * cosÏ;
+ if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue;
+ if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - Ï) < ε) {
+ if (y + y0 > 2) area += 4 * (x - x0);
+ } else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * Ï + x - x0) % (2 * Ï) - Ï) * (y0 + y);
+ x1 = x0, x0 = x, y0 = y;
}
- var rect = container.getBoundingClientRect();
- return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
+ return area;
}
- 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;
- }) : [];
- };
- function d3_noop() {}
- d3.scale = {};
- function d3_scaleExtent(domain) {
- var start = domain[0], stop = domain[domain.length - 1];
- return start < stop ? [ start, stop ] : [ stop, start ];
+ function d3_geo_clipSort(a, b) {
+ return ((a = a.point)[0] < 0 ? a[1] - Ï / 2 - ε : Ï / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - Ï / 2 - ε : Ï / 2 - b[1]);
}
- function d3_scaleRange(scale) {
- return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
+ var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate);
+ 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λ = Math.abs(λ1 - λ0);
+ if (Math.abs(dλ - Ï) < ε) {
+ listener.point(λ0, Ï0 = (Ï0 + Ï1) / 2 > 0 ? Ï / 2 : -Ï / 2);
+ 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 (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
+ if (Math.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_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;
- }
- if (nice = nice(x1 - x0)) {
- domain[i0] = nice.floor(x0);
- domain[i1] = nice.ceil(x1);
- }
- return domain;
+ function d3_geo_clipAntimeridianIntersect(λ0, Ï0, λ1, Ï1) {
+ var cosÏ0, cosÏ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
+ return Math.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_scale_niceDefault() {
- return Math;
+ function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
+ var Ï;
+ if (from == null) {
+ Ï = direction * Ï / 2;
+ listener.point(-Ï, Ï);
+ listener.point(0, Ï);
+ listener.point(Ï, Ï);
+ listener.point(Ï, 0);
+ listener.point(Ï, -Ï);
+ listener.point(0, -Ï);
+ listener.point(-Ï, -Ï);
+ listener.point(-Ï, 0);
+ listener.point(-Ï, Ï);
+ } else if (Math.abs(from[0] - to[0]) > ε) {
+ var s = (from[0] < to[0] ? 1 : -1) * Ï;
+ Ï = direction * s / 2;
+ listener.point(-s, Ï);
+ listener.point(0, Ï);
+ listener.point(s, Ï);
+ } else {
+ listener.point(to[0], to[1]);
+ }
}
- 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 d3_geo_clipCircle(radius) {
+ var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = Math.abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
+ return d3_geo_clip(visible, clipLine, interpolate);
+ function visible(λ, Ï) {
+ return Math.cos(λ) * Math.cos(Ï) > cr;
}
- function scale(x) {
- return output(x);
+ 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;
+ }
+ };
}
- 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) {
- return d3_scale_linearTickFormat(domain, m);
- };
- scale.nice = function() {
- d3_scale_nice(domain, d3_scale_linearNice);
- 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(dx) {
- dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
- return dx && {
- floor: function(x) {
- return Math.floor(x / dx) * dx;
- },
- ceil: function(x) {
- return Math.ceil(x / dx) * dx;
+ 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 = Math.abs(Ύλ - Ï) < ε, meridian = polar || Ύλ < ε;
+ if (!polar && Ï1 < Ï0) z = Ï0, Ï0 = Ï1, Ï1 = z;
+ if (meridian ? polar ? Ï0 + Ï1 > 0 ^ q[1] < (Math.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;
+ }
+ }
+ var d3_geo_clipViewMAX = 1e9;
+ function d3_geo_clipView(x0, y0, x1, y1) {
+ return function(listener) {
+ var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), segments, polygon, ring;
+ var clip = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ listener = bufferListener;
+ segments = [];
+ polygon = [];
+ },
+ polygonEnd: function() {
+ listener = listener_;
+ if ((segments = d3.merge(segments)).length) {
+ listener.polygonStart();
+ d3_geo_clipPolygon(segments, compare, inside, interpolate, listener);
+ listener.polygonEnd();
+ } else if (insidePolygon([ x0, y0 ])) {
+ listener.polygonStart(), listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd(), listener.polygonEnd();
+ }
+ segments = polygon = ring = null;
+ }
+ };
+ function inside(point) {
+ var a = corner(point, -1), i = insidePolygon([ a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0 ]);
+ return i;
+ }
+ 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 && isLeft(a, b, p) > 0) ++wn;
+ } else {
+ if (b[1] <= y && isLeft(a, b, p) < 0) --wn;
+ }
+ a = b;
+ }
+ }
+ return wn !== 0;
+ }
+ function isLeft(a, b, c) {
+ return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
+ }
+ 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 visible(x, y) {
+ return x0 <= x && x <= x1 && y0 <= y && y <= y1;
+ }
+ function point(x, y) {
+ if (visible(x, y)) listener.point(x, y);
+ }
+ var x__, y__, v__, x_, y_, v_, first;
+ 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_clipViewMAX, Math.min(d3_geo_clipViewMAX, x));
+ y = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, y));
+ var v = visible(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 a = [ x_, y_ ], b = [ x, y ];
+ if (clipLine(a, b)) {
+ if (!v_) {
+ listener.lineStart();
+ listener.point(a[0], a[1]);
+ }
+ listener.point(b[0], b[1]);
+ if (!v) listener.lineEnd();
+ } else if (v) {
+ listener.lineStart();
+ listener.point(x, y);
+ }
+ }
+ }
+ x_ = x, y_ = y, v_ = v;
}
+ return clip;
};
- }
- function d3_scale_linearTickRange(domain, m) {
- 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) {
- return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f");
- }
- 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_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();
+ function corner(p, direction) {
+ return Math.abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : Math.abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : Math.abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
}
- while (++j <= k) {
- u.push(uninterpolate(domain[j - 1], domain[j]));
- i.push(interpolate(range[j - 1], range[j]));
+ function compare(a, b) {
+ return comparePoints(a.point, b.point);
}
- return function(x) {
- var j = d3.bisect(domain, x, 1, k) - 1;
- return i[j](u[j](x));
- };
- }
- d3.scale.log = function() {
- return d3_scale_log(d3.scale.linear(), d3_scale_logp);
- };
- function d3_scale_log(linear, log) {
- var pow = log.pow;
- function scale(x) {
- return linear(log(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];
}
- scale.invert = function(x) {
- return pow(linear.invert(x));
- };
- scale.domain = function(x) {
- if (!arguments.length) return linear.domain().map(pow);
- log = x[0] < 0 ? d3_scale_logn : d3_scale_logp;
- pow = log.pow;
- linear.domain(x.map(log));
- return scale;
- };
- scale.nice = function() {
- linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault));
- return scale;
- };
- scale.ticks = function() {
- var extent = d3_scaleExtent(linear.domain()), ticks = [];
- if (extent.every(isFinite)) {
- var i = Math.floor(extent[0]), j = Math.ceil(extent[1]), u = pow(extent[0]), v = pow(extent[1]);
- if (log === d3_scale_logn) {
- ticks.push(pow(i));
- for (;i++ < j; ) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k);
- } else {
- for (;i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k);
- ticks.push(pow(i));
+ function clipLine(a, b) {
+ var dx = b[0] - a[0], dy = b[1] - a[1], t = [ 0, 1 ];
+ if (Math.abs(dx) < ε && Math.abs(dy) < ε) return x0 <= a[0] && a[0] <= x1 && y0 <= a[1] && a[1] <= y1;
+ if (d3_geo_clipViewT(x0 - a[0], dx, t) && d3_geo_clipViewT(a[0] - x1, -dx, t) && d3_geo_clipViewT(y0 - a[1], dy, t) && d3_geo_clipViewT(a[1] - y1, -dy, t)) {
+ if (t[1] < 1) {
+ b[0] = a[0] + t[1] * dx;
+ b[1] = a[1] + t[1] * dy;
}
- for (i = 0; ticks[i] < u; i++) {}
- for (j = ticks.length; ticks[j - 1] > v; j--) {}
- ticks = ticks.slice(i, j);
+ if (t[0] > 0) {
+ a[0] += t[0] * dx;
+ a[1] += t[0] * dy;
+ }
+ return true;
}
- return ticks;
- };
- scale.tickFormat = function(n, format) {
- if (arguments.length < 2) format = d3_scale_logFormat;
- if (!arguments.length) return format;
- var k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12,
- Math.floor) : (e = 1e-12, Math.ceil), e;
- return function(d) {
- return d / pow(f(log(d) + e)) <= k ? format(d) : "";
- };
- };
- scale.copy = function() {
- return d3_scale_log(linear.copy(), log);
- };
- return d3_scale_linearRebind(scale, linear);
- }
- var d3_scale_logFormat = d3.format(".0e");
- function d3_scale_logp(x) {
- return Math.log(x < 0 ? 0 : x) / Math.LN10;
+ return false;
+ }
}
- function d3_scale_logn(x) {
- return -Math.log(x > 0 ? 0 : -x) / Math.LN10;
+ function d3_geo_clipViewT(num, denominator, t) {
+ if (Math.abs(denominator) < ε) return num <= 0;
+ var u = num / denominator;
+ if (denominator > 0) {
+ if (u > t[1]) return false;
+ if (u > t[0]) t[0] = u;
+ } else {
+ if (u < t[0]) return false;
+ if (u < t[1]) t[1] = u;
+ }
+ return true;
}
- d3_scale_logp.pow = function(x) {
- return Math.pow(10, x);
- };
- d3_scale_logn.pow = function(x) {
- return -Math.pow(10, -x);
- };
- d3.scale.pow = function() {
- return d3_scale_pow(d3.scale.linear(), 1);
- };
- function d3_scale_pow(linear, exponent) {
- var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
- function scale(x) {
- return linear(powp(x));
+ function d3_geo_compose(a, b) {
+ function compose(x, y) {
+ return x = a(x, y), b(x[0], x[1]);
}
- scale.invert = function(x) {
- return powb(linear.invert(x));
- };
- scale.domain = function(x) {
- if (!arguments.length) return linear.domain().map(powb);
- linear.domain(x.map(powp));
- return scale;
- };
- scale.ticks = function(m) {
- return d3_scale_linearTicks(scale.domain(), m);
- };
- scale.tickFormat = function(m) {
- return d3_scale_linearTickFormat(scale.domain(), m);
- };
- scale.nice = function() {
- return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));
- };
- scale.exponent = function(x) {
- if (!arguments.length) return exponent;
- var domain = scale.domain();
- powp = d3_scale_powPow(exponent = x);
- powb = d3_scale_powPow(1 / exponent);
- return scale.domain(domain);
- };
- scale.copy = function() {
- return d3_scale_pow(linear.copy(), exponent);
+ if (a.invert && b.invert) compose.invert = function(x, y) {
+ return x = b.invert(x, y), x && a.invert(x[0], x[1]);
};
- return d3_scale_linearRebind(scale, linear);
+ return compose;
}
- function d3_scale_powPow(e) {
- return function(x) {
- return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
+ function d3_geo_resample(project) {
+ var ÎŽ2 = .5, maxDepth = 16;
+ function resample(stream) {
+ var λ0, x0, y0, a0, b0, c0;
+ var resample = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ stream.polygonStart();
+ resample.lineStart = polygonLineStart;
+ },
+ 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 polygonLineStart() {
+ var λ00, Ï00, x00, y00, a00, b00, c00;
+ lineStart();
+ resample.point = function(λ, Ï) {
+ linePoint(λ00 = λ, Ï00 = Ï), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
+ resample.point = linePoint;
+ };
+ resample.lineEnd = function() {
+ 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 = Math.abs(Math.abs(c) - 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 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) {
+ 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.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) || index.set(x, domain.push(x))) - 1) % range.length];
+ 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;
+ function projection(point) {
+ point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
+ return [ point[0] * k + ÎŽx, ÎŽy - point[1] * k ];
}
- function steps(start, step) {
- return d3.range(domain.length).map(function(i) {
- return start + step * i;
- });
+ function invert(point) {
+ point = projectRotate.invert((point[0] - ÎŽx) / k, (ÎŽy - point[1]) / k);
+ return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
}
- 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);
+ projection.stream = function(stream) {
+ return d3_geo_projectionRadiansRotate(rotate, preclip(projectResample(postclip(stream))));
};
- scale.range = function(x) {
- if (!arguments.length) return range;
- range = x;
- rangeBand = 0;
- ranger = {
- t: "range",
- a: arguments
- };
- return scale;
+ projection.clipAngle = function(_) {
+ if (!arguments.length) return clipAngle;
+ preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
+ return projection;
};
- scale.rangePoints = function(x, padding) {
- if (arguments.length < 2) padding = 0;
- var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
- range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
- rangeBand = 0;
- ranger = {
- t: "rangePoints",
- a: arguments
- };
- return scale;
+ projection.clipExtent = function(_) {
+ if (!arguments.length) return clipExtent;
+ clipExtent = _;
+ postclip = _ == null ? d3_identity : d3_geo_clipView(_[0][0], _[0][1], _[1][0], _[1][1]);
+ return projection;
};
- 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;
+ projection.scale = function(_) {
+ if (!arguments.length) return k;
+ k = +_;
+ return reset();
};
- 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)), error = stop - start - (domain.length - padding) * step;
- range = steps(start + Math.round(error / 2), step);
- if (reverse) range.reverse();
- rangeBand = Math.round(step * (1 - padding));
- ranger = {
- t: "rangeRoundBands",
- a: arguments
- };
- return scale;
+ projection.translate = function(_) {
+ if (!arguments.length) return [ x, y ];
+ x = +_[0];
+ y = +_[1];
+ return reset();
};
- scale.rangeBand = function() {
- return rangeBand;
+ projection.center = function(_) {
+ if (!arguments.length) return [ λ * d3_degrees, Ï * d3_degrees ];
+ λ = _[0] % 360 * d3_radians;
+ Ï = _[1] % 360 * d3_radians;
+ return reset();
};
- scale.rangeExtent = function() {
- return d3_scaleExtent(ranger.a[0]);
+ 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();
};
- scale.copy = function() {
- return d3_scale_ordinal(domain, ranger);
+ 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 projection;
+ }
+ return function() {
+ project = projectAt.apply(this, arguments);
+ projection.invert = project.invert && invert;
+ return reset();
};
- 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 = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ];
- var d3_category20 = [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5" ];
- var d3_category20b = [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" ];
- var d3_category20c = [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9" ];
- d3.scale.quantile = function() {
- return d3_scale_quantile([], []);
+ function d3_geo_projectionRadiansRotate(rotate, stream) {
+ return {
+ point: function(x, y) {
+ y = rotate(x * d3_radians, y * d3_radians), x = y[0];
+ stream.point(x > Ï ? x - 2 * Ï : x < -Ï ? x + 2 * Ï : x, y[1]);
+ },
+ sphere: function() {
+ stream.sphere();
+ },
+ lineStart: function() {
+ stream.lineStart();
+ },
+ lineEnd: function() {
+ stream.lineEnd();
+ },
+ polygonStart: function() {
+ stream.polygonStart();
+ },
+ polygonEnd: function() {
+ stream.polygonEnd();
+ }
+ };
+ }
+ 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_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 d3_geo_rotation(Ύλ, ÎŽÏ, Ύγ) {
+ return Ύλ ? ÎŽÏ || Ύγ ? d3_geo_compose(d3_geo_rotationλ(Ύλ), d3_geo_rotationÏγ(ÎŽÏ, Ύγ)) : d3_geo_rotationλ(Ύλ) : ÎŽÏ || Ύγ ? d3_geo_rotationÏγ(ÎŽÏ, Ύγ) : d3_geo_equirectangular;
+ }
+ function d3_geo_forwardRotationλ(Ύλ) {
+ return function(λ, Ï) {
+ return λ += Ύλ, [ λ > Ï ? λ - 2 * Ï : λ < -Ï ? λ + 2 * Ï : λ, Ï ];
+ };
+ }
+ 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ÎŽÏ), Math.asin(Math.max(-1, Math.min(1, k * cosΎγ + y * sinΎγ))) ];
}
- function scale(x) {
- if (isNaN(x = +x)) return NaN;
- return range[d3.bisect(thresholds, x)];
+ 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ÎŽÏ), Math.asin(Math.max(-1, Math.min(1, 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 ]
+ };
}
- scale.domain = function(x) {
- if (!arguments.length) return domain;
- domain = x.filter(function(d) {
- return !isNaN(d);
- }).sort(d3.ascending);
- return rescale();
+ circle.origin = function(x) {
+ if (!arguments.length) return origin;
+ origin = x;
+ return circle;
};
- scale.range = function(x) {
- if (!arguments.length) return range;
- range = x;
- return rescale();
+ circle.angle = function(x) {
+ if (!arguments.length) return angle;
+ interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
+ return circle;
};
- scale.quantiles = function() {
- return thresholds;
+ circle.precision = function(_) {
+ if (!arguments.length) return precision;
+ interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
+ return circle;
};
- scale.copy = function() {
- return d3_scale_quantile(domain, range);
+ 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) {
+ if (from != null) {
+ from = d3_geo_circleAngle(cr, from);
+ to = d3_geo_circleAngle(cr, to);
+ if (direction > 0 ? from < to : from > to) from += direction * 2 * Ï;
+ } else {
+ from = radius + direction * 2 * Ï;
+ to = radius;
+ }
+ var point;
+ for (var step = direction * precision, 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]);
+ }
};
- return rescale();
}
- d3.scale.quantize = function() {
- return d3_scale_quantize(0, 1, [ 0, 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Îλ);
};
- 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))))];
+ 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 rescale() {
- kx = range.length / (x1 - x0);
- i = range.length - 1;
- return scale;
+ 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 Math.abs(x % DX) > ε;
+ }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
+ return Math.abs(y % DY) > ε;
+ }).map(y));
}
- 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();
+ graticule.lines = function() {
+ return lines().map(function(coordinates) {
+ return {
+ type: "LineString",
+ coordinates: coordinates
+ };
+ });
};
- scale.copy = function() {
- return d3_scale_quantize(x0, x1, range);
+ graticule.outline = function() {
+ return {
+ type: "Polygon",
+ coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
+ };
};
- return rescale();
- }
- d3.scale.threshold = function() {
- return d3_scale_threshold([ .5 ], [ 0, 1 ]);
- };
- function d3_scale_threshold(domain, range) {
- function scale(x) {
- return range[d3.bisect(domain, x)];
- }
- scale.domain = function(_) {
- if (!arguments.length) return domain;
- domain = _;
- return scale;
+ 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);
};
- scale.range = function(_) {
- if (!arguments.length) return range;
- range = _;
- return scale;
+ 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);
};
- scale.copy = function() {
- return d3_scale_threshold(domain, range);
+ graticule.step = function(_) {
+ if (!arguments.length) return graticule.minorStep();
+ return graticule.majorStep(_).minorStep(_);
};
- 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;
+ graticule.majorStep = function(_) {
+ if (!arguments.length) return [ DX, DY ];
+ DX = +_[0], DY = +_[1];
+ return graticule;
};
- identity.ticks = function(m) {
- return d3_scale_linearTicks(domain, m);
+ graticule.minorStep = function(_) {
+ if (!arguments.length) return [ dx, dy ];
+ dx = +_[0], dy = +_[1];
+ return graticule;
};
- identity.tickFormat = function(m) {
- return d3_scale_linearTickFormat(domain, m);
+ 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;
};
- identity.copy = function() {
- return d3_scale_identity(domain);
+ 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 ];
+ });
};
- return identity;
}
- d3.svg = {};
- d3.svg.arc = function() {
- var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
- function arc() {
- var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0,
- a0 = a1, a1 = da), a1 - a0), df = da < Ï ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
- return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
- }
- arc.innerRadius = function(v) {
- if (!arguments.length) return innerRadius;
- innerRadius = d3_functor(v);
- return arc;
+ 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 ];
+ });
};
- arc.outerRadius = function(v) {
- if (!arguments.length) return outerRadius;
- outerRadius = d3_functor(v);
- return arc;
+ }
+ 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));
};
- arc.startAngle = function(v) {
- if (!arguments.length) return startAngle;
- startAngle = d3_functor(v);
- return arc;
+ greatArc.source = function(_) {
+ if (!arguments.length) return source;
+ source = _, source_ = typeof _ === "function" ? null : _;
+ return greatArc;
};
- arc.endAngle = function(v) {
- if (!arguments.length) return endAngle;
- endAngle = d3_functor(v);
- return arc;
+ greatArc.target = function(_) {
+ if (!arguments.length) return target;
+ target = _, target_ = typeof _ === "function" ? null : _;
+ return greatArc;
};
- arc.centroid = function() {
- var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
- return [ Math.cos(a) * r, Math.sin(a) * r ];
+ greatArc.precision = function() {
+ return arguments.length ? greatArc : 0;
};
- return arc;
+ return greatArc;
};
- var d3_svg_arcOffset = -Ï / 2, d3_svg_arcMax = 2 * Ï - 1e-6;
- function d3_svg_arcInnerRadius(d) {
- return d.innerRadius;
+ 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;
}
- function d3_svg_arcOuterRadius(d) {
- return d.outerRadius;
+ 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 = Math.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_svg_arcStartAngle(d) {
- return d.startAngle;
+ 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_svg_arcEndAngle(d) {
- return d.endAngle;
+ 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;
}
- function d3_svg_line(projection) {
- var x = d3_svg_lineX, y = d3_svg_lineY, 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 = [];
- }
+ (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 ];
}
- if (points.length) segment();
- return segments.length ? segments.join("") : null;
+ }, 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;
}
- line.x = function(_) {
- if (!arguments.length) return x;
- x = _;
- return line;
+ 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);
};
- line.y = function(_) {
- if (!arguments.length) return y;
- y = _;
- return line;
+ 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();
+ }
+ };
};
- line.defined = function(_) {
- if (!arguments.length) return defined;
- defined = _;
- return line;
+ albersUsa.precision = function(_) {
+ if (!arguments.length) return lower48.precision();
+ lower48.precision(_);
+ alaska.precision(_);
+ hawaii.precision(_);
+ return albersUsa;
};
- 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;
+ albersUsa.scale = function(_) {
+ if (!arguments.length) return lower48.scale();
+ lower48.scale(_);
+ alaska.scale(_ * .35);
+ hawaii.scale(_);
+ return albersUsa.translate(lower48.translate());
};
- line.tension = function(_) {
- if (!arguments.length) return tension;
- tension = _;
- return line;
+ 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 line;
- }
- d3.svg.line = function() {
- return d3_svg_line(d3_identity);
+ return albersUsa.scale(1070);
};
- function d3_svg_lineX(d) {
- return d[0];
- }
- function d3_svg_lineY(d) {
- return d[1];
- }
- var d3_svg_lineInterpolators = d3.map({
- linear: d3_svg_lineLinear,
- "linear-closed": d3_svg_lineLinearClosed,
- "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_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, points.length - 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));
+ 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 += Math.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);
+ };
}
- 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));
+ 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_svg_lineHermite(points, tangents) {
- if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
- return d3_svg_lineLinear(points);
+ 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);
}
- 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;
+ function pointLineStart(x, y) {
+ buffer.push("M", x, ",", y);
+ stream.point = pointLine;
}
- 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];
- }
+ function pointLine(x, y) {
+ buffer.push("L", x, ",", y);
}
- if (quad) {
- var lp = points[pi];
- path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
+ function lineEnd() {
+ stream.point = point;
}
- return path;
+ function lineEndPolygon() {
+ buffer.push("Z");
+ }
+ return stream;
}
- 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]) ]);
+ 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;
}
- return tangents;
+ };
+ function d3_geo_pathCentroidPoint(x, y) {
+ if (d3_geo_centroidDimension) return;
+ d3_geo_centroidX += x;
+ d3_geo_centroidY += y;
+ ++d3_geo_centroidZ;
}
- 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 ];
- d3_svg_lineBasisBezier(path, px, py);
- while (++i < n) {
- pi = points[i];
- px.shift();
- px.push(pi[0]);
- py.shift();
- py.push(pi[1]);
- d3_svg_lineBasisBezier(path, px, py);
+ function d3_geo_pathCentroidLineStart() {
+ var x0, y0;
+ if (d3_geo_centroidDimension !== 1) {
+ if (d3_geo_centroidDimension < 1) {
+ d3_geo_centroidDimension = 1;
+ d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ } else return;
}
- i = -1;
- while (++i < 2) {
- px.shift();
- px.push(pi[0]);
- py.shift();
- py.push(pi[1]);
- d3_svg_lineBasisBezier(path, px, py);
+ d3_geo_pathCentroid.point = function(x, y) {
+ d3_geo_pathCentroid.point = nextPoint;
+ x0 = x, y0 = y;
+ };
+ function nextPoint(x, y) {
+ var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+ d3_geo_centroidX += z * (x0 + x) / 2;
+ d3_geo_centroidY += z * (y0 + y) / 2;
+ d3_geo_centroidZ += z;
+ x0 = x, y0 = y;
}
- 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]);
+ function d3_geo_pathCentroidLineEnd() {
+ d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+ }
+ function d3_geo_pathCentroidRingStart() {
+ var x00, y00, x0, y0;
+ if (d3_geo_centroidDimension < 2) {
+ d3_geo_centroidDimension = 2;
+ d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
}
- 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);
+ d3_geo_pathCentroid.point = function(x, y) {
+ d3_geo_pathCentroid.point = nextPoint;
+ x00 = x0 = x, y00 = y0 = y;
+ };
+ function nextPoint(x, y) {
+ var z = y0 * x - x0 * y;
+ d3_geo_centroidX += z * (x0 + x);
+ d3_geo_centroidY += z * (y0 + y);
+ d3_geo_centroidZ += z * 3;
+ x0 = x, y0 = y;
}
- return path.join("");
+ d3_geo_pathCentroid.lineEnd = function() {
+ nextPoint(x00, y00);
+ };
}
- 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]);
+ 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, y);
+ context.arc(x, y, pointRadius, 0, 2 * Ï);
}
- 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);
+ function pointLineStart(x, y) {
+ context.moveTo(x, y);
+ stream.point = pointLine;
}
- return path.join("");
+ function pointLine(x, y) {
+ context.lineTo(x, y);
+ }
+ function lineEnd() {
+ stream.point = point;
+ }
+ function lineEndPolygon() {
+ context.closePath();
+ }
+ return stream;
+ }
+ d3.geo.path = function() {
+ var pointRadius = 4.5, projection, context, projectStream, contextStream;
+ function path(object) {
+ if (object) d3.geo.stream(object, projectStream(contextStream.pointRadius(typeof pointRadius === "function" ? +pointRadius.apply(this, arguments) : pointRadius)));
+ 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_centroidDimension = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
+ return d3_geo_centroidZ ? [ d3_geo_centroidX / d3_geo_centroidZ, d3_geo_centroidY / d3_geo_centroidZ ] : undefined;
+ };
+ 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 path;
+ };
+ path.context = function(_) {
+ if (!arguments.length) return context;
+ contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
+ return path;
+ };
+ path.pointRadius = function(_) {
+ if (!arguments.length) return pointRadius;
+ pointRadius = typeof _ === "function" ? _ : +_;
+ return path;
+ };
+ return path.projection(d3.geo.albersUsa()).context(null);
+ };
+ function d3_geo_pathProjectStream(project) {
+ var resample = d3_geo_resample(function(λ, Ï) {
+ return project([ λ * d3_degrees, Ï * d3_degrees ]);
+ });
+ return function(stream) {
+ stream = resample(stream);
+ return {
+ point: function(λ, Ï) {
+ stream.point(λ * d3_radians, Ï * d3_radians);
+ },
+ sphere: function() {
+ stream.sphere();
+ },
+ lineStart: function() {
+ stream.lineStart();
+ },
+ lineEnd: function() {
+ stream.lineEnd();
+ },
+ polygonStart: function() {
+ stream.polygonStart();
+ },
+ polygonEnd: function() {
+ stream.polygonEnd();
+ }
+ };
+ };
}
- 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);
- }
+ 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(Ï) ];
}
- 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]);
+ 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;
}
- 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;
+ 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(λ, Ï) {
+ var Ï = Math.abs(Math.abs(Ï) - Ï / 2) < ε ? 0 : 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)) - Ï / 2 ];
+ };
+ 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 (Math.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)) ];
}
- 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 (Math.abs(d) < 1e-6) {
- 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;
+ d3_geo_mercator.invert = function(x, y) {
+ return [ x, 2 * Math.atan(Math.exp(y)) - Ï / 2 ];
+ };
+ 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;
}
- }
- 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;
+ return v;
+ };
+ return m.clipExtent(null);
}
- function d3_svg_lineMonotone(points) {
- return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+ (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(λ, Ï) {
+ var B = Math.cos(Ï) * Math.sin(λ);
+ return [ Math.log((1 + B) / (1 - B)) / 2, Math.atan2(Math.tan(Ï), Math.cos(λ)) ];
}
- 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;
+ d3_geo_transverseMercator.invert = function(x, y) {
+ return [ Math.atan2(d3_sinh(x), Math.cos(y)), d3_asin(Math.sin(y) / d3_cosh(x)) ];
};
- 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] + d3_svg_arcOffset;
- point[0] = r * Math.cos(a);
- point[1] = r * Math.sin(a);
- }
- return points;
- }
- function d3_svg_area(projection) {
- var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, 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;
+ (d3.geo.transverseMercator = function() {
+ return d3_geo_mercatorProjection(d3_geo_transverseMercator);
+ }).raw = d3_geo_transverseMercator;
+ d3.geom = {};
+ d3.svg = {};
+ function d3_svg_line(projection) {
+ var x = d3_svg_lineX, y = d3_svg_lineY, 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(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
+ segments.push("M", interpolate(projection(points), tension));
}
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) {
+ points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
+ } else if (points.length) {
segment();
- points0 = [];
- points1 = [];
+ points = [];
}
}
- if (points0.length) segment();
+ if (points.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;
+ line.x = function(_) {
+ if (!arguments.length) return x;
+ x = _;
+ return line;
};
- area.y1 = function(_) {
- if (!arguments.length) return y1;
- y1 = _;
- return area;
+ line.y = function(_) {
+ if (!arguments.length) return y;
+ y = _;
+ return line;
};
- area.defined = function(_) {
+ line.defined = function(_) {
if (!arguments.length) return defined;
defined = _;
- return area;
+ return line;
};
- area.interpolate = function(_) {
+ line.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;
+ return line;
};
- area.tension = function(_) {
+ line.tension = function(_) {
if (!arguments.length) return tension;
tension = _;
- return area;
+ return line;
};
- return area;
+ return line;
+ }
+ d3.svg.line = function() {
+ return d3_svg_line(d3_identity);
+ };
+ function d3_svg_lineX(d) {
+ return d[0];
+ }
+ function d3_svg_lineY(d) {
+ return d[1];
+ }
+ var d3_svg_lineInterpolators = d3.map({
+ linear: d3_svg_lineLinear,
+ "linear-closed": d3_svg_lineLinearClosed,
+ "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");
}
- 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 d3_svg_lineLinearClosed(points) {
+ return d3_svg_lineLinear(points) + "Z";
+ }
+ 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, points.length - 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);
}
- 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) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
- 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) ]
- };
+ 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;
}
- function equals(a, b) {
- return a.a0 == b.a0 && a.a1 == b.a1;
+ 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];
+ }
}
- function arc(r, p, a) {
- return "A" + r + "," + r + " 0 " + +(a > Ï) + ",1 " + p;
+ if (quad) {
+ var lp = points[pi];
+ path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
}
- function curve(r0, p0, r1, p1) {
- return "Q 0,0 " + p1;
+ 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]) ]);
}
- 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;
+ return tangents;
}
- 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];
+ 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 ];
+ d3_svg_lineBasisBezier(path, px, py);
+ while (++i < n) {
+ pi = points[i];
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
}
- 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 ];
+ i = -1;
+ while (++i < 2) {
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
+ }
+ return path.join("");
}
- 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] + d3_svg_arcOffset;
- return [ r * Math.cos(a), r * Math.sin(a) ];
- };
+ 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("");
}
- 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));
+ 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]);
}
- 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;
+ 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];
}
- function d3_svg_symbolType() {
- return "circle";
+ 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_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";
+ function d3_svg_lineSlope(p0, p1) {
+ return (p1[1] - p0[1]) / (p1[0] - p0[0]);
}
- 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";
+ 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;
}
- });
- d3.svg.symbolTypes = d3_svg_symbols.keys();
- var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
- d3.svg.axis = function() {
- var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0;
- function axis(g) {
- g.each(function() {
- var g = d3.select(this);
- var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_;
- var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(".tick.minor").data(subticks, String), subtickEnter = subtick.enter().insert("line", ".tick").attr("class", "tick minor").style("opacity", 1e-6), subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style("opacity", 1);
- var tick = g.selectAll(".tick.major").data(ticks, String), tickEnter = tick.enter().insert("g", "path").attr("class", "tick major").style("opacity", 1e-6), tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform;
- var range = d3_scaleRange(scale), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"),
- d3.transition(path));
- var scale1 = scale.copy(), scale0 = this.__chart__ || scale1;
- this.__chart__ = scale1;
- 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");
- switch (orient) {
- case "bottom":
- {
- tickTransform = d3_svg_axisX;
- subtickEnter.attr("y2", tickMinorSize);
- subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize);
- lineEnter.attr("y2", tickMajorSize);
- textEnter.attr("y", Math.max(tickMajorSize, 0) + tickPadding);
- lineUpdate.attr("x2", 0).attr("y2", tickMajorSize);
- textUpdate.attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding);
- text.attr("dy", ".71em").style("text-anchor", "middle");
- pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize);
- break;
- }
-
- case "top":
- {
- tickTransform = d3_svg_axisX;
- subtickEnter.attr("y2", -tickMinorSize);
- subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize);
- lineEnter.attr("y2", -tickMajorSize);
- textEnter.attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
- lineUpdate.attr("x2", 0).attr("y2", -tickMajorSize);
- textUpdate.attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
- text.attr("dy", "0em").style("text-anchor", "middle");
- pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize);
- break;
- }
-
- case "left":
- {
- tickTransform = d3_svg_axisY;
- subtickEnter.attr("x2", -tickMinorSize);
- subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0);
- lineEnter.attr("x2", -tickMajorSize);
- textEnter.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding));
- lineUpdate.attr("x2", -tickMajorSize).attr("y2", 0);
- textUpdate.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0);
- text.attr("dy", ".32em").style("text-anchor", "end");
- pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize);
- break;
- }
-
- case "right":
- {
- tickTransform = d3_svg_axisY;
- subtickEnter.attr("x2", tickMinorSize);
- subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0);
- lineEnter.attr("x2", tickMajorSize);
- textEnter.attr("x", Math.max(tickMajorSize, 0) + tickPadding);
- lineUpdate.attr("x2", tickMajorSize).attr("y2", 0);
- textUpdate.attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0);
- text.attr("dy", ".32em").style("text-anchor", "start");
- pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize);
- break;
+ 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 (Math.abs(d) < 1e-6) {
+ 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.geom.hull = function(vertices) {
+ var x = d3_svg_lineX, y = d3_svg_lineY;
+ if (arguments.length) return hull(vertices);
+ function hull(data) {
+ if (data.length < 3) return [];
+ var fx = d3_functor(x), fy = d3_functor(y), n = data.length, vertices, plen = n - 1, points = [], stack = [], d, i, j, h = 0, x1, y1, x2, y2, u, v, a, sp;
+ if (fx === d3_svg_lineX && y === d3_svg_lineY) vertices = data; else for (i = 0,
+ vertices = []; i < n; ++i) {
+ vertices.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);
+ }
+ for (i = 1; i < n; ++i) {
+ if (vertices[i][1] < vertices[h][1] || vertices[i][1] == vertices[h][1] && vertices[i][0] < vertices[h][0]) h = i;
+ }
+ for (i = 0; i < n; ++i) {
+ if (i === h) continue;
+ y1 = vertices[i][1] - vertices[h][1];
+ x1 = vertices[i][0] - vertices[h][0];
+ points.push({
+ angle: Math.atan2(y1, x1),
+ index: i
+ });
+ }
+ points.sort(function(a, b) {
+ return a.angle - b.angle;
+ });
+ a = points[0].angle;
+ v = points[0].index;
+ u = 0;
+ for (i = 1; i < plen; ++i) {
+ j = points[i].index;
+ if (a == points[i].angle) {
+ x1 = vertices[v][0] - vertices[h][0];
+ y1 = vertices[v][1] - vertices[h][1];
+ x2 = vertices[j][0] - vertices[h][0];
+ y2 = vertices[j][1] - vertices[h][1];
+ if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) {
+ points[i].index = -1;
+ continue;
+ } else {
+ points[u].index = -1;
}
}
- if (scale.ticks) {
- tickEnter.call(tickTransform, scale0);
- tickUpdate.call(tickTransform, scale1);
- tickExit.call(tickTransform, scale1);
- subtickEnter.call(tickTransform, scale0);
- subtickUpdate.call(tickTransform, scale1);
- subtickExit.call(tickTransform, scale1);
- } else {
- var dx = scale1.rangeBand() / 2, x = function(d) {
- return scale1(d) + dx;
- };
- tickEnter.call(tickTransform, x);
- tickUpdate.call(tickTransform, x);
+ a = points[i].angle;
+ u = i;
+ v = j;
+ }
+ stack.push(h);
+ for (i = 0, j = 0; i < 2; ++j) {
+ if (points[j].index > -1) {
+ stack.push(points[j].index);
+ i++;
}
- });
+ }
+ sp = stack.length;
+ for (;j < plen; ++j) {
+ if (points[j].index < 0) continue;
+ while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) {
+ --sp;
+ }
+ stack[sp++] = points[j].index;
+ }
+ var poly = [];
+ for (i = sp - 1; i >= 0; --i) poly.push(data[stack[i]]);
+ return poly;
}
- 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, y) {
- if (!arguments.length) return tickMajorSize;
- var n = arguments.length - 1;
- tickMajorSize = +x;
- tickMinorSize = n > 1 ? +y : tickMajorSize;
- tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
- return axis;
- };
- axis.tickPadding = function(x) {
- if (!arguments.length) return tickPadding;
- tickPadding = +x;
- return axis;
+ hull.x = function(_) {
+ return arguments.length ? (x = _, hull) : x;
};
- axis.tickSubdivide = function(x) {
- if (!arguments.length) return tickSubdivide;
- tickSubdivide = +x;
- return axis;
+ hull.y = function(_) {
+ return arguments.length ? (y = _, hull) : y;
};
- return axis;
- };
- var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
- top: 1,
- right: 1,
- bottom: 1,
- left: 1
+ return hull;
};
- function d3_svg_axisX(selection, x) {
- selection.attr("transform", function(d) {
- return "translate(" + x(d) + ",0)";
- });
- }
- function d3_svg_axisY(selection, y) {
- selection.attr("transform", function(d) {
- return "translate(0," + y(d) + ")";
- });
+ function d3_geom_hullCCW(i1, i2, i3, v) {
+ var t, a, b, c, d, e, f;
+ t = v[i1];
+ a = t[0];
+ b = t[1];
+ t = v[i2];
+ c = t[0];
+ d = t[1];
+ t = v[i3];
+ e = t[0];
+ f = t[1];
+ return (f - b) * (c - a) - (d - b) * (e - a) > 0;
}
- function d3_svg_axisSubdivide(scale, ticks, m) {
- subticks = [];
- if (m && ticks.length > 1) {
- var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v;
+ d3.geom.polygon = function(coordinates) {
+ coordinates.area = function() {
+ var i = 0, n = coordinates.length, area = coordinates[n - 1][1] * coordinates[0][0] - coordinates[n - 1][0] * coordinates[0][1];
+ while (++i < n) {
+ area += coordinates[i - 1][1] * coordinates[i][0] - coordinates[i - 1][0] * coordinates[i][1];
+ }
+ return area * .5;
+ };
+ coordinates.centroid = function(k) {
+ var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c;
+ if (!arguments.length) k = -1 / (6 * coordinates.area());
+ while (++i < n) {
+ a = b;
+ b = coordinates[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 ];
+ };
+ coordinates.clip = function(subject) {
+ var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d;
while (++i < n) {
- for (j = m; --j > 0; ) {
- if ((v = +ticks[i] - j * d) >= extent[0]) {
- subticks.push(v);
+ input = subject.slice();
+ subject.length = 0;
+ b = coordinates[i];
+ c = input[(m = input.length) - 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;
}
+ a = b;
}
- for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) {
- subticks.push(v);
- }
- }
- return subticks;
+ return subject;
+ };
+ return coordinates;
+ };
+ function d3_geom_polygonInside(p, a, b) {
+ return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
}
- d3.svg.brush = function() {
- var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain;
- function brush(g) {
- g.each(function() {
- var g = d3.select(this), bg = g.selectAll(".background").data([ 0 ]), fg = g.selectAll(".extent").data([ 0 ]), tz = g.selectAll(".resize").data(resizes, String), e;
- g.style("pointer-events", "all").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
- bg.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
- fg.enter().append("rect").attr("class", "extent").style("cursor", "move");
- tz.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");
- tz.style("display", brush.empty() ? "none" : null);
- tz.exit().remove();
- if (x) {
- e = d3_scaleRange(x);
- bg.attr("x", e[0]).attr("width", e[1] - e[0]);
- redrawX(g);
+ 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 ];
+ }
+ d3.geom.delaunay = function(vertices) {
+ var edges = vertices.map(function() {
+ return [];
+ }), triangles = [];
+ d3_geom_voronoiTessellate(vertices, function(e) {
+ edges[e.region.l.index].push(vertices[e.region.r.index]);
+ });
+ edges.forEach(function(edge, i) {
+ var v = vertices[i], cx = v[0], cy = v[1];
+ edge.forEach(function(v) {
+ v.angle = Math.atan2(v[0] - cx, v[1] - cy);
+ });
+ edge.sort(function(a, b) {
+ return a.angle - b.angle;
+ });
+ for (var j = 0, m = edge.length - 1; j < m; j++) {
+ triangles.push([ v, edge[j], edge[j + 1] ]);
+ }
+ });
+ return triangles;
+ };
+ d3.geom.voronoi = function(points) {
+ var size = null, x = d3_svg_lineX, y = d3_svg_lineY, clip;
+ if (arguments.length) return voronoi(points);
+ function voronoi(data) {
+ var points, polygons = data.map(function() {
+ return [];
+ }), fx = d3_functor(x), fy = d3_functor(y), d, i, n = data.length, Z = 1e6;
+ if (fx === d3_svg_lineX && fy === d3_svg_lineY) points = data; else for (points = [],
+ i = 0; i < n; ++i) {
+ points.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);
+ }
+ d3_geom_voronoiTessellate(points, function(e) {
+ var s1, s2, x1, x2, y1, y2;
+ if (e.a === 1 && e.b >= 0) {
+ s1 = e.ep.r;
+ s2 = e.ep.l;
+ } else {
+ s1 = e.ep.l;
+ s2 = e.ep.r;
}
- if (y) {
- e = d3_scaleRange(y);
- bg.attr("y", e[0]).attr("height", e[1] - e[0]);
- redrawY(g);
+ if (e.a === 1) {
+ y1 = s1 ? s1.y : -Z;
+ x1 = e.c - e.b * y1;
+ y2 = s2 ? s2.y : Z;
+ x2 = e.c - e.b * y2;
+ } else {
+ x1 = s1 ? s1.x : -Z;
+ y1 = e.c - e.a * x1;
+ x2 = s2 ? s2.x : Z;
+ y2 = e.c - e.a * x2;
}
- redraw(g);
+ var v1 = [ x1, y1 ], v2 = [ x2, y2 ];
+ polygons[e.region.l.index].push(v1, v2);
+ polygons[e.region.r.index].push(v1, v2);
});
- }
- function redraw(g) {
- g.selectAll(".resize").attr("transform", function(d) {
- return "translate(" + extent[+/e$/.test(d)][0] + "," + extent[+/^s/.test(d)][1] + ")";
+ polygons = polygons.map(function(polygon, i) {
+ var cx = points[i][0], cy = points[i][1], angle = polygon.map(function(v) {
+ return Math.atan2(v[0] - cx, v[1] - cy);
+ }), order = d3.range(polygon.length).sort(function(a, b) {
+ return angle[a] - angle[b];
+ });
+ return order.filter(function(d, i) {
+ return !i || angle[d] - angle[order[i - 1]] > ε;
+ }).map(function(d) {
+ return polygon[d];
+ });
});
+ polygons.forEach(function(polygon, i) {
+ var n = polygon.length;
+ if (!n) return polygon.push([ -Z, -Z ], [ -Z, Z ], [ Z, Z ], [ Z, -Z ]);
+ if (n > 2) return;
+ var p0 = points[i], p1 = polygon[0], p2 = polygon[1], x0 = p0[0], y0 = p0[1], x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1], dx = Math.abs(x2 - x1), dy = y2 - y1;
+ if (Math.abs(dy) < ε) {
+ var y = y0 < y1 ? -Z : Z;
+ polygon.push([ -Z, y ], [ Z, y ]);
+ } else if (dx < ε) {
+ var x = x0 < x1 ? -Z : Z;
+ polygon.push([ x, -Z ], [ x, Z ]);
+ } else {
+ var y = (x2 - x1) * (y1 - y0) < (x1 - x0) * (y2 - y1) ? Z : -Z, z = Math.abs(dy) - dx;
+ if (Math.abs(z) < ε) {
+ polygon.push([ dy < 0 ? y : -y, y ]);
+ } else {
+ if (z > 0) y *= -1;
+ polygon.push([ -Z, y ], [ Z, y ]);
+ }
+ }
+ });
+ if (clip) for (i = 0; i < n; ++i) clip(polygons[i]);
+ for (i = 0; i < n; ++i) polygons[i].point = data[i];
+ return polygons;
}
- function redrawX(g) {
- g.select(".extent").attr("x", extent[0][0]);
- g.selectAll(".extent,.n>rect,.s>rect").attr("width", extent[1][0] - extent[0][0]);
- }
- function redrawY(g) {
- g.select(".extent").attr("y", extent[0][1]);
- g.selectAll(".extent,.e>rect,.w>rect").attr("height", extent[1][1] - extent[0][1]);
- }
- 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"), center, origin = mouse(), offset;
- var w = d3.select(d3_window).on("mousemove.brush", brushmove).on("mouseup.brush", brushend).on("touchmove.brush", brushmove).on("touchend.brush", brushend).on("keydown.brush", keydown).on("keyup.brush", keyup);
- if (dragging) {
- origin[0] = extent[0][0] - origin[0];
- origin[1] = extent[0][1] - origin[1];
- } else if (resizing) {
- var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
- offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ];
- origin[0] = extent[ex][0];
- origin[1] = extent[ey][1];
- } 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"
+ voronoi.x = function(_) {
+ return arguments.length ? (x = _, voronoi) : x;
+ };
+ voronoi.y = function(_) {
+ return arguments.length ? (y = _, voronoi) : y;
+ };
+ voronoi.size = function(_) {
+ if (!arguments.length) return size;
+ if (_ == null) {
+ clip = null;
+ } else {
+ size = [ +_[0], +_[1] ];
+ clip = d3.geom.polygon([ [ 0, 0 ], [ 0, size[1] ], size, [ size[0], 0 ] ]).clip;
+ }
+ return voronoi;
+ };
+ voronoi.links = function(data) {
+ var points, graph = data.map(function() {
+ return [];
+ }), links = [], fx = d3_functor(x), fy = d3_functor(y), d, i, n = data.length;
+ if (fx === d3_svg_lineX && fy === d3_svg_lineY) points = data; else for (i = 0; i < n; ++i) {
+ points.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);
+ }
+ d3_geom_voronoiTessellate(points, function(e) {
+ var l = e.region.l.index, r = e.region.r.index;
+ if (graph[l][r]) return;
+ graph[l][r] = graph[r][l] = true;
+ links.push({
+ source: data[l],
+ target: data[r]
+ });
});
- brushmove();
- d3_eventCancel();
- function mouse() {
- var touches = d3.event.changedTouches;
- return touches ? d3.touches(target, touches)[0] : d3.mouse(target);
+ return links;
+ };
+ voronoi.triangles = function(data) {
+ if (x === d3_svg_lineX && y === d3_svg_lineY) return d3.geom.delaunay(data);
+ var points, point, fx = d3_functor(x), fy = d3_functor(y), d, i, n;
+ for (i = 0, points = [], n = data.length; i < n; ++i) {
+ point = [ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ];
+ point.data = d;
+ points.push(point);
+ }
+ return d3.geom.delaunay(points).map(function(triangle) {
+ return triangle.map(function(point) {
+ return point.data;
+ });
+ });
+ };
+ return voronoi;
+ };
+ var d3_geom_voronoiOpposite = {
+ l: "r",
+ r: "l"
+ };
+ function d3_geom_voronoiTessellate(points, callback) {
+ var Sites = {
+ list: points.map(function(v, i) {
+ return {
+ index: i,
+ x: v[0],
+ y: v[1]
+ };
+ }).sort(function(a, b) {
+ return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0;
+ }),
+ bottomSite: null
+ };
+ var EdgeList = {
+ list: [],
+ leftEnd: null,
+ rightEnd: null,
+ init: function() {
+ EdgeList.leftEnd = EdgeList.createHalfEdge(null, "l");
+ EdgeList.rightEnd = EdgeList.createHalfEdge(null, "l");
+ EdgeList.leftEnd.r = EdgeList.rightEnd;
+ EdgeList.rightEnd.l = EdgeList.leftEnd;
+ EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd);
+ },
+ createHalfEdge: function(edge, side) {
+ return {
+ edge: edge,
+ side: side,
+ vertex: null,
+ l: null,
+ r: null
+ };
+ },
+ insert: function(lb, he) {
+ he.l = lb;
+ he.r = lb.r;
+ lb.r.l = he;
+ lb.r = he;
+ },
+ leftBound: function(p) {
+ var he = EdgeList.leftEnd;
+ do {
+ he = he.r;
+ } while (he != EdgeList.rightEnd && Geom.rightOf(he, p));
+ he = he.l;
+ return he;
+ },
+ del: function(he) {
+ he.l.r = he.r;
+ he.r.l = he.l;
+ he.edge = null;
+ },
+ right: function(he) {
+ return he.r;
+ },
+ left: function(he) {
+ return he.l;
+ },
+ leftRegion: function(he) {
+ return he.edge == null ? Sites.bottomSite : he.edge.region[he.side];
+ },
+ rightRegion: function(he) {
+ return he.edge == null ? Sites.bottomSite : he.edge.region[d3_geom_voronoiOpposite[he.side]];
}
- function keydown() {
- if (d3.event.keyCode == 32) {
- if (!dragging) {
- center = null;
- origin[0] -= extent[1][0];
- origin[1] -= extent[1][1];
- dragging = 2;
+ };
+ var Geom = {
+ bisect: function(s1, s2) {
+ var newEdge = {
+ region: {
+ l: s1,
+ r: s2
+ },
+ ep: {
+ l: null,
+ r: null
}
- d3_eventCancel();
- }
- }
- function keyup() {
- if (d3.event.keyCode == 32 && dragging == 2) {
- origin[0] += extent[1][0];
- origin[1] += extent[1][1];
- dragging = 0;
- d3_eventCancel();
+ };
+ var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy;
+ newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5;
+ if (adx > ady) {
+ newEdge.a = 1;
+ newEdge.b = dy / dx;
+ newEdge.c /= dx;
+ } else {
+ newEdge.b = 1;
+ newEdge.a = dx / dy;
+ newEdge.c /= dy;
}
- }
- function brushmove() {
- var point = mouse(), moved = false;
- if (offset) {
- point[0] += offset[0];
- point[1] += offset[1];
+ return newEdge;
+ },
+ intersect: function(el1, el2) {
+ var e1 = el1.edge, e2 = el2.edge;
+ if (!e1 || !e2 || e1.region.r == e2.region.r) {
+ return null;
}
- if (!dragging) {
- if (d3.event.altKey) {
- if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ];
- origin[0] = extent[+(point[0] < center[0])][0];
- origin[1] = extent[+(point[1] < center[1])][1];
- } else center = null;
+ var d = e1.a * e2.b - e1.b * e2.a;
+ if (Math.abs(d) < 1e-10) {
+ return null;
}
- if (resizingX && move1(point, x, 0)) {
- redrawX(g);
- moved = true;
+ var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e;
+ if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) {
+ el = el1;
+ e = e1;
+ } else {
+ el = el2;
+ e = e2;
}
- if (resizingY && move1(point, y, 1)) {
- redrawY(g);
- moved = true;
+ var rightOfSite = xint >= e.region.r.x;
+ if (rightOfSite && el.side === "l" || !rightOfSite && el.side === "r") {
+ return null;
}
- if (moved) {
- redraw(g);
- event_({
- type: "brush",
- mode: dragging ? "move" : "resize"
- });
+ return {
+ x: xint,
+ y: yint
+ };
+ },
+ rightOf: function(he, p) {
+ var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x;
+ if (rightOfSite && he.side === "l") {
+ return 1;
}
- }
- function move1(point, scale, i) {
- var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max;
- if (dragging) {
- r0 -= position;
- r1 -= size + position;
+ if (!rightOfSite && he.side === "r") {
+ return 0;
}
- min = Math.max(r0, Math.min(r1, 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;
+ if (e.a === 1) {
+ var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0;
+ if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) {
+ above = fast = dyp >= e.b * dxp;
} else {
- max = position;
+ above = p.x + p.y * e.b > e.c;
+ if (e.b < 0) {
+ above = !above;
+ }
+ if (!above) {
+ fast = 1;
+ }
}
+ if (!fast) {
+ var dxs = topsite.x - e.region.l.x;
+ above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);
+ if (e.b < 0) {
+ above = !above;
+ }
+ }
+ } else {
+ var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y;
+ above = t1 * t1 > t2 * t2 + t3 * t3;
}
- if (extent[0][i] !== min || extent[1][i] !== max) {
- extentDomain = null;
- extent[0][i] = min;
- extent[1][i] = 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);
- event_({
- type: "brushend"
- });
- d3_eventCancel();
+ return he.side === "l" ? above : !above;
+ },
+ endPoint: function(edge, side, site) {
+ edge.ep[side] = site;
+ if (!edge.ep[d3_geom_voronoiOpposite[side]]) return;
+ callback(edge);
+ },
+ distance: function(s, t) {
+ var dx = s.x - t.x, dy = s.y - t.y;
+ return Math.sqrt(dx * dx + dy * dy);
}
- }
- 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.extent = function(z) {
- var x0, x1, y0, y1, t;
- if (!arguments.length) {
- z = extentDomain || extent;
- if (x) {
- x0 = z[0][0], x1 = z[1][0];
- if (!extentDomain) {
- x0 = extent[0][0], x1 = extent[1][0];
- if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
- if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ var EventQueue = {
+ list: [],
+ insert: function(he, site, offset) {
+ he.vertex = site;
+ he.ystar = site.y + offset;
+ for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) {
+ var next = list[i];
+ if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) {
+ continue;
+ } else {
+ break;
}
}
- if (y) {
- y0 = z[0][1], y1 = z[1][1];
- if (!extentDomain) {
- y0 = extent[0][1], y1 = extent[1][1];
- if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
- if (y1 < y0) t = y0, y0 = y1, y1 = t;
- }
+ list.splice(i, 0, he);
+ },
+ del: function(he) {
+ for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {}
+ ls.splice(i, 1);
+ },
+ empty: function() {
+ return EventQueue.list.length === 0;
+ },
+ nextEvent: function(he) {
+ for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) {
+ if (ls[i] == he) return ls[i + 1];
}
- return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
- }
- extentDomain = [ [ 0, 0 ], [ 0, 0 ] ];
- if (x) {
- x0 = z[0], x1 = z[1];
- if (y) x0 = x0[0], x1 = x1[0];
- extentDomain[0][0] = x0, extentDomain[1][0] = x1;
- if (x.invert) x0 = x(x0), x1 = x(x1);
- if (x1 < x0) t = x0, x0 = x1, x1 = t;
- extent[0][0] = x0 | 0, extent[1][0] = x1 | 0;
- }
- if (y) {
- y0 = z[0], y1 = z[1];
- if (x) y0 = y0[1], y1 = y1[1];
- extentDomain[0][1] = y0, extentDomain[1][1] = y1;
- if (y.invert) y0 = y(y0), y1 = y(y1);
- if (y1 < y0) t = y0, y0 = y1, y1 = t;
- extent[0][1] = y0 | 0, extent[1][1] = y1 | 0;
+ return null;
+ },
+ min: function() {
+ var elem = EventQueue.list[0];
+ return {
+ x: elem.vertex.x,
+ y: elem.ystar
+ };
+ },
+ extractMin: function() {
+ return EventQueue.list.shift();
}
- return brush;
- };
- brush.clear = function() {
- extentDomain = null;
- extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0;
- return brush;
- };
- brush.empty = function() {
- return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][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" ], [] ];
- d3.behavior = {};
- d3.behavior.drag = function() {
- var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null;
- function drag() {
- this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown);
- }
- function mousedown() {
- var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0;
- var w = d3.select(d3_window).on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
- if (origin) {
- offset = origin.apply(target, arguments);
- offset = [ offset.x - origin_[0], offset.y - origin_[1] ];
+ EdgeList.init();
+ Sites.bottomSite = Sites.list.shift();
+ var newSite = Sites.list.shift(), newIntStar;
+ var lbnd, rbnd, llbnd, rrbnd, bisector;
+ var bot, top, temp, p, v;
+ var e, pm;
+ while (true) {
+ if (!EventQueue.empty()) {
+ newIntStar = EventQueue.min();
+ }
+ if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) {
+ lbnd = EdgeList.leftBound(newSite);
+ rbnd = EdgeList.right(lbnd);
+ bot = EdgeList.rightRegion(lbnd);
+ e = Geom.bisect(bot, newSite);
+ bisector = EdgeList.createHalfEdge(e, "l");
+ EdgeList.insert(lbnd, bisector);
+ p = Geom.intersect(lbnd, bisector);
+ if (p) {
+ EventQueue.del(lbnd);
+ EventQueue.insert(lbnd, p, Geom.distance(p, newSite));
+ }
+ lbnd = bisector;
+ bisector = EdgeList.createHalfEdge(e, "r");
+ EdgeList.insert(lbnd, bisector);
+ p = Geom.intersect(bisector, rbnd);
+ if (p) {
+ EventQueue.insert(bisector, p, Geom.distance(p, newSite));
+ }
+ newSite = Sites.list.shift();
+ } else if (!EventQueue.empty()) {
+ lbnd = EventQueue.extractMin();
+ llbnd = EdgeList.left(lbnd);
+ rbnd = EdgeList.right(lbnd);
+ rrbnd = EdgeList.right(rbnd);
+ bot = EdgeList.leftRegion(lbnd);
+ top = EdgeList.rightRegion(rbnd);
+ v = lbnd.vertex;
+ Geom.endPoint(lbnd.edge, lbnd.side, v);
+ Geom.endPoint(rbnd.edge, rbnd.side, v);
+ EdgeList.del(lbnd);
+ EventQueue.del(rbnd);
+ EdgeList.del(rbnd);
+ pm = "l";
+ if (bot.y > top.y) {
+ temp = bot;
+ bot = top;
+ top = temp;
+ pm = "r";
+ }
+ e = Geom.bisect(bot, top);
+ bisector = EdgeList.createHalfEdge(e, pm);
+ EdgeList.insert(llbnd, bisector);
+ Geom.endPoint(e, d3_geom_voronoiOpposite[pm], v);
+ p = Geom.intersect(llbnd, bisector);
+ if (p) {
+ EventQueue.del(llbnd);
+ EventQueue.insert(llbnd, p, Geom.distance(p, bot));
+ }
+ p = Geom.intersect(bisector, rrbnd);
+ if (p) {
+ EventQueue.insert(bisector, p, Geom.distance(p, bot));
+ }
} else {
- offset = [ 0, 0 ];
- }
- if (touchId == null) d3_eventCancel();
- event_({
- type: "dragstart"
- });
- function point() {
- var p = target.parentNode;
- return touchId != null ? d3.touches(p).filter(function(p) {
- return p.identifier === touchId;
- })[0] : d3.mouse(p);
+ break;
}
- function dragmove() {
- if (!target.parentNode) return dragend();
- var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1];
- moved |= dx | dy;
- origin_ = p;
- d3_eventCancel();
- event_({
- type: "drag",
- x: p[0] + offset[0],
- y: p[1] + offset[1],
- dx: dx,
- dy: dy
- });
+ }
+ for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) {
+ callback(lbnd.edge);
+ }
+ }
+ d3.geom.quadtree = function(points, x1, y1, x2, y2) {
+ var x = d3_svg_lineX, y = d3_svg_lineY, compat;
+ if (compat = arguments.length) {
+ x = d3_geom_quadtreeCompatX;
+ y = d3_geom_quadtreeCompatY;
+ if (compat === 3) {
+ y2 = y1;
+ x2 = x1;
+ y1 = x1 = 0;
}
- function dragend() {
- event_({
- type: "dragend"
- });
- if (moved) {
- d3_eventCancel();
- if (d3.event.target === eventTarget) w.on("click.drag", click, true);
+ 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_);
}
- w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null);
}
- function click() {
- d3_eventCancel();
- w.on("click.drag", null);
+ 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 (Math.abs(nx - x) + Math.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 sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right;
+ n.leaf = false;
+ n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
+ if (right) x1 = sx; else x2 = sx;
+ if (bottom) y1 = sy; else y2 = sy;
+ 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_);
+ };
+ 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;
}
- drag.origin = function(x) {
- if (!arguments.length) return origin;
- origin = x;
- return drag;
- };
- return d3.rebind(drag, event, "on");
- };
- d3.behavior.zoom = function() {
- var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime;
- function zoom() {
- this.on("mousedown.zoom", mousedown).on("mousemove.zoom", mousemove).on(d3_behavior_zoomWheel + ".zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart);
- }
- zoom.translate = function(x) {
- if (!arguments.length) return translate;
- translate = x.map(Number);
- rescale();
- return zoom;
- };
- zoom.scale = function(x) {
- if (!arguments.length) return scale;
- scale = +x;
- rescale();
- return zoom;
+ quadtree.x = function(_) {
+ return arguments.length ? (x = _, quadtree) : x;
};
- zoom.scaleExtent = function(x) {
- if (!arguments.length) return scaleExtent;
- scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);
- return zoom;
+ quadtree.y = function(_) {
+ return arguments.length ? (y = _, quadtree) : y;
};
- zoom.x = function(z) {
- if (!arguments.length) return x1;
- x1 = z;
- x0 = z.copy();
- translate = [ 0, 0 ];
- scale = 1;
- return zoom;
+ quadtree.size = function(_) {
+ if (!arguments.length) return x1 == null ? null : [ x2, y2 ];
+ if (_ == null) {
+ x1 = y1 = x2 = y2 = null;
+ } else {
+ x1 = y1 = 0;
+ x2 = +_[0], y2 = +_[1];
+ }
+ return quadtree;
};
- zoom.y = function(z) {
- if (!arguments.length) return y1;
- y1 = z;
- y0 = z.copy();
- translate = [ 0, 0 ];
- scale = 1;
- return zoom;
+ 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 location(p) {
- return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ];
- }
- function point(l) {
- return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ];
+ }
+ 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 scaleTo(s) {
- scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+ }
+ 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.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;
}
- function translateTo(p, l) {
- l = point(l);
- translate[0] += p[0] - l[0];
- translate[1] += p[1] - l[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;
}
- function rescale() {
- if (x1) x1.domain(x0.range().map(function(x) {
- return (x - translate[0]) / scale;
- }).map(x0.invert));
- if (y1) y1.domain(y0.range().map(function(y) {
- return (y - translate[1]) / scale;
- }).map(y0.invert));
+ 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.interpolateNumber = d3_interpolateNumber;
+ function d3_interpolateNumber(a, b) {
+ b -= a = +a;
+ return function(t) {
+ return a + b * t;
+ };
+ }
+ 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("");
}
- function dispatch(event) {
- rescale();
- d3.event.preventDefault();
- event({
- type: "zoom",
- scale: scale,
- translate: translate
+ 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 + ")");
}
- function mousedown() {
- var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(d3_window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target));
- d3_window.focus();
- d3_eventCancel();
- function mousemove() {
- moved = 1;
- translateTo(d3.mouse(target), l);
- dispatch(event_);
- }
- function mouseup() {
- if (moved) d3_eventCancel();
- w.on("mousemove.zoom", null).on("mouseup.zoom", null);
- if (moved && d3.event.target === eventTarget) w.on("click.zoom", click, true);
- }
- function click() {
- d3_eventCancel();
- w.on("click.zoom", null);
- }
+ 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 + ")");
}
- function mousewheel() {
- if (!translate0) translate0 = location(d3.mouse(this));
- scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);
- translateTo(d3.mouse(this), translate0);
- dispatch(event.of(this, arguments));
+ 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 + ")");
}
- function mousemove() {
- translate0 = null;
+ n = q.length;
+ return function(t) {
+ var i = -1, o;
+ while (++i < n) s[(o = q[i]).i] = o.x(t);
+ return s.join("");
+ };
+ }
+ d3.interpolateObject = d3_interpolateObject;
+ function d3_interpolateObject(a, b) {
+ var i = {}, c = {}, k;
+ for (k in a) {
+ if (k in b) {
+ i[k] = d3_interpolateByName(k)(a[k], b[k]);
+ } else {
+ c[k] = a[k];
+ }
}
- function dblclick() {
- var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2;
- scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
- translateTo(p, l);
- dispatch(event.of(this, arguments));
+ for (k in b) {
+ if (!(k in a)) {
+ c[k] = b[k];
+ }
}
- function touchstart() {
- var touches = d3.touches(this), now = Date.now();
- scale0 = scale;
- translate0 = {};
- touches.forEach(function(t) {
- translate0[t.identifier] = location(t);
+ return function(t) {
+ for (k in i) c[k] = i[k](t);
+ return c;
+ };
+ }
+ d3.interpolateString = d3_interpolateString;
+ function d3_interpolateString(a, b) {
+ var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
+ a = a + "", b = b + "";
+ d3_interpolate_number.lastIndex = 0;
+ for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
+ if (m.index) s.push(b.substring(s0, s1 = m.index));
+ q.push({
+ i: s.length,
+ x: m[0]
});
- d3_eventCancel();
- if (touches.length === 1) {
- if (now - touchtime < 500) {
- var p = touches[0], l = location(touches[0]);
- scaleTo(scale * 2);
- translateTo(p, l);
- dispatch(event.of(this, arguments));
+ s.push(null);
+ s0 = d3_interpolate_number.lastIndex;
+ }
+ if (s0 < b.length) s.push(b.substring(s0));
+ for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
+ o = q[i];
+ if (o.x == m[0]) {
+ if (o.i) {
+ if (s[o.i + 1] == null) {
+ s[o.i - 1] += o.x;
+ s.splice(o.i, 1);
+ for (j = i + 1; j < n; ++j) q[j].i--;
+ } else {
+ s[o.i - 1] += o.x + s[o.i + 1];
+ s.splice(o.i, 2);
+ for (j = i + 1; j < n; ++j) q[j].i -= 2;
+ }
+ } else {
+ if (s[o.i + 1] == null) {
+ s[o.i] = o.x;
+ } else {
+ s[o.i] = o.x + s[o.i + 1];
+ s.splice(o.i + 1, 1);
+ for (j = i + 1; j < n; ++j) q[j].i--;
+ }
}
- touchtime = now;
+ q.splice(i, 1);
+ n--;
+ i--;
+ } else {
+ o.x = d3_interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
}
}
- function touchmove() {
- var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier];
- if (p1 = touches[1]) {
- var p1, l1 = translate0[p1.identifier];
- p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
- l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
- scaleTo(d3.event.scale * scale0);
+ while (i < n) {
+ o = q.pop();
+ if (s[o.i + 1] == null) {
+ s[o.i] = o.x;
+ } else {
+ s[o.i] = o.x + s[o.i + 1];
+ s.splice(o.i + 1, 1);
}
- translateTo(p0, l0);
- touchtime = null;
- dispatch(event.of(this, arguments));
+ n--;
}
- return d3.rebind(zoom, event, "on");
+ if (s.length === 1) {
+ return s[0] == null ? (o = q[0].x, function(t) {
+ return o(t) + "";
+ }) : function() {
+ return b;
+ };
+ }
+ return function(t) {
+ for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
+ return s.join("");
+ };
+ }
+ var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/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;
+ }
+ function d3_interpolateByName(name) {
+ return name == "transform" ? d3_interpolateTransform : d3_interpolate;
+ }
+ 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 : t === "object" ? Array.isArray(b) ? d3_interpolateArray : 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_behavior_zoomInfinity = [ 0, Infinity ];
- var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in document ? (d3_behavior_zoomDelta = function() {
- return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
- }, "wheel") : "onmousewheel" in document ? (d3_behavior_zoomDelta = function() {
- return d3.event.wheelDelta;
- }, "mousewheel") : (d3_behavior_zoomDelta = function() {
- return -d3.event.detail;
- }, "MozMousePixelScroll");
+ 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.substring(0, i) : name, m = i >= 0 ? name.substring(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, Array.prototype.slice.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 * Ï / 2);
+ }
+ 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 / (2 * Ï) * 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) * 2 * Ï / 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);
+ };
+ }
+ function d3_uninterpolateNumber(a, b) {
+ b = b - (a = +a) ? 1 / (b - a) : 0;
+ return function(x) {
+ return (x - a) * b;
+ };
+ }
+ function d3_uninterpolateClamp(a, b) {
+ b = b - (a = +a) ? 1 / (b - a) : 0;
+ return function(x) {
+ return Math.max(0, Math.min(1, (x - a) * b));
+ };
+ }
d3.layout = {};
d3.layout.bundle = function() {
return function(links) {
@@ -4145,465 +5387,169 @@ d3 = function() {
};
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.gravity = function(x) {
- if (!arguments.length) return gravity;
- gravity = +x;
- return force;
- };
- force.theta = function(x) {
- if (!arguments.length) return theta;
- theta = +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, j, 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) {
- var neighbors = neighbor(i), j = -1, m = neighbors.length, x;
- while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;
- return Math.random() * size;
- }
- function neighbor() {
- if (!neighbors) {
- neighbors = [];
- 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);
- }
- }
- return neighbors[i];
- }
- 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.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 = 2 * Ï;
- function pie(data) {
- var values = data.map(function(d, i) {
- return +value.call(pie, d, i);
- });
- var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
- var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - startAngle) / d3.sum(values);
- var index = d3.range(data.length);
- 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]);
- });
- var arcs = [];
- index.forEach(function(i) {
- var d;
- arcs[i] = {
- data: data[i],
- value: d = values[i],
- startAngle: a,
- endAngle: a += d * k
- };
- });
- return arcs;
- }
- pie.value = function(x) {
- if (!arguments.length) return value;
- value = x;
- return pie;
+ nodes = x;
+ return force;
};
- pie.sort = function(x) {
- if (!arguments.length) return sort;
- sort = x;
- return pie;
+ force.links = function(x) {
+ if (!arguments.length) return links;
+ links = x;
+ return force;
};
- pie.startAngle = function(x) {
- if (!arguments.length) return startAngle;
- startAngle = x;
- return pie;
+ force.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return force;
};
- pie.endAngle = function(x) {
- if (!arguments.length) return endAngle;
- endAngle = x;
- return pie;
+ force.linkDistance = function(x) {
+ if (!arguments.length) return linkDistance;
+ linkDistance = typeof x === "function" ? x : +x;
+ return force;
};
- 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) {
- 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 n = series.length, m = series[0].length, 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;
+ force.distance = force.linkDistance;
+ force.linkStrength = function(x) {
+ if (!arguments.length) return linkStrength;
+ linkStrength = typeof x === "function" ? x : +x;
+ return force;
};
- stack.order = function(x) {
- if (!arguments.length) return order;
- order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
- return stack;
+ force.friction = function(x) {
+ if (!arguments.length) return friction;
+ friction = +x;
+ return force;
};
- stack.offset = function(x) {
- if (!arguments.length) return offset;
- offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
- return stack;
+ force.charge = function(x) {
+ if (!arguments.length) return charge;
+ charge = typeof x === "function" ? x : +x;
+ return force;
};
- stack.x = function(z) {
- if (!arguments.length) return x;
- x = z;
- return stack;
+ force.gravity = function(x) {
+ if (!arguments.length) return gravity;
+ gravity = +x;
+ return force;
};
- stack.y = function(z) {
- if (!arguments.length) return y;
- y = z;
- return stack;
+ force.theta = function(x) {
+ if (!arguments.length) return theta;
+ theta = +x;
+ return force;
};
- stack.out = function(z) {
- if (!arguments.length) return out;
- out = z;
- return stack;
+ 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;
};
- 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 = [];
+ force.start = function() {
+ var i, j, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
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;
+ (o = nodes[i]).index = i;
+ o.weight = 0;
}
- 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 (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 (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;
+ 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;
}
- }
- 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;
+ 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) {
+ var neighbors = neighbor(i), j = -1, m = neighbors.length, x;
+ while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;
+ return Math.random() * size;
}
- 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]);
+ function neighbor() {
+ if (!neighbors) {
+ neighbors = [];
+ 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);
}
}
+ return neighbors[i];
}
- return bins;
- }
- histogram.value = function(x) {
- if (!arguments.length) return valuer;
- valuer = x;
- return histogram;
+ return force.resume();
};
- histogram.range = function(x) {
- if (!arguments.length) return ranger;
- ranger = d3_functor(x);
- return histogram;
+ force.resume = function() {
+ return force.alpha(.1);
};
- 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;
+ force.stop = function() {
+ return force.alpha(0);
};
- histogram.frequency = function(x) {
- if (!arguments.length) return frequency;
- frequency = !!x;
- return histogram;
+ 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);
};
- return histogram;
+ function dragmove(d) {
+ d.px = d3.event.x, d.py = d3.event.y;
+ force.resume();
+ }
+ return d3.rebind(force, event, "on");
};
- function d3_layout_histogramBinSturges(range, values) {
- return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
+ function d3_layout_forceDragstart(d) {
+ d.fixed |= 2;
}
- 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_forceDragend(d) {
+ d.fixed &= ~6;
}
- function d3_layout_histogramRange(values) {
- return [ d3.min(values), d3.max(values) ];
+ 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.hierarchy = function() {
var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
function recurse(node, depth, nodes) {
@@ -4687,2492 +5633,2325 @@ d3 = function() {
});
}));
}
- d3.layout.pack = function() {
- var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ];
- function pack(d, i) {
- var nodes = hierarchy.call(this, d, i), root = nodes[0];
- root.x = 0;
- root.y = 0;
- d3_layout_treeVisitAfter(root, function(d) {
- d.r = Math.sqrt(d.value);
- });
- d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
- var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h);
- if (padding > 0) {
- var dr = padding * k / 2;
- d3_layout_treeVisitAfter(root, function(d) {
- d.r += dr;
- });
- d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
- d3_layout_treeVisitAfter(root, function(d) {
- d.r -= dr;
- });
- k = Math.max(2 * root.r / w, 2 * root.r / h);
- }
- d3_layout_packTransform(root, w / 2, h / 2, 1 / k);
- return nodes;
- }
- pack.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- 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 dr * dr - dx * dx - dy * dy > .001;
- }
- 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.cluster = function() {
- var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
- function cluster(d, i) {
- var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
- d3_layout_treeVisitAfter(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;
+ 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;
}
- });
- 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_treeVisitAfter(root, function(node) {
- node.x = (node.x - x0) / (x1 - x0) * size[0];
- node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
- });
+ }
+ }
+ 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;
}
- cluster.separation = function(x) {
- if (!arguments.length) return separation;
- separation = x;
- return cluster;
- };
- cluster.size = function(x) {
+ partition.size = function(x) {
if (!arguments.length) return size;
size = x;
- return cluster;
+ return partition;
};
- return d3_layout_hierarchyRebind(cluster, hierarchy);
+ return d3_layout_hierarchyRebind(partition, 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.tree = function() {
- var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
- function tree(d, i) {
- var nodes = hierarchy.call(this, d, i), root = nodes[0];
- function firstWalk(node, previousSibling) {
- var children = node.children, layout = node._tree;
- if (children && (n = children.length)) {
- var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
- while (++i < n) {
- child = children[i];
- firstWalk(child, previousChild);
- ancestor = apportion(child, previousChild, ancestor);
- previousChild = child;
- }
- d3_layout_treeShift(node);
- var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
- if (previousSibling) {
- layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
- layout.mod = layout.prelim - midpoint;
- } else {
- layout.prelim = midpoint;
- }
- } else {
- if (previousSibling) {
- layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
- }
- }
- }
- function secondWalk(node, x) {
- node.x = node._tree.prelim + x;
- var children = node.children;
- if (children && (n = children.length)) {
- var i = -1, n;
- x += node._tree.mod;
- while (++i < n) {
- secondWalk(children[i], x);
- }
- }
- }
- function apportion(node, previousSibling, ancestor) {
- if (previousSibling) {
- var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, 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._tree.ancestor = node;
- shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
- if (shift > 0) {
- d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
- sip += shift;
- sop += shift;
- }
- sim += vim._tree.mod;
- sip += vip._tree.mod;
- som += vom._tree.mod;
- sop += vop._tree.mod;
- }
- if (vim && !d3_layout_treeRight(vop)) {
- vop._tree.thread = vim;
- vop._tree.mod += sim - sop;
- }
- if (vip && !d3_layout_treeLeft(vom)) {
- vom._tree.thread = vip;
- vom._tree.mod += sip - som;
- ancestor = node;
- }
- }
- return ancestor;
- }
- d3_layout_treeVisitAfter(root, function(node, previousSibling) {
- node._tree = {
- ancestor: node,
- prelim: 0,
- mod: 0,
- change: 0,
- shift: 0,
- number: previousSibling ? previousSibling._tree.number + 1 : 0
- };
+ d3.layout.pie = function() {
+ var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * Ï;
+ function pie(data) {
+ var values = data.map(function(d, i) {
+ return +value.call(pie, d, i);
});
- firstWalk(root);
- secondWalk(root, -root._tree.prelim);
- var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
- d3_layout_treeVisitAfter(root, function(node) {
- node.x = (node.x - x0) / (x1 - x0) * size[0];
- node.y = node.depth / y1 * size[1];
- delete node._tree;
+ var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
+ var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);
+ var index = d3.range(data.length);
+ 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]);
});
- return nodes;
+ var arcs = [];
+ index.forEach(function(i) {
+ var d;
+ arcs[i] = {
+ data: data[i],
+ value: d = values[i],
+ startAngle: a,
+ endAngle: a += d * k
+ };
+ });
+ return arcs;
}
- tree.separation = function(x) {
- if (!arguments.length) return separation;
- separation = x;
- return tree;
+ pie.value = function(x) {
+ if (!arguments.length) return value;
+ value = x;
+ return pie;
};
- tree.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- return tree;
+ pie.sort = function(x) {
+ if (!arguments.length) return sort;
+ sort = x;
+ return pie;
};
- return d3_layout_hierarchyRebind(tree, hierarchy);
+ pie.startAngle = function(x) {
+ if (!arguments.length) return startAngle;
+ startAngle = x;
+ return pie;
+ };
+ pie.endAngle = function(x) {
+ if (!arguments.length) return endAngle;
+ endAngle = x;
+ return pie;
+ };
+ return pie;
};
- function d3_layout_treeSeparation(a, b) {
- return a.parent == b.parent ? 1 : 2;
- }
- function d3_layout_treeLeft(node) {
- var children = node.children;
- return children && children.length ? children[0] : node._tree.thread;
- }
- function d3_layout_treeRight(node) {
- var children = node.children, n;
- return children && (n = children.length) ? children[n - 1] : node._tree.thread;
- }
- function d3_layout_treeSearch(node, compare) {
- var children = node.children;
- if (children && (n = children.length)) {
- var child, n, i = -1;
- while (++i < n) {
- if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
- node = child;
+ 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) {
+ 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 n = series.length, m = series[0].length, 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;
}
- return node;
- }
- function d3_layout_treeRightmost(a, b) {
- return a.x - b.x;
+ 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_treeLeftmost(a, b) {
- return b.x - a.x;
+ function d3_layout_stackY(d) {
+ return d.y;
}
- function d3_layout_treeDeepest(a, b) {
- return a.depth - b.depth;
+ function d3_layout_stackOut(d, y0, y) {
+ d.y0 = y0;
+ d.y = y;
}
- function d3_layout_treeVisitAfter(node, callback) {
- function visit(node, previousSibling) {
- var children = node.children;
- if (children && (n = children.length)) {
- var child, previousChild = null, i = -1, n;
- while (++i < n) {
- child = children[i];
- visit(child, previousChild);
- previousChild = child;
+ 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);
}
}
- callback(node, previousSibling);
- }
- visit(node, null);
- }
- function d3_layout_treeShift(node) {
- var shift = 0, change = 0, children = node.children, i = children.length, child;
- while (--i >= 0) {
- child = children[i]._tree;
- child.prelim += shift;
- child.mod += shift;
- shift += child.shift + (change += child.change);
- }
- }
- function d3_layout_treeMove(ancestor, node, shift) {
- ancestor = ancestor._tree;
- node = node._tree;
- var change = shift / (node.number - ancestor.number);
- ancestor.change += change;
- node.change -= change;
- node.shift += shift;
- node.prelim += shift;
- node.mod += shift;
- }
- function d3_layout_treeAncestor(vim, node, ancestor) {
- return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
- }
- 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;
+ 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);
}
- }
- 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);
+ for (j = 0; j < m; ++j) {
+ y0[j] = (max - sums[j]) / 2;
}
- }
- 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;
+ 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];
}
- children.forEach(stickify);
+ y0[j] = o -= s1 ? s2 / s1 * dx : 0;
+ if (o < o0) o0 = o;
}
- }
- 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;
+ 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;
}
- 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;
+ 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;
}
}
- 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);
+ 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;
}
- function padConstant(node) {
- return d3_layout_treemapPad(node, x);
+ 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]);
+ }
+ }
}
- 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;
+ return bins;
+ }
+ histogram.value = function(x) {
+ if (!arguments.length) return valuer;
+ valuer = x;
+ return histogram;
};
- treemap.sticky = function(x) {
- if (!arguments.length) return sticky;
- sticky = x;
- stickies = null;
- return treemap;
+ histogram.range = function(x) {
+ if (!arguments.length) return ranger;
+ ranger = d3_functor(x);
+ return histogram;
};
- treemap.ratio = function(x) {
- if (!arguments.length) return ratio;
- ratio = x;
- return treemap;
+ 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;
};
- treemap.mode = function(x) {
- if (!arguments.length) return mode;
- mode = x + "";
- return treemap;
+ histogram.frequency = function(x) {
+ if (!arguments.length) return frequency;
+ frequency = !!x;
+ return histogram;
};
- return d3_layout_hierarchyRebind(treemap, hierarchy);
+ return histogram;
};
- function d3_layout_treemapPadNull(node) {
- return {
- x: node.x,
- y: node.y,
- dx: node.dx,
- dy: node.dy
- };
+ function d3_layout_histogramBinSturges(range, values) {
+ return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
}
- 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
- };
+ 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_dsv(delimiter, mimeType) {
- var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
- function dsv(url, callback) {
- return d3.xhr(url, mimeType, callback).response(response);
- }
- function response(request) {
- return dsv.parse(request.responseText);
- }
- dsv.parse = function(text) {
- var o;
- return dsv.parseRows(text, function(row) {
- if (o) return o(row);
- o = new Function("d", "return {" + row.map(function(name, i) {
- return JSON.stringify(name) + ": d[" + i + "]";
- }).join(",") + "}");
- });
- };
- 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;
- }
+ function d3_layout_histogramRange(values) {
+ return [ d3.min(values), d3.max(values) ];
+ }
+ d3.layout.tree = function() {
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
+ function tree(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0];
+ function firstWalk(node, previousSibling) {
+ var children = node.children, layout = node._tree;
+ if (children && (n = children.length)) {
+ var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
+ while (++i < n) {
+ child = children[i];
+ firstWalk(child, previousChild);
+ ancestor = apportion(child, previousChild, ancestor);
+ previousChild = child;
}
- 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;
+ d3_layout_treeShift(node);
+ var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
+ if (previousSibling) {
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
+ layout.mod = layout.prelim - midpoint;
+ } else {
+ layout.prelim = midpoint;
+ }
+ } else {
+ if (previousSibling) {
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
}
- return text.substring(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.substring(j, I - k);
+ }
+ function secondWalk(node, x) {
+ node.x = node._tree.prelim + x;
+ var children = node.children;
+ if (children && (n = children.length)) {
+ var i = -1, n;
+ x += node._tree.mod;
+ while (++i < n) {
+ secondWalk(children[i], x);
+ }
}
- return text.substring(j);
}
- while ((t = token()) !== EOF) {
- var a = [];
- while (t !== EOL && t !== EOF) {
- a.push(t);
- t = token();
+ function apportion(node, previousSibling, ancestor) {
+ if (previousSibling) {
+ var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, 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._tree.ancestor = node;
+ shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
+ if (shift > 0) {
+ d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
+ sip += shift;
+ sop += shift;
+ }
+ sim += vim._tree.mod;
+ sip += vip._tree.mod;
+ som += vom._tree.mod;
+ sop += vop._tree.mod;
+ }
+ if (vim && !d3_layout_treeRight(vop)) {
+ vop._tree.thread = vim;
+ vop._tree.mod += sim - sop;
+ }
+ if (vip && !d3_layout_treeLeft(vom)) {
+ vom._tree.thread = vip;
+ vom._tree.mod += sip - som;
+ ancestor = node;
+ }
}
- if (f && !(a = f(a, n++))) continue;
- rows.push(a);
+ return ancestor;
}
- return rows;
- };
- dsv.format = 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");
- d3.geo = {};
- d3.geo.stream = function(object, listener) {
- if (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 (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) {
- var coordinate = object.coordinates;
- listener.point(coordinate[0], coordinate[1]);
- },
- MultiPoint: function(object, listener) {
- var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate;
- while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
- },
- 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);
+ d3_layout_treeVisitAfter(root, function(node, previousSibling) {
+ node._tree = {
+ ancestor: node,
+ prelim: 0,
+ mod: 0,
+ change: 0,
+ shift: 0,
+ number: previousSibling ? previousSibling._tree.number + 1 : 0
+ };
+ });
+ firstWalk(root);
+ secondWalk(root, -root._tree.prelim);
+ var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
+ d3_layout_treeVisitAfter(root, function(node) {
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
+ node.y = node.depth / y1 * size[1];
+ delete node._tree;
+ });
+ return nodes;
}
+ tree.separation = function(x) {
+ if (!arguments.length) return separation;
+ separation = x;
+ return tree;
+ };
+ tree.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return tree;
+ };
+ return d3_layout_hierarchyRebind(tree, hierarchy);
};
- 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]);
- 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();
- }
- function d3_geo_spherical(cartesian) {
- return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ];
- }
- function d3_geo_sphericalEqual(a, b) {
- return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;
+ function d3_layout_treeSeparation(a, b) {
+ return a.parent == b.parent ? 1 : 2;
}
- function d3_geo_cartesian(spherical) {
- var λ = spherical[0], Ï = spherical[1], cosÏ = Math.cos(Ï);
- return [ cosÏ * Math.cos(λ), cosÏ * Math.sin(λ), Math.sin(Ï) ];
+ function d3_layout_treeLeft(node) {
+ var children = node.children;
+ return children && children.length ? children[0] : node._tree.thread;
}
- function d3_geo_cartesianDot(a, b) {
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ function d3_layout_treeRight(node) {
+ var children = node.children, n;
+ return children && (n = children.length) ? children[n - 1] : node._tree.thread;
}
- 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_layout_treeSearch(node, compare) {
+ var children = node.children;
+ if (children && (n = children.length)) {
+ var child, n, i = -1;
+ while (++i < n) {
+ if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
+ node = child;
+ }
+ }
+ }
+ return node;
}
- function d3_geo_cartesianAdd(a, b) {
- a[0] += b[0];
- a[1] += b[1];
- a[2] += b[2];
+ function d3_layout_treeRightmost(a, b) {
+ return a.x - b.x;
}
- function d3_geo_cartesianScale(vector, k) {
- return [ vector[0] * k, vector[1] * k, vector[2] * k ];
+ function d3_layout_treeLeftmost(a, b) {
+ return b.x - a.x;
}
- 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_layout_treeDeepest(a, b) {
+ return a.depth - b.depth;
}
- function d3_geo_resample(project) {
- var ÎŽ2 = .5, maxDepth = 16;
- function resample(stream) {
- var λ0, x0, y0, a0, b0, c0;
- var resample = {
- point: point,
- lineStart: lineStart,
- lineEnd: lineEnd,
- polygonStart: function() {
- stream.polygonStart();
- resample.lineStart = polygonLineStart;
- },
- 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 polygonLineStart() {
- var λ00, Ï00, x00, y00, a00, b00, c00;
- lineStart();
- resample.point = function(λ, Ï) {
- linePoint(λ00 = λ, Ï00 = Ï), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
- resample.point = linePoint;
- };
- resample.lineEnd = function() {
- 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 = Math.abs(Math.abs(c) - 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 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) {
- 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);
+ function d3_layout_treeVisitAfter(node, callback) {
+ function visit(node, previousSibling) {
+ var children = node.children;
+ if (children && (n = children.length)) {
+ var child, previousChild = null, i = -1, n;
+ while (++i < n) {
+ child = children[i];
+ visit(child, previousChild);
+ previousChild = child;
}
}
+ callback(node, previousSibling);
}
- resample.precision = function(_) {
- if (!arguments.length) return Math.sqrt(ÎŽ2);
- maxDepth = (ÎŽ2 = _ * _) > 0 && 16;
- return resample;
- };
- return resample;
+ visit(node, null);
}
- d3.geo.albersUsa = function() {
- var lower48 = d3.geo.albers();
- var alaska = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 60 ]).parallels([ 55, 65 ]);
- var hawaii = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 20 ]).parallels([ 8, 18 ]);
- var puertoRico = d3.geo.albers().rotate([ 60, 0 ]).center([ 0, 10 ]).parallels([ 8, 18 ]);
- function albersUsa(coordinates) {
- return projection(coordinates)(coordinates);
- }
- function projection(point) {
- var lon = point[0], lat = point[1];
- return lat > 50 ? alaska : lon < -140 ? hawaii : lat < 21 ? puertoRico : lower48;
- }
- albersUsa.scale = function(x) {
- if (!arguments.length) return lower48.scale();
- lower48.scale(x);
- alaska.scale(x * .6);
- hawaii.scale(x);
- puertoRico.scale(x * 1.5);
- return albersUsa.translate(lower48.translate());
- };
- albersUsa.translate = function(x) {
- if (!arguments.length) return lower48.translate();
- var dz = lower48.scale(), dx = x[0], dy = x[1];
- lower48.translate(x);
- alaska.translate([ dx - .4 * dz, dy + .17 * dz ]);
- hawaii.translate([ dx - .19 * dz, dy + .2 * dz ]);
- puertoRico.translate([ dx + .58 * dz, dy + .43 * dz ]);
- return albersUsa;
- };
- return albersUsa.scale(lower48.scale());
- };
- function d3_geo_albers(Ï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 albers(λ, Ï) {
- var Ï = Math.sqrt(C - 2 * n * Math.sin(Ï)) / n;
- return [ Ï * Math.sin(λ *= n), Ï0 - Ï * Math.cos(λ) ];
+ function d3_layout_treeShift(node) {
+ var shift = 0, change = 0, children = node.children, i = children.length, child;
+ while (--i >= 0) {
+ child = children[i]._tree;
+ child.prelim += shift;
+ child.mod += shift;
+ shift += child.shift + (change += child.change);
}
- albers.invert = function(x, y) {
- var Ï0_y = Ï0 - y;
- return [ Math.atan2(x, Ï0_y) / n, Math.asin((C - (x * x + Ï0_y * Ï0_y) * n * n) / (2 * n)) ];
- };
- return albers;
}
- (d3.geo.albers = function() {
- var Ï0 = 29.5 * d3_radians, Ï1 = 45.5 * d3_radians, m = d3_geo_projectionMutator(d3_geo_albers), p = m(Ï0, Ï1);
- p.parallels = function(_) {
- if (!arguments.length) return [ Ï0 * d3_degrees, Ï1 * d3_degrees ];
- return m(Ï0 = _[0] * d3_radians, Ï1 = _[1] * d3_radians);
- };
- return p.rotate([ 98, 0 ]).center([ 0, 38 ]).scale(1e3);
- }).raw = d3_geo_albers;
- 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;
- d3.geo.bounds = d3_geo_bounds(d3_identity);
- function d3_geo_bounds(projectStream) {
- var x0, y0, x1, y1;
- var bound = {
- point: boundPoint,
- lineStart: d3_noop,
- lineEnd: d3_noop,
- polygonStart: function() {
- bound.lineEnd = boundPolygonLineEnd;
- },
- polygonEnd: function() {
- bound.point = boundPoint;
+ function d3_layout_treeMove(ancestor, node, shift) {
+ ancestor = ancestor._tree;
+ node = node._tree;
+ var change = shift / (node.number - ancestor.number);
+ ancestor.change += change;
+ node.change -= change;
+ node.shift += shift;
+ node.prelim += shift;
+ node.mod += shift;
+ }
+ function d3_layout_treeAncestor(vim, node, ancestor) {
+ return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
+ }
+ d3.layout.pack = function() {
+ var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ];
+ function pack(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0];
+ root.x = 0;
+ root.y = 0;
+ d3_layout_treeVisitAfter(root, function(d) {
+ d.r = Math.sqrt(d.value);
+ });
+ d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+ var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h);
+ if (padding > 0) {
+ var dr = padding * k / 2;
+ d3_layout_treeVisitAfter(root, function(d) {
+ d.r += dr;
+ });
+ d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+ d3_layout_treeVisitAfter(root, function(d) {
+ d.r -= dr;
+ });
+ k = Math.max(2 * root.r / w, 2 * root.r / h);
}
- };
- function boundPoint(x, y) {
- if (x < x0) x0 = x;
- if (x > x1) x1 = x;
- if (y < y0) y0 = y;
- if (y > y1) y1 = y;
- }
- function boundPolygonLineEnd() {
- bound.point = bound.lineEnd = d3_noop;
+ d3_layout_packTransform(root, w / 2, h / 2, 1 / k);
+ return nodes;
}
- return function(feature) {
- y1 = x1 = -(x0 = y0 = Infinity);
- d3.geo.stream(feature, projectStream(bound));
- return [ [ x0, y0 ], [ x1, y1 ] ];
+ pack.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ 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;
}
- d3.geo.centroid = function(object) {
- d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- d3.geo.stream(object, d3_geo_centroid);
- var m;
- if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) {
- return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ];
+ 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 dr * dr - dx * dx - dy * dy > .001;
+ }
+ 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);
}
- };
- var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ;
- var d3_geo_centroid = {
- sphere: function() {
- if (d3_geo_centroidDimension < 2) {
- d3_geo_centroidDimension = 2;
- d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- }
- },
- point: d3_geo_centroidPoint,
- lineStart: d3_geo_centroidLineStart,
- lineEnd: d3_geo_centroidLineEnd,
- polygonStart: function() {
- if (d3_geo_centroidDimension < 2) {
- d3_geo_centroidDimension = 2;
- d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ 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);
+ }
+ }
}
- d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
- },
- polygonEnd: function() {
- d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
}
- };
- function d3_geo_centroidPoint(λ, Ï) {
- if (d3_geo_centroidDimension) return;
- ++d3_geo_centroidW;
- λ *= d3_radians;
- var cosÏ = Math.cos(Ï *= d3_radians);
- d3_geo_centroidX += (cosÏ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW;
- d3_geo_centroidY += (cosÏ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW;
- d3_geo_centroidZ += (Math.sin(Ï) - d3_geo_centroidZ) / d3_geo_centroidW;
+ 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_geo_centroidRingStart() {
- var λ00, Ï00;
- d3_geo_centroidDimension = 1;
- d3_geo_centroidLineStart();
- d3_geo_centroidDimension = 2;
- var linePoint = d3_geo_centroid.point;
- d3_geo_centroid.point = function(λ, Ï) {
- linePoint(λ00 = λ, Ï00 = Ï);
- };
- d3_geo_centroid.lineEnd = function() {
- d3_geo_centroid.point(λ00, Ï00);
- d3_geo_centroidLineEnd();
- d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
- };
+ function d3_layout_packLink(node) {
+ node._pack_next = node._pack_prev = node;
}
- function d3_geo_centroidLineStart() {
- var x0, y0, z0;
- if (d3_geo_centroidDimension > 1) return;
- if (d3_geo_centroidDimension < 1) {
- d3_geo_centroidDimension = 1;
- d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- }
- 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;
- };
- 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_centroidW += w;
- d3_geo_centroidX += w * (x0 + (x0 = x));
- d3_geo_centroidY += w * (y0 + (y0 = y));
- d3_geo_centroidZ += w * (z0 + (z0 = z));
+ 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_geo_centroidLineEnd() {
- d3_geo_centroid.point = d3_geo_centroidPoint;
+ 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.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;
+ d3.layout.cluster = function() {
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
+ function cluster(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
+ d3_layout_treeVisitAfter(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;
}
});
- return {
- type: "Polygon",
- coordinates: [ ring ]
- };
+ 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_treeVisitAfter(root, 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;
}
- 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;
+ cluster.separation = function(x) {
+ if (!arguments.length) return separation;
+ separation = x;
+ return cluster;
};
- circle.precision = function(_) {
- if (!arguments.length) return precision;
- interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
- return circle;
+ cluster.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return cluster;
};
- return circle.angle(90);
+ return d3_layout_hierarchyRebind(cluster, hierarchy);
};
- function d3_geo_circleInterpolate(radians, precision) {
- var cr = Math.cos(radians), sr = Math.sin(radians);
- return function(from, to, direction, listener) {
- if (from != null) {
- from = d3_geo_circleAngle(cr, from);
- to = d3_geo_circleAngle(cr, to);
- if (direction > 0 ? from < to : from > to) from += direction * 2 * Ï;
- } else {
- from = radians + direction * 2 * Ï;
- to = radians;
- }
- var point;
- for (var step = direction * precision, 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_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_geo_circleAngle(cr, point) {
- var a = d3_geo_cartesian(point);
- a[0] -= cr;
- d3_geo_cartesianNormalize(a);
- var angle = Math.acos(Math.max(-1, Math.min(1, -a[1])));
- return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
+ function d3_layout_clusterRight(node) {
+ var children = node.children, n;
+ return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
}
- function d3_geo_clip(pointVisible, clipLine, interpolate) {
- return function(listener) {
- var line = clipLine(listener);
- var clip = {
- point: point,
- lineStart: lineStart,
- lineEnd: lineEnd,
- polygonStart: function() {
- clip.point = pointRing;
- clip.lineStart = ringStart;
- clip.lineEnd = ringEnd;
- invisible = false;
- invisibleArea = visibleArea = 0;
- segments = [];
- listener.polygonStart();
- },
- polygonEnd: function() {
- clip.point = point;
- clip.lineStart = lineStart;
- clip.lineEnd = lineEnd;
- segments = d3.merge(segments);
- if (segments.length) {
- d3_geo_clipPolygon(segments, interpolate, listener);
- } else if (visibleArea < -ε || invisible && invisibleArea < -ε) {
- listener.lineStart();
- interpolate(null, null, 1, listener);
- listener.lineEnd();
+ 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;
}
- listener.polygonEnd();
- segments = null;
- },
- sphere: function() {
- listener.polygonStart();
- listener.lineStart();
- interpolate(null, null, 1, listener);
- listener.lineEnd();
- listener.polygonEnd();
}
- };
- function point(λ, Ï) {
- if (pointVisible(λ, Ï)) listener.point(λ, Ï);
- }
- function pointLine(λ, Ï) {
- line.point(λ, Ï);
- }
- function lineStart() {
- clip.point = pointLine;
- line.lineStart();
- }
- function lineEnd() {
- clip.point = point;
- line.lineEnd();
+ if (row.length) {
+ position(row, u, rect, true);
+ row.length = row.area = 0;
+ }
+ children.forEach(squarify);
}
- var segments, visibleArea, invisibleArea, invisible;
- var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring;
- function pointRing(λ, Ï) {
- ringListener.point(λ, Ï);
- ring.push([ λ, Ï ]);
+ }
+ 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 ringStart() {
- ringListener.lineStart();
- ring = [];
+ }
+ 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;
}
- function ringEnd() {
- pointRing(ring[0][0], ring[0][1]);
- ringListener.lineEnd();
- var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
- if (!n) {
- invisible = true;
- invisibleArea += d3_geo_clipAreaRing(ring, -1);
- ring = null;
- return;
+ 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);
}
- ring = null;
- if (clean & 1) {
- segment = ringSegments[0];
- visibleArea += d3_geo_clipAreaRing(segment, 1);
- var n = segment.length - 1, i = -1, point;
- listener.lineStart();
- while (++i < n) listener.point((point = segment[i])[0], point[1]);
- listener.lineEnd();
- return;
+ 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);
}
- if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
- segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
+ o.z = false;
+ o.dy += rect.y + rect.dy - y;
+ rect.x += v;
+ rect.dx -= v;
}
- return clip;
+ }
+ 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_geo_clipPolygon(segments, interpolate, listener) {
- var subject = [], clip = [];
- segments.forEach(function(segment) {
- var n = segment.length;
- if (n <= 1) return;
- var p0 = segment[0], p1 = segment[n - 1], a = {
- point: p0,
- points: segment,
- other: null,
- visited: false,
- entry: true,
- subject: true
- }, b = {
- point: p0,
- points: [ p0 ],
- other: a,
- visited: false,
- entry: false,
- subject: false
+ 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);
};
- a.other = b;
- subject.push(a);
- clip.push(b);
- a = {
- point: p1,
- points: [ p1 ],
- other: null,
- visited: false,
- entry: false,
- subject: true
+ },
+ logNormal: function() {
+ var random = d3.random.normal.apply(d3, arguments);
+ return function() {
+ return Math.exp(random());
};
- b = {
- point: p1,
- points: [ p1 ],
- other: a,
- visited: false,
- entry: true,
- subject: false
+ },
+ irwinHall: function(m) {
+ return function() {
+ for (var s = 0, j = 0; j < m; j++) s += Math.random();
+ return s / m;
};
- a.other = b;
- subject.push(a);
- clip.push(b);
- });
- clip.sort(d3_geo_clipSort);
- d3_geo_clipLinkCircular(subject);
- d3_geo_clipLinkCircular(clip);
- if (!subject.length) return;
- var start = subject[0], current, points, point;
- while (1) {
- current = start;
- while (current.visited) if ((current = current.next) === start) return;
- points = current.points;
- listener.lineStart();
- do {
- current.visited = current.other.visited = true;
- if (current.entry) {
- if (current.subject) {
- for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);
- } else {
- interpolate(current.point, current.next.point, 1, listener);
- }
- current = current.next;
- } else {
- if (current.subject) {
- points = current.prev.points;
- for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]);
- } else {
- interpolate(current.point, current.prev.point, -1, listener);
- }
- current = current.prev;
- }
- current = current.other;
- points = current.points;
- } while (!current.visited);
- listener.lineEnd();
}
+ };
+ d3.scale = {};
+ function d3_scaleExtent(domain) {
+ var start = domain[0], stop = domain[domain.length - 1];
+ return start < stop ? [ start, stop ] : [ stop, start ];
}
- function d3_geo_clipLinkCircular(array) {
- if (!(n = array.length)) return;
- var n, i = 0, a = array[0], b;
- while (++i < n) {
- a.next = b = array[i];
- b.prev = a;
- a = b;
- }
- a.next = b = array[0];
- b.prev = a;
+ function d3_scaleRange(scale) {
+ return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
}
- function d3_geo_clipSort(a, b) {
- return ((a = a.point)[0] < 0 ? a[1] - Ï / 2 - ε : Ï / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - Ï / 2 - ε : Ï / 2 - b[1]);
+ 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_geo_clipSegmentLength1(segment) {
- return segment.length > 1;
+ 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;
+ }
+ if (nice = nice(x1 - x0)) {
+ domain[i0] = nice.floor(x0);
+ domain[i1] = nice.ceil(x1);
+ }
+ return domain;
}
- 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;
- }
+ 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));
};
}
- function d3_geo_clipAreaRing(ring, invisible) {
- if (!(n = ring.length)) return 0;
- var n, i = 0, area = 0, p = ring[0], λ = p[0], Ï = p[1], cosÏ = Math.cos(Ï), x0 = Math.atan2(invisible * Math.sin(λ) * cosÏ, Math.sin(Ï)), y0 = 1 - invisible * Math.cos(λ) * cosÏ, x1 = x0, x, y;
- while (++i < n) {
- p = ring[i];
- cosÏ = Math.cos(Ï = p[1]);
- x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosÏ, Math.sin(Ï));
- y = 1 - invisible * Math.cos(λ) * cosÏ;
- if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue;
- if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - Ï) < ε) {
- if (y + y0 > 2) area += 4 * (x - x0);
- } else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * Ï + x - x0) % (2 * Ï) - Ï) * (y0 + y);
- x1 = x0, x0 = x, y0 = y;
+ 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;
}
- return area;
+ 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() {
+ d3_scale_nice(domain, d3_scale_linearNice);
+ return rescale();
+ };
+ scale.copy = function() {
+ return d3_scale_linear(domain, range, interpolate, clamp);
+ };
+ return rescale();
}
- var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate);
- 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λ = Math.abs(λ1 - λ0);
- if (Math.abs(dλ - Ï) < ε) {
- listener.point(λ0, Ï0 = (Ï0 + Ï1) / 2 > 0 ? Ï / 2 : -Ï / 2);
- 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 (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
- if (Math.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;
+ function d3_scale_linearRebind(scale, linear) {
+ return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
+ }
+ function d3_scale_linearNice(dx) {
+ dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
+ return dx && {
+ floor: function(x) {
+ return Math.floor(x / dx) * dx;
},
- clean: function() {
- return 2 - clean;
+ ceil: function(x) {
+ return Math.ceil(x / dx) * dx;
}
};
}
- function d3_geo_clipAntimeridianIntersect(λ0, Ï0, λ1, Ï1) {
- var cosÏ0, cosÏ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
- return Math.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_scale_linearTickRange(domain, m) {
+ 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_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
- var Ï;
- if (from == null) {
- Ï = direction * Ï / 2;
- listener.point(-Ï, Ï);
- listener.point(0, Ï);
- listener.point(Ï, Ï);
- listener.point(Ï, 0);
- listener.point(Ï, -Ï);
- listener.point(0, -Ï);
- listener.point(-Ï, -Ï);
- listener.point(-Ï, 0);
- listener.point(-Ï, Ï);
- } else if (Math.abs(from[0] - to[0]) > ε) {
- var s = (from[0] < to[0] ? 1 : -1) * Ï;
- Ï = direction * s / 2;
- listener.point(-s, Ï);
- listener.point(0, Ï);
- listener.point(s, Ï);
- } else {
- listener.point(to[0], to[1]);
- }
+ function d3_scale_linearTicks(domain, m) {
+ return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
}
- function d3_geo_clipCircle(degrees) {
- var radians = degrees * d3_radians, cr = Math.cos(radians), interpolate = d3_geo_circleInterpolate(radians, 6 * d3_radians);
- return d3_geo_clip(visible, clipLine, interpolate);
- function visible(λ, Ï) {
- return Math.cos(λ) * Math.cos(Ï) > cr;
+ function d3_scale_linearTickFormat(domain, m, format) {
+ var precision = -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01);
+ return d3.format(format ? format.replace(d3_format_re, function(a, b, c, d, e, f, g, h, i, j) {
+ return [ b, c, d, e, f, g, h, i || "." + (precision - (j === "%") * 2), j ].join("");
+ }) : ",." + precision + "f");
+ }
+ d3.scale.log = function() {
+ return d3_scale_log(d3.scale.linear().domain([ 0, Math.LN10 ]), 10, d3_scale_logp, d3_scale_powp, [ 1, 10 ]);
+ };
+ function d3_scale_log(linear, base, log, pow, domain) {
+ function scale(x) {
+ return linear(log(x));
}
- function clipLine(listener) {
- var point0, v0, v00, clean;
- return {
- lineStart: function() {
- v00 = v0 = false;
- clean = 1;
- },
- point: function(λ, Ï) {
- var point1 = [ λ, Ï ], point2, v = visible(λ, Ï);
- 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 (v0 = 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;
- }
- if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) listener.point(point1[0], point1[1]);
- point0 = point1;
- },
- lineEnd: function() {
- if (v0) listener.lineEnd();
- point0 = null;
+ scale.invert = function(x) {
+ return pow(linear.invert(x));
+ };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ if (x[0] < 0) log = d3_scale_logn, pow = d3_scale_pown; else log = d3_scale_logp,
+ pow = d3_scale_powp;
+ linear.domain((domain = x.map(Number)).map(log));
+ return scale;
+ };
+ scale.base = function(_) {
+ if (!arguments.length) return base;
+ base = +_;
+ return scale;
+ };
+ scale.nice = function() {
+ linear.domain(d3_scale_nice(domain, nice).map(log));
+ return scale;
+ };
+ scale.ticks = function() {
+ var extent = d3_scaleExtent(linear.domain()), ticks = [];
+ if (extent.every(isFinite)) {
+ var b = Math.log(base), i = Math.floor(extent[0] / b), j = Math.ceil(extent[1] / b), u = pow(extent[0]), v = pow(extent[1]), n = base % 1 ? 2 : base;
+ if (log === d3_scale_logn) {
+ ticks.push(-Math.pow(base, -i));
+ for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(-Math.pow(base, -i) * k);
+ } else {
+ for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(Math.pow(base, i) * k);
+ ticks.push(Math.pow(base, i));
+ }
+ 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 < 2) format = d3_scale_logFormat;
+ if (!arguments.length) return format;
+ var b = Math.log(base), k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12,
+ Math.floor) : (e = 1e-12, Math.ceil), e;
+ return function(d) {
+ return d / pow(b * f(log(d) / b + e)) <= k ? format(d) : "";
+ };
+ };
+ scale.copy = function() {
+ return d3_scale_log(linear.copy(), base, log, pow, domain);
+ };
+ function nice() {
+ return log === d3_scale_logp ? {
+ floor: floor,
+ ceil: ceil
+ } : {
+ floor: function(x) {
+ return -ceil(-x);
},
- clean: function() {
- return clean | (v00 && v0) << 1;
+ ceil: function(x) {
+ return -floor(-x);
}
};
}
- function intersect(a, b) {
- var pa = d3_geo_cartesian(a, 0), pb = d3_geo_cartesian(b, 0);
- 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 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), t = Math.sqrt(w * w - uu * (d3_geo_cartesianDot(A, A) - 1)), q = d3_geo_cartesianScale(u, (-w - t) / uu);
- d3_geo_cartesianAdd(q, A);
- return d3_geo_spherical(q);
+ function floor(x) {
+ return Math.pow(base, Math.floor(Math.log(x) / Math.log(base)));
}
- }
- function d3_geo_compose(a, b) {
- function compose(x, y) {
- return x = a(x, y), b(x[0], x[1]);
+ function ceil(x) {
+ return Math.pow(base, Math.ceil(Math.log(x) / Math.log(base)));
}
- 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;
+ return d3_scale_linearRebind(scale, linear);
}
- function d3_geo_equirectangular(λ, Ï) {
- return [ λ, Ï ];
+ var d3_scale_logFormat = d3.format(".0e");
+ function d3_scale_logp(x) {
+ return Math.log(x < 0 ? 0 : x);
}
- (d3.geo.equirectangular = function() {
- return d3_geo_projection(d3_geo_equirectangular).scale(250 / Ï);
- }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
- 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;
- d3.geo.graticule = function() {
- var x1, x0, y1, y0, dx = 22.5, dy = dx, 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));
+ function d3_scale_powp(x) {
+ return Math.exp(x);
+ }
+ function d3_scale_logn(x) {
+ return -Math.log(x > 0 ? 0 : -x);
+ }
+ function d3_scale_pown(x) {
+ return -Math.exp(-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));
}
- graticule.lines = function() {
- return lines().map(function(coordinates) {
- return {
- type: "LineString",
- coordinates: coordinates
- };
- });
+ scale.invert = function(x) {
+ return powb(linear.invert(x));
};
- graticule.outline = function() {
- return {
- type: "Polygon",
- coordinates: [ x(x0).concat(y(y1).slice(1), x(x1).reverse().slice(1), y(y0).reverse().slice(1)) ]
- };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ linear.domain((domain = x.map(Number)).map(powp));
+ return scale;
};
- graticule.extent = 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);
+ scale.ticks = function(m) {
+ return d3_scale_linearTicks(domain, m);
};
- graticule.step = function(_) {
- if (!arguments.length) return [ dx, dy ];
- dx = +_[0], dy = +_[1];
- return graticule;
+ scale.tickFormat = function(m, format) {
+ return d3_scale_linearTickFormat(domain, m, format);
};
- graticule.precision = function(_) {
- if (!arguments.length) return precision;
- precision = +_;
- x = d3_geo_graticuleX(y0, y1, precision);
- y = d3_geo_graticuleY(x0, x1, precision);
- return graticule;
+ scale.nice = function() {
+ return scale.domain(d3_scale_nice(domain, d3_scale_linearNice));
};
- return graticule.extent([ [ -180 + ε, -90 + ε ], [ 180 - ε, 90 - ε ] ]);
- };
- function d3_geo_graticuleX(y0, y1, dy) {
- var y = d3.range(y0, y1 - ε, dy).concat(y1);
+ 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 y.map(function(y) {
- return [ x, y ];
- });
+ return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
};
}
- 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 ];
+ 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) || index.set(x, domain.push(x))) - 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 = (stop - start) / (Math.max(1, domain.length - 1) + padding);
+ range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
+ rangeBand = 0;
+ ranger = {
+ t: "rangePoints",
+ 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;
};
- }
- 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 = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))), k = 1 / Math.sin(d);
- function interpolate(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_radians, Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians ];
- }
- interpolate.distance = d;
- return interpolate;
- }
- d3.geo.greatArc = function() {
- var source = d3_source, source_, target = d3_target, target_, precision = 6 * d3_radians, interpolate;
- function greatArc() {
- var p0 = source_ || source.apply(this, arguments), p1 = target_ || target.apply(this, arguments), i = interpolate || d3.geo.interpolate(p0, p1), t = 0, dt = precision / i.distance, coordinates = [ p0 ];
- while ((t += dt) < 1) coordinates.push(i(t));
- coordinates.push(p1);
- return {
- type: "LineString",
- coordinates: coordinates
+ 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)), error = stop - start - (domain.length - padding) * step;
+ range = steps(start + Math.round(error / 2), step);
+ if (reverse) range.reverse();
+ rangeBand = Math.round(step * (1 - padding));
+ ranger = {
+ t: "rangeRoundBands",
+ a: arguments
};
- }
- greatArc.distance = function() {
- return (interpolate || d3.geo.interpolate(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments))).distance;
+ return scale;
};
- greatArc.source = function(_) {
- if (!arguments.length) return source;
- source = _, source_ = typeof _ === "function" ? null : _;
- interpolate = source_ && target_ ? d3.geo.interpolate(source_, target_) : null;
- return greatArc;
+ scale.rangeBand = function() {
+ return rangeBand;
};
- greatArc.target = function(_) {
- if (!arguments.length) return target;
- target = _, target_ = typeof _ === "function" ? null : _;
- interpolate = source_ && target_ ? d3.geo.interpolate(source_, target_) : null;
- return greatArc;
+ scale.rangeExtent = function() {
+ return d3_scaleExtent(ranger.a[0]);
};
- greatArc.precision = function(_) {
- if (!arguments.length) return precision / d3_radians;
- precision = _ * d3_radians;
- return greatArc;
+ scale.copy = function() {
+ return d3_scale_ordinal(domain, ranger);
};
- return greatArc;
- };
- function d3_geo_mercator(λ, Ï) {
- return [ λ / (2 * Ï), Math.max(-.5, Math.min(+.5, Math.log(Math.tan(Ï / 4 + Ï / 2)) / (2 * Ï))) ];
+ return scale.domain(domain);
}
- d3_geo_mercator.invert = function(x, y) {
- return [ 2 * Ï * x, 2 * Math.atan(Math.exp(2 * Ï * y)) - Ï / 2 ];
+ d3.scale.category10 = function() {
+ return d3.scale.ordinal().range(d3_category10);
};
- (d3.geo.mercator = function() {
- return d3_geo_projection(d3_geo_mercator).scale(500);
- }).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;
- d3.geo.path = function() {
- var pointRadius = 4.5, projection, context, projectStream, contextStream;
- function path(object) {
- if (object) d3.geo.stream(object, projectStream(contextStream.pointRadius(typeof pointRadius === "function" ? +pointRadius.apply(this, arguments) : pointRadius)));
- return contextStream.result();
+ 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 = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ];
+ var d3_category20 = [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5" ];
+ var d3_category20b = [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" ];
+ var d3_category20c = [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9" ];
+ 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;
}
- 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_centroidDimension = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
- return d3_geo_centroidZ ? [ d3_geo_centroidX / d3_geo_centroidZ, d3_geo_centroidY / d3_geo_centroidZ ] : undefined;
- };
- path.bounds = function(object) {
- return d3_geo_bounds(projectStream)(object);
- };
- path.projection = function(_) {
- if (!arguments.length) return projection;
- projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
- return path;
- };
- path.context = function(_) {
- if (!arguments.length) return context;
- contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
- return path;
+ function scale(x) {
+ if (isNaN(x = +x)) return NaN;
+ return range[d3.bisect(thresholds, x)];
+ }
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.filter(function(d) {
+ return !isNaN(d);
+ }).sort(d3.ascending);
+ return rescale();
};
- path.pointRadius = function(_) {
- if (!arguments.length) return pointRadius;
- pointRadius = typeof _ === "function" ? _ : +_;
- return path;
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
};
- return path.projection(d3.geo.albersUsa()).context(null);
- };
- function d3_geo_pathCircle(radius) {
- return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + +2 * radius + "z";
- }
- function d3_geo_pathProjectStream(project) {
- var resample = d3_geo_resample(function(λ, Ï) {
- return project([ λ * d3_degrees, Ï * d3_degrees ]);
- });
- return function(stream) {
- stream = resample(stream);
- return {
- point: function(λ, Ï) {
- stream.point(λ * d3_radians, Ï * d3_radians);
- },
- sphere: function() {
- stream.sphere();
- },
- lineStart: function() {
- stream.lineStart();
- },
- lineEnd: function() {
- stream.lineEnd();
- },
- polygonStart: function() {
- stream.polygonStart();
- },
- polygonEnd: function() {
- stream.polygonEnd();
- }
- };
+ scale.quantiles = function() {
+ return thresholds;
};
- }
- function d3_geo_pathBuffer() {
- var pointCircle = d3_geo_pathCircle(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_pathCircle(_);
- return stream;
- },
- result: function() {
- if (buffer.length) {
- var result = buffer.join("");
- buffer = [];
- return result;
- }
- }
+ scale.copy = function() {
+ return d3_scale_quantile(domain, range);
};
- 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;
+ return rescale();
}
- 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, y);
- context.arc(x, y, pointRadius, 0, 2 * Ï);
- }
- 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();
+ 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))))];
}
- return stream;
- }
- 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 += Math.abs(d3_geo_pathAreaPolygon / 2);
+ function rescale() {
+ kx = range.length / (x1 - x0);
+ i = range.length - 1;
+ return scale;
}
- };
- 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;
+ scale.domain = function(x) {
+ if (!arguments.length) return [ x0, x1 ];
+ x0 = +x[0];
+ x1 = +x[x.length - 1];
+ return rescale();
};
- function nextPoint(x, y) {
- d3_geo_pathAreaPolygon += y0 * x - x0 * y;
- x0 = x, y0 = y;
- }
- d3_geo_pathArea.lineEnd = function() {
- nextPoint(x00, y00);
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
+ };
+ scale.copy = function() {
+ return d3_scale_quantize(x0, x1, range);
};
+ return rescale();
}
- 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;
- }
+ d3.scale.threshold = function() {
+ return d3_scale_threshold([ .5 ], [ 0, 1 ]);
};
- function d3_geo_pathCentroidPoint(x, y) {
- if (d3_geo_centroidDimension) return;
- d3_geo_centroidX += x;
- d3_geo_centroidY += y;
- ++d3_geo_centroidZ;
+ function d3_scale_threshold(domain, range) {
+ function scale(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.copy = function() {
+ return d3_scale_threshold(domain, range);
+ };
+ return scale;
}
- function d3_geo_pathCentroidLineStart() {
- var x0, y0;
- if (d3_geo_centroidDimension !== 1) {
- if (d3_geo_centroidDimension < 1) {
- d3_geo_centroidDimension = 1;
- d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- } else return;
+ d3.scale.identity = function() {
+ return d3_scale_identity([ 0, 1 ]);
+ };
+ function d3_scale_identity(domain) {
+ function identity(x) {
+ return +x;
}
- d3_geo_pathCentroid.point = function(x, y) {
- d3_geo_pathCentroid.point = nextPoint;
- x0 = x, y0 = y;
+ identity.invert = identity;
+ identity.domain = identity.range = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.map(identity);
+ return identity;
};
- function nextPoint(x, y) {
- var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
- d3_geo_centroidX += z * (x0 + x) / 2;
- d3_geo_centroidY += z * (y0 + y) / 2;
- d3_geo_centroidZ += z;
- x0 = x, y0 = y;
+ 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.arc = function() {
+ var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+ function arc() {
+ var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0,
+ a0 = a1, a1 = da), a1 - a0), df = da < Ï ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
+ return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
}
+ 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.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.centroid = function() {
+ var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
+ return [ Math.cos(a) * r, Math.sin(a) * r ];
+ };
+ return arc;
+ };
+ var d3_svg_arcOffset = -Ï / 2, d3_svg_arcMax = 2 * Ï - 1e-6;
+ function d3_svg_arcInnerRadius(d) {
+ return d.innerRadius;
}
- function d3_geo_pathCentroidLineEnd() {
- d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+ function d3_svg_arcOuterRadius(d) {
+ return d.outerRadius;
}
- function d3_geo_pathCentroidRingStart() {
- var x00, y00, x0, y0;
- if (d3_geo_centroidDimension < 2) {
- d3_geo_centroidDimension = 2;
- d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ function d3_svg_arcStartAngle(d) {
+ return d.startAngle;
+ }
+ function d3_svg_arcEndAngle(d) {
+ return d.endAngle;
+ }
+ 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] + d3_svg_arcOffset;
+ point[0] = r * Math.cos(a);
+ point[1] = r * Math.sin(a);
}
- d3_geo_pathCentroid.point = function(x, y) {
- d3_geo_pathCentroid.point = nextPoint;
- x00 = x0 = x, y00 = y0 = y;
- };
- function nextPoint(x, y) {
- var z = y0 * x - x0 * y;
- d3_geo_centroidX += z * (x0 + x);
- d3_geo_centroidY += z * (y0 + y);
- d3_geo_centroidZ += z * 3;
- x0 = x, y0 = y;
+ return points;
+ }
+ function d3_svg_area(projection) {
+ var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, 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;
}
- d3_geo_pathCentroid.lineEnd = function() {
- nextPoint(x00, y00);
+ 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.geo.area = function(object) {
- d3_geo_areaSum = 0;
- d3.geo.stream(object, d3_geo_area);
- return d3_geo_areaSum;
+ d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
+ d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
+ d3.svg.area = function() {
+ return d3_svg_area(d3_identity);
};
- var d3_geo_areaSum, d3_geo_areaRingU, d3_geo_areaRingV;
- var d3_geo_area = {
- sphere: function() {
- d3_geo_areaSum += 4 * Ï;
- },
- point: d3_noop,
- lineStart: d3_noop,
- lineEnd: d3_noop,
- polygonStart: function() {
- d3_geo_areaRingU = 1, d3_geo_areaRingV = 0;
- d3_geo_area.lineStart = d3_geo_areaRingStart;
- },
- polygonEnd: function() {
- var area = 2 * Math.atan2(d3_geo_areaRingV, d3_geo_areaRingU);
- d3_geo_areaSum += area < 0 ? 4 * Ï + area : area;
- d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
- }
+ 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;
};
- 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, cosÏ = Math.cos(Ï), sinÏ = Math.sin(Ï), k = sinÏ0 * sinÏ, u0 = d3_geo_areaRingU, v0 = d3_geo_areaRingV, u = cosÏ0 * cosÏ + k * Math.cos(dλ), v = k * Math.sin(dλ);
- d3_geo_areaRingU = u0 * u - v0 * v;
- d3_geo_areaRingV = v0 * u + u0 * v;
- λ0 = λ, cosÏ0 = cosÏ, sinÏ0 = sinÏ;
+ 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";
}
- d3_geo_area.lineEnd = function() {
- nextPoint(λ00, Ï00);
- };
- }
- 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, clip = d3_geo_clipAntimeridian, clipAngle = null;
- function projection(point) {
- point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
- return [ point[0] * k + ÎŽx, ÎŽy - point[1] * k ];
+ 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) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
+ 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 invert(point) {
- point = projectRotate.invert((point[0] - ÎŽx) / k, (ÎŽy - point[1]) / k);
- return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
+ function equals(a, b) {
+ return a.a0 == b.a0 && a.a1 == b.a1;
}
- projection.stream = function(stream) {
- return d3_geo_projectionRadiansRotate(rotate, clip(projectResample(stream)));
- };
- projection.clipAngle = function(_) {
- if (!arguments.length) return clipAngle;
- clip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle(clipAngle = +_);
- return projection;
+ 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;
};
- projection.scale = function(_) {
- if (!arguments.length) return k;
- k = +_;
- return reset();
+ chord.source = function(v) {
+ if (!arguments.length) return source;
+ source = d3_functor(v);
+ return chord;
};
- projection.translate = function(_) {
- if (!arguments.length) return [ x, y ];
- x = +_[0];
- y = +_[1];
- return reset();
+ chord.target = function(v) {
+ if (!arguments.length) return target;
+ target = d3_functor(v);
+ return chord;
};
- projection.center = function(_) {
- if (!arguments.length) return [ λ * d3_degrees, Ï * d3_degrees ];
- λ = _[0] % 360 * d3_radians;
- Ï = _[1] % 360 * d3_radians;
- return reset();
+ chord.startAngle = function(v) {
+ if (!arguments.length) return startAngle;
+ startAngle = d3_functor(v);
+ return chord;
};
- 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();
+ chord.endAngle = function(v) {
+ if (!arguments.length) return endAngle;
+ endAngle = d3_functor(v);
+ return chord;
};
- 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 projection;
+ 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];
}
- return function() {
- project = projectAt.apply(this, arguments);
- projection.invert = project.invert && invert;
- return reset();
+ diagonal.source = function(x) {
+ if (!arguments.length) return source;
+ source = d3_functor(x);
+ return diagonal;
};
- }
- function d3_geo_projectionRadiansRotate(rotate, stream) {
- return {
- point: function(x, y) {
- y = rotate(x * d3_radians, y * d3_radians), x = y[0];
- stream.point(x > Ï ? x - 2 * Ï : x < -Ï ? x + 2 * Ï : x, y[1]);
- },
- sphere: function() {
- stream.sphere();
- },
- lineStart: function() {
- stream.lineStart();
- },
- lineEnd: function() {
- stream.lineEnd();
- },
- polygonStart: function() {
- stream.polygonStart();
- },
- polygonEnd: function() {
- stream.polygonEnd();
- }
+ diagonal.target = function(x) {
+ if (!arguments.length) return target;
+ target = d3_functor(x);
+ return diagonal;
};
- }
- function d3_geo_rotation(Ύλ, ÎŽÏ, Ύγ) {
- return Ύλ ? ÎŽÏ || Ύγ ? d3_geo_compose(d3_geo_rotationλ(Ύλ), d3_geo_rotationÏγ(ÎŽÏ, Ύγ)) : d3_geo_rotationλ(Ύλ) : ÎŽÏ || Ύγ ? d3_geo_rotationÏγ(ÎŽÏ, Ύγ) : d3_geo_equirectangular;
- }
- function d3_geo_forwardRotationλ(Ύλ) {
- return function(λ, Ï) {
- return λ += Ύλ, [ λ > Ï ? λ - 2 * Ï : λ < -Ï ? λ + 2 * Ï : λ, Ï ];
+ 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 ];
}
- 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ÎŽÏ), Math.asin(Math.max(-1, Math.min(1, 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ÎŽÏ), Math.asin(Math.max(-1, Math.min(1, k * cosÎŽÏ - x * sinÎŽÏ))) ];
+ 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] + d3_svg_arcOffset;
+ return [ r * Math.cos(a), r * Math.sin(a) ];
};
- return rotation;
}
- 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_azimuthal(scale, angle) {
- function azimuthal(λ, Ï) {
- var cosλ = Math.cos(λ), cosÏ = Math.cos(Ï), k = scale(cosλ * cosÏ);
- return [ k * cosÏ * Math.sin(λ), k * Math.sin(Ï) ];
+ 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));
}
- 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 / Ï) ];
+ symbol.type = function(x) {
+ if (!arguments.length) return type;
+ type = d3_functor(x);
+ return symbol;
};
- return azimuthal;
+ symbol.size = function(x) {
+ if (!arguments.length) return size;
+ size = d3_functor(x);
+ return symbol;
+ };
+ return symbol;
+ };
+ function d3_svg_symbolSize() {
+ return 64;
}
- d3.geom = {};
- d3.geom.hull = function(vertices) {
- if (vertices.length < 3) return [];
- var len = vertices.length, plen = len - 1, points = [], stack = [], i, j, h = 0, x1, y1, x2, y2, u, v, a, sp;
- for (i = 1; i < len; ++i) {
- if (vertices[i][1] < vertices[h][1]) {
- h = i;
- } else if (vertices[i][1] == vertices[h][1]) {
- h = vertices[i][0] < vertices[h][0] ? i : h;
- }
- }
- for (i = 0; i < len; ++i) {
- if (i === h) continue;
- y1 = vertices[i][1] - vertices[h][1];
- x1 = vertices[i][0] - vertices[h][0];
- points.push({
- angle: Math.atan2(y1, x1),
- index: i
- });
+ 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";
}
- points.sort(function(a, b) {
- return a.angle - b.angle;
- });
- a = points[0].angle;
- v = points[0].index;
- u = 0;
- for (i = 1; i < plen; ++i) {
- j = points[i].index;
- if (a == points[i].angle) {
- x1 = vertices[v][0] - vertices[h][0];
- y1 = vertices[v][1] - vertices[h][1];
- x2 = vertices[j][0] - vertices[h][0];
- y2 = vertices[j][1] - vertices[h][1];
- if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) {
- points[i].index = -1;
+ });
+ d3.svg.symbolTypes = d3_svg_symbols.keys();
+ var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
+ function d3_transition(groups, id) {
+ d3_arraySubclass(groups, d3_transitionPrototype);
+ groups.id = id;
+ return groups;
+ }
+ var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit = {
+ ease: d3_ease_cubicInOut,
+ delay: 0,
+ duration: 250
+ };
+ d3_transitionPrototype.call = d3_selectionPrototype.call;
+ d3_transitionPrototype.empty = d3_selectionPrototype.empty;
+ d3_transitionPrototype.node = d3_selectionPrototype.node;
+ d3.transition = function(selection) {
+ return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
+ };
+ d3.transition.prototype = d3_transitionPrototype;
+ d3_transitionPrototype.select = function(selector) {
+ var id = this.id, subgroups = [], subgroup, subnode, node;
+ if (typeof selector !== "function") 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))) {
+ if ("__data__" in node) subnode.__data__ = node.__data__;
+ d3_transitionNode(subnode, i, id, node.__transition__[id]);
+ subgroup.push(subnode);
} else {
- points[u].index = -1;
- a = points[i].angle;
- u = i;
- v = j;
+ subgroup.push(null);
}
- } else {
- a = points[i].angle;
- u = i;
- v = j;
}
}
- stack.push(h);
- for (i = 0, j = 0; i < 2; ++j) {
- if (points[j].index !== -1) {
- stack.push(points[j].index);
- i++;
+ return d3_transition(subgroups, id);
+ };
+ d3_transitionPrototype.selectAll = function(selector) {
+ var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
+ if (typeof selector !== "function") 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.__transition__[id];
+ subnodes = selector.call(node, node.__data__, i);
+ subgroups.push(subgroup = []);
+ for (var k = -1, o = subnodes.length; ++k < o; ) {
+ d3_transitionNode(subnode = subnodes[k], k, id, transition);
+ subgroup.push(subnode);
+ }
+ }
}
}
- sp = stack.length;
- for (;j < plen; ++j) {
- if (points[j].index === -1) continue;
- while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) {
- --sp;
+ return d3_transition(subgroups, 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)) {
+ subgroup.push(node);
+ }
}
- stack[sp++] = points[j].index;
- }
- var poly = [];
- for (i = 0; i < sp; ++i) {
- poly.push(vertices[stack[i]]);
}
- return poly;
+ return d3_transition(subgroups, this.id, this.time).ease(this.ease());
};
- function d3_geom_hullCCW(i1, i2, i3, v) {
- var t, a, b, c, d, e, f;
- t = v[i1];
- a = t[0];
- b = t[1];
- t = v[i2];
- c = t[0];
- d = t[1];
- t = v[i3];
- e = t[0];
- f = t[1];
- return (f - b) * (c - a) - (d - b) * (e - a) > 0;
+ d3_transitionPrototype.tween = function(name, tween) {
+ var id = this.id;
+ if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
+ return d3_selection_each(this, tween == null ? function(node) {
+ node.__transition__[id].tween.remove(name);
+ } : function(node) {
+ node.__transition__[id].tween.set(name, tween);
+ });
+ };
+ function d3_transition_tween(groups, name, value, tween) {
+ var id = groups.id;
+ return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
+ node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
+ } : (value = tween(value), function(node) {
+ node.__transition__[id].tween.set(name, value);
+ }));
}
- d3.geom.polygon = function(coordinates) {
- coordinates.area = function() {
- var i = 0, n = coordinates.length, area = coordinates[n - 1][1] * coordinates[0][0] - coordinates[n - 1][0] * coordinates[0][1];
- while (++i < n) {
- area += coordinates[i - 1][1] * coordinates[i][0] - coordinates[i - 1][0] * coordinates[i][1];
- }
- return area * .5;
- };
- coordinates.centroid = function(k) {
- var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c;
- if (!arguments.length) k = -1 / (6 * coordinates.area());
- while (++i < n) {
- a = b;
- b = coordinates[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 ];
- };
- coordinates.clip = function(subject) {
- var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d;
- while (++i < n) {
- input = subject.slice();
- subject.length = 0;
- b = coordinates[i];
- c = input[(m = input.length) - 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;
- }
- a = b;
+ d3_transitionPrototype.attr = function(nameNS, value) {
+ if (arguments.length < 2) {
+ for (value in nameNS) this.attr(value, nameNS[value]);
+ return this;
+ }
+ var interpolate = d3_interpolateByName(nameNS), 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;
}
- return subject;
- };
- return coordinates;
+ priority = "";
+ }
+ var interpolate = d3_interpolateByName(name);
+ 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 = interpolate(a, b), function(t) {
+ this.style.setProperty(name, i(t), priority);
+ });
+ });
+ }
+ return d3_transition_tween(this, "style." + name, value, styleString);
};
- 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 ];
+ 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.geom.voronoi = function(vertices) {
- var polygons = vertices.map(function() {
- return [];
- }), Z = 1e6;
- d3_voronoi_tessellate(vertices, function(e) {
- var s1, s2, x1, x2, y1, y2;
- if (e.a === 1 && e.b >= 0) {
- s1 = e.ep.r;
- s2 = e.ep.l;
- } else {
- s1 = e.ep.l;
- s2 = e.ep.r;
- }
- if (e.a === 1) {
- y1 = s1 ? s1.y : -Z;
- x1 = e.c - e.b * y1;
- y2 = s2 ? s2.y : Z;
- x2 = e.c - e.b * y2;
- } else {
- x1 = s1 ? s1.x : -Z;
- y1 = e.c - e.a * x1;
- x2 = s2 ? s2.x : Z;
- y2 = e.c - e.a * x2;
- }
- var v1 = [ x1, y1 ], v2 = [ x2, y2 ];
- polygons[e.region.l.index].push(v1, v2);
- polygons[e.region.r.index].push(v1, v2);
+ d3_transitionPrototype.remove = function() {
+ return this.each("end.transition", function() {
+ var p;
+ if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);
+ });
+ };
+ d3_transitionPrototype.ease = function(value) {
+ var id = this.id;
+ if (arguments.length < 1) return this.node().__transition__[id].ease;
+ if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
+ return d3_selection_each(this, function(node) {
+ node.__transition__[id].ease = value;
});
- polygons = polygons.map(function(polygon, i) {
- var cx = vertices[i][0], cy = vertices[i][1], angle = polygon.map(function(v) {
- return Math.atan2(v[0] - cx, v[1] - cy);
- }), order = d3.range(polygon.length).sort(function(a, b) {
- return angle[a] - angle[b];
+ };
+ d3_transitionPrototype.delay = function(value) {
+ var id = this.id;
+ return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+ node.__transition__[id].delay = value.call(node, node.__data__, i, j) | 0;
+ } : (value |= 0, function(node) {
+ node.__transition__[id].delay = value;
+ }));
+ };
+ d3_transitionPrototype.duration = function(value) {
+ var id = this.id;
+ return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+ node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j) | 0);
+ } : (value = Math.max(1, value | 0), function(node) {
+ node.__transition__[id].duration = value;
+ }));
+ };
+ d3_transitionPrototype.each = function(type, listener) {
+ var id = this.id;
+ if (arguments.length < 2) {
+ var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
+ d3_transitionInheritId = id;
+ d3_selection_each(this, function(node, i, j) {
+ d3_transitionInherit = node.__transition__[id];
+ type.call(node, node.__data__, i, j);
});
- return order.filter(function(d, i) {
- return !i || angle[d] - angle[order[i - 1]] > ε;
- }).map(function(d) {
- return polygon[d];
+ d3_transitionInherit = inherit;
+ d3_transitionInheritId = inheritId;
+ } else {
+ d3_selection_each(this, function(node) {
+ node.__transition__[id].event.on(type, listener);
});
- });
- polygons.forEach(function(polygon, i) {
- var n = polygon.length;
- if (!n) return polygon.push([ -Z, -Z ], [ -Z, Z ], [ Z, Z ], [ Z, -Z ]);
- if (n > 2) return;
- var p0 = vertices[i], p1 = polygon[0], p2 = polygon[1], x0 = p0[0], y0 = p0[1], x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1], dx = Math.abs(x2 - x1), dy = y2 - y1;
- if (Math.abs(dy) < ε) {
- var y = y0 < y1 ? -Z : Z;
- polygon.push([ -Z, y ], [ Z, y ]);
- } else if (dx < ε) {
- var x = x0 < x1 ? -Z : Z;
- polygon.push([ x, -Z ], [ x, Z ]);
- } else {
- var y = (x2 - x1) * (y1 - y0) < (x1 - x0) * (y2 - y1) ? Z : -Z, z = Math.abs(dy) - dx;
- if (Math.abs(z) < ε) {
- polygon.push([ dy < 0 ? y : -y, y ]);
- } else {
- if (z > 0) y *= -1;
- polygon.push([ -Z, y ], [ Z, y ]);
+ }
+ return this;
+ };
+ d3_transitionPrototype.transition = function() {
+ var id0 = this.id, id1 = ++d3_transitionId, 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 = Object.create(node.__transition__[id0]);
+ transition.delay += transition.duration;
+ d3_transitionNode(node, i, id1, transition);
}
+ subgroup.push(node);
}
- });
- return polygons;
- };
- var d3_voronoi_opposite = {
- l: "r",
- r: "l"
+ }
+ return d3_transition(subgroups, id1);
};
- function d3_voronoi_tessellate(vertices, callback) {
- var Sites = {
- list: vertices.map(function(v, i) {
- return {
- index: i,
- x: v[0],
- y: v[1]
- };
- }).sort(function(a, b) {
- return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0;
- }),
- bottomSite: null
- };
- var EdgeList = {
- list: [],
- leftEnd: null,
- rightEnd: null,
- init: function() {
- EdgeList.leftEnd = EdgeList.createHalfEdge(null, "l");
- EdgeList.rightEnd = EdgeList.createHalfEdge(null, "l");
- EdgeList.leftEnd.r = EdgeList.rightEnd;
- EdgeList.rightEnd.l = EdgeList.leftEnd;
- EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd);
- },
- createHalfEdge: function(edge, side) {
- return {
- edge: edge,
- side: side,
- vertex: null,
- l: null,
- r: null
- };
- },
- insert: function(lb, he) {
- he.l = lb;
- he.r = lb.r;
- lb.r.l = he;
- lb.r = he;
- },
- leftBound: function(p) {
- var he = EdgeList.leftEnd;
- do {
- he = he.r;
- } while (he != EdgeList.rightEnd && Geom.rightOf(he, p));
- he = he.l;
- return he;
- },
- del: function(he) {
- he.l.r = he.r;
- he.r.l = he.l;
- he.edge = null;
- },
- right: function(he) {
- return he.r;
- },
- left: function(he) {
- return he.l;
- },
- leftRegion: function(he) {
- return he.edge == null ? Sites.bottomSite : he.edge.region[he.side];
- },
- rightRegion: function(he) {
- return he.edge == null ? Sites.bottomSite : he.edge.region[d3_voronoi_opposite[he.side]];
- }
- };
- var Geom = {
- bisect: function(s1, s2) {
- var newEdge = {
- region: {
- l: s1,
- r: s2
- },
- ep: {
- l: null,
- r: null
+ function d3_transitionNode(node, i, id, inherit) {
+ var lock = node.__transition__ || (node.__transition__ = {
+ active: 0,
+ count: 0
+ }), transition = lock[id];
+ if (!transition) {
+ var time = inherit.time;
+ transition = lock[id] = {
+ tween: new d3_Map(),
+ event: d3.dispatch("start", "end"),
+ time: time,
+ ease: inherit.ease,
+ delay: inherit.delay,
+ duration: inherit.duration
+ };
+ ++lock.count;
+ d3.timer(function(elapsed) {
+ var d = node.__data__, ease = transition.ease, event = transition.event, delay = transition.delay, duration = transition.duration, tweened = [];
+ return delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time), 1;
+ function start(elapsed) {
+ if (lock.active > id) return stop();
+ lock.active = id;
+ event.start.call(node, d, i);
+ transition.tween.forEach(function(key, value) {
+ if (value = value.call(node, d, i)) {
+ tweened.push(value);
+ }
+ });
+ if (!tick(elapsed)) d3.timer(tick, 0, time);
+ return 1;
+ }
+ function tick(elapsed) {
+ if (lock.active !== id) return stop();
+ var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length;
+ while (n > 0) {
+ tweened[--n].call(node, e);
+ }
+ if (t >= 1) {
+ stop();
+ event.end.call(node, d, i);
+ return 1;
+ }
+ }
+ function stop() {
+ if (--lock.count) delete lock[id]; else delete node.__transition__;
+ return 1;
+ }
+ }, 0, time);
+ return transition;
+ }
+ }
+ d3.svg.axis = function() {
+ var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0;
+ function axis(g) {
+ g.each(function() {
+ var g = d3.select(this);
+ var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_;
+ var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(".tick.minor").data(subticks, String), subtickEnter = subtick.enter().insert("line", ".tick").attr("class", "tick minor").style("opacity", 1e-6), subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style("opacity", 1);
+ var tick = g.selectAll(".tick.major").data(ticks, String), tickEnter = tick.enter().insert("g", "path").attr("class", "tick major").style("opacity", 1e-6), tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform;
+ var range = d3_scaleRange(scale), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"),
+ d3.transition(path));
+ var scale1 = scale.copy(), scale0 = this.__chart__ || scale1;
+ this.__chart__ = scale1;
+ 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");
+ switch (orient) {
+ case "bottom":
+ {
+ tickTransform = d3_svg_axisX;
+ subtickEnter.attr("y2", tickMinorSize);
+ subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize);
+ lineEnter.attr("y2", tickMajorSize);
+ textEnter.attr("y", Math.max(tickMajorSize, 0) + tickPadding);
+ lineUpdate.attr("x2", 0).attr("y2", tickMajorSize);
+ textUpdate.attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding);
+ text.attr("dy", ".71em").style("text-anchor", "middle");
+ pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize);
+ break;
+ }
+
+ case "top":
+ {
+ tickTransform = d3_svg_axisX;
+ subtickEnter.attr("y2", -tickMinorSize);
+ subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize);
+ lineEnter.attr("y2", -tickMajorSize);
+ textEnter.attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
+ lineUpdate.attr("x2", 0).attr("y2", -tickMajorSize);
+ textUpdate.attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
+ text.attr("dy", "0em").style("text-anchor", "middle");
+ pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize);
+ break;
+ }
+
+ case "left":
+ {
+ tickTransform = d3_svg_axisY;
+ subtickEnter.attr("x2", -tickMinorSize);
+ subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0);
+ lineEnter.attr("x2", -tickMajorSize);
+ textEnter.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding));
+ lineUpdate.attr("x2", -tickMajorSize).attr("y2", 0);
+ textUpdate.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0);
+ text.attr("dy", ".32em").style("text-anchor", "end");
+ pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize);
+ break;
+ }
+
+ case "right":
+ {
+ tickTransform = d3_svg_axisY;
+ subtickEnter.attr("x2", tickMinorSize);
+ subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0);
+ lineEnter.attr("x2", tickMajorSize);
+ textEnter.attr("x", Math.max(tickMajorSize, 0) + tickPadding);
+ lineUpdate.attr("x2", tickMajorSize).attr("y2", 0);
+ textUpdate.attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0);
+ text.attr("dy", ".32em").style("text-anchor", "start");
+ pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize);
+ break;
}
- };
- var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy;
- newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5;
- if (adx > ady) {
- newEdge.a = 1;
- newEdge.b = dy / dx;
- newEdge.c /= dx;
- } else {
- newEdge.b = 1;
- newEdge.a = dx / dy;
- newEdge.c /= dy;
- }
- return newEdge;
- },
- intersect: function(el1, el2) {
- var e1 = el1.edge, e2 = el2.edge;
- if (!e1 || !e2 || e1.region.r == e2.region.r) {
- return null;
- }
- var d = e1.a * e2.b - e1.b * e2.a;
- if (Math.abs(d) < 1e-10) {
- return null;
}
- var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e;
- if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) {
- el = el1;
- e = e1;
+ if (scale.ticks) {
+ tickEnter.call(tickTransform, scale0);
+ tickUpdate.call(tickTransform, scale1);
+ tickExit.call(tickTransform, scale1);
+ subtickEnter.call(tickTransform, scale0);
+ subtickUpdate.call(tickTransform, scale1);
+ subtickExit.call(tickTransform, scale1);
} else {
- el = el2;
- e = e2;
- }
- var rightOfSite = xint >= e.region.r.x;
- if (rightOfSite && el.side === "l" || !rightOfSite && el.side === "r") {
- return null;
- }
- return {
- x: xint,
- y: yint
- };
- },
- rightOf: function(he, p) {
- var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x;
- if (rightOfSite && he.side === "l") {
- return 1;
- }
- if (!rightOfSite && he.side === "r") {
- return 0;
+ var dx = scale1.rangeBand() / 2, x = function(d) {
+ return scale1(d) + dx;
+ };
+ tickEnter.call(tickTransform, x);
+ tickUpdate.call(tickTransform, x);
}
- if (e.a === 1) {
- var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0;
- if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) {
- above = fast = dyp >= e.b * dxp;
- } else {
- above = p.x + p.y * e.b > e.c;
- if (e.b < 0) {
- above = !above;
- }
- if (!above) {
- fast = 1;
- }
- }
- if (!fast) {
- var dxs = topsite.x - e.region.l.x;
- above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);
- if (e.b < 0) {
- above = !above;
- }
+ });
+ }
+ 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, y) {
+ if (!arguments.length) return tickMajorSize;
+ var n = arguments.length - 1;
+ tickMajorSize = +x;
+ tickMinorSize = n > 1 ? +y : tickMajorSize;
+ tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
+ return axis;
+ };
+ axis.tickPadding = function(x) {
+ if (!arguments.length) return tickPadding;
+ tickPadding = +x;
+ return axis;
+ };
+ axis.tickSubdivide = function(x) {
+ if (!arguments.length) return tickSubdivide;
+ tickSubdivide = +x;
+ return axis;
+ };
+ return axis;
+ };
+ var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
+ top: 1,
+ right: 1,
+ bottom: 1,
+ left: 1
+ };
+ function d3_svg_axisX(selection, x) {
+ selection.attr("transform", function(d) {
+ return "translate(" + x(d) + ",0)";
+ });
+ }
+ function d3_svg_axisY(selection, y) {
+ selection.attr("transform", function(d) {
+ return "translate(0," + y(d) + ")";
+ });
+ }
+ function d3_svg_axisSubdivide(scale, ticks, m) {
+ subticks = [];
+ if (m && ticks.length > 1) {
+ var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v;
+ while (++i < n) {
+ for (j = m; --j > 0; ) {
+ if ((v = +ticks[i] - j * d) >= extent[0]) {
+ subticks.push(v);
}
- } else {
- var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y;
- above = t1 * t1 > t2 * t2 + t3 * t3;
}
- return he.side === "l" ? above : !above;
- },
- endPoint: function(edge, side, site) {
- edge.ep[side] = site;
- if (!edge.ep[d3_voronoi_opposite[side]]) return;
- callback(edge);
- },
- distance: function(s, t) {
- var dx = s.x - t.x, dy = s.y - t.y;
- return Math.sqrt(dx * dx + dy * dy);
}
- };
- var EventQueue = {
- list: [],
- insert: function(he, site, offset) {
- he.vertex = site;
- he.ystar = site.y + offset;
- for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) {
- var next = list[i];
- if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) {
- continue;
- } else {
- break;
+ for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) {
+ subticks.push(v);
+ }
+ }
+ return subticks;
+ }
+ d3.svg.brush = function() {
+ var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain;
+ function brush(g) {
+ g.each(function() {
+ var g = d3.select(this), bg = g.selectAll(".background").data([ 0 ]), fg = g.selectAll(".extent").data([ 0 ]), tz = g.selectAll(".resize").data(resizes, String), e;
+ g.style("pointer-events", "all").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
+ bg.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
+ fg.enter().append("rect").attr("class", "extent").style("cursor", "move");
+ tz.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");
+ tz.style("display", brush.empty() ? "none" : null);
+ tz.exit().remove();
+ if (x) {
+ e = d3_scaleRange(x);
+ bg.attr("x", e[0]).attr("width", e[1] - e[0]);
+ redrawX(g);
+ }
+ if (y) {
+ e = d3_scaleRange(y);
+ bg.attr("y", e[0]).attr("height", e[1] - e[0]);
+ redrawY(g);
+ }
+ redraw(g);
+ });
+ }
+ function redraw(g) {
+ g.selectAll(".resize").attr("transform", function(d) {
+ return "translate(" + extent[+/e$/.test(d)][0] + "," + extent[+/^s/.test(d)][1] + ")";
+ });
+ }
+ function redrawX(g) {
+ g.select(".extent").attr("x", extent[0][0]);
+ g.selectAll(".extent,.n>rect,.s>rect").attr("width", extent[1][0] - extent[0][0]);
+ }
+ function redrawY(g) {
+ g.select(".extent").attr("y", extent[0][1]);
+ g.selectAll(".extent,.e>rect,.w>rect").attr("height", extent[1][1] - extent[0][1]);
+ }
+ 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"), center, origin = mouse(), offset;
+ var w = d3.select(d3_window).on("mousemove.brush", brushmove).on("mouseup.brush", brushend).on("touchmove.brush", brushmove).on("touchend.brush", brushend).on("keydown.brush", keydown).on("keyup.brush", keyup);
+ if (dragging) {
+ origin[0] = extent[0][0] - origin[0];
+ origin[1] = extent[0][1] - origin[1];
+ } else if (resizing) {
+ var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
+ offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ];
+ origin[0] = extent[ex][0];
+ origin[1] = extent[ey][1];
+ } 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();
+ d3_eventCancel();
+ function mouse() {
+ var touches = d3.event.changedTouches;
+ return touches ? d3.touches(target, touches)[0] : d3.mouse(target);
+ }
+ function keydown() {
+ if (d3.event.keyCode == 32) {
+ if (!dragging) {
+ center = null;
+ origin[0] -= extent[1][0];
+ origin[1] -= extent[1][1];
+ dragging = 2;
}
+ d3_eventCancel();
}
- list.splice(i, 0, he);
- },
- del: function(he) {
- for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {}
- ls.splice(i, 1);
- },
- empty: function() {
- return EventQueue.list.length === 0;
- },
- nextEvent: function(he) {
- for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) {
- if (ls[i] == he) return ls[i + 1];
- }
- return null;
- },
- min: function() {
- var elem = EventQueue.list[0];
- return {
- x: elem.vertex.x,
- y: elem.ystar
- };
- },
- extractMin: function() {
- return EventQueue.list.shift();
}
- };
- EdgeList.init();
- Sites.bottomSite = Sites.list.shift();
- var newSite = Sites.list.shift(), newIntStar;
- var lbnd, rbnd, llbnd, rrbnd, bisector;
- var bot, top, temp, p, v;
- var e, pm;
- while (true) {
- if (!EventQueue.empty()) {
- newIntStar = EventQueue.min();
+ function keyup() {
+ if (d3.event.keyCode == 32 && dragging == 2) {
+ origin[0] += extent[1][0];
+ origin[1] += extent[1][1];
+ dragging = 0;
+ d3_eventCancel();
+ }
}
- if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) {
- lbnd = EdgeList.leftBound(newSite);
- rbnd = EdgeList.right(lbnd);
- bot = EdgeList.rightRegion(lbnd);
- e = Geom.bisect(bot, newSite);
- bisector = EdgeList.createHalfEdge(e, "l");
- EdgeList.insert(lbnd, bisector);
- p = Geom.intersect(lbnd, bisector);
- if (p) {
- EventQueue.del(lbnd);
- EventQueue.insert(lbnd, p, Geom.distance(p, newSite));
+ function brushmove() {
+ var point = mouse(), moved = false;
+ if (offset) {
+ point[0] += offset[0];
+ point[1] += offset[1];
}
- lbnd = bisector;
- bisector = EdgeList.createHalfEdge(e, "r");
- EdgeList.insert(lbnd, bisector);
- p = Geom.intersect(bisector, rbnd);
- if (p) {
- EventQueue.insert(bisector, p, Geom.distance(p, newSite));
+ if (!dragging) {
+ if (d3.event.altKey) {
+ if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ];
+ origin[0] = extent[+(point[0] < center[0])][0];
+ origin[1] = extent[+(point[1] < center[1])][1];
+ } else center = null;
}
- newSite = Sites.list.shift();
- } else if (!EventQueue.empty()) {
- lbnd = EventQueue.extractMin();
- llbnd = EdgeList.left(lbnd);
- rbnd = EdgeList.right(lbnd);
- rrbnd = EdgeList.right(rbnd);
- bot = EdgeList.leftRegion(lbnd);
- top = EdgeList.rightRegion(rbnd);
- v = lbnd.vertex;
- Geom.endPoint(lbnd.edge, lbnd.side, v);
- Geom.endPoint(rbnd.edge, rbnd.side, v);
- EdgeList.del(lbnd);
- EventQueue.del(rbnd);
- EdgeList.del(rbnd);
- pm = "l";
- if (bot.y > top.y) {
- temp = bot;
- bot = top;
- top = temp;
- pm = "r";
+ if (resizingX && move1(point, x, 0)) {
+ redrawX(g);
+ moved = true;
}
- e = Geom.bisect(bot, top);
- bisector = EdgeList.createHalfEdge(e, pm);
- EdgeList.insert(llbnd, bisector);
- Geom.endPoint(e, d3_voronoi_opposite[pm], v);
- p = Geom.intersect(llbnd, bisector);
- if (p) {
- EventQueue.del(llbnd);
- EventQueue.insert(llbnd, p, Geom.distance(p, bot));
+ if (resizingY && move1(point, y, 1)) {
+ redrawY(g);
+ moved = true;
}
- p = Geom.intersect(bisector, rrbnd);
- if (p) {
- EventQueue.insert(bisector, p, Geom.distance(p, bot));
+ if (moved) {
+ redraw(g);
+ event_({
+ type: "brush",
+ mode: dragging ? "move" : "resize"
+ });
}
- } else {
- break;
- }
- }
- for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) {
- callback(lbnd.edge);
- }
- }
- d3.geom.delaunay = function(vertices) {
- var edges = vertices.map(function() {
- return [];
- }), triangles = [];
- d3_voronoi_tessellate(vertices, function(e) {
- edges[e.region.l.index].push(vertices[e.region.r.index]);
- });
- edges.forEach(function(edge, i) {
- var v = vertices[i], cx = v[0], cy = v[1];
- edge.forEach(function(v) {
- v.angle = Math.atan2(v[0] - cx, v[1] - cy);
- });
- edge.sort(function(a, b) {
- return a.angle - b.angle;
- });
- for (var j = 0, m = edge.length - 1; j < m; j++) {
- triangles.push([ v, edge[j], edge[j + 1] ]);
}
- });
- return triangles;
- };
- d3.geom.quadtree = function(points, x1, y1, x2, y2) {
- var p, i = -1, n = points.length;
- if (arguments.length < 5) {
- if (arguments.length === 3) {
- y2 = y1;
- x2 = x1;
- y1 = x1 = 0;
- } else {
- x1 = y1 = Infinity;
- x2 = y2 = -Infinity;
- while (++i < n) {
- p = points[i];
- if (p.x < x1) x1 = p.x;
- if (p.y < y1) y1 = p.y;
- if (p.x > x2) x2 = p.x;
- if (p.y > y2) y2 = p.y;
- }
- }
- }
- var dx = x2 - x1, dy = y2 - y1;
- if (dx > dy) y2 = y1 + dx; else x2 = x1 + dy;
- function insert(n, p, x1, y1, x2, y2) {
- if (isNaN(p.x) || isNaN(p.y)) return;
- if (n.leaf) {
- var v = n.point;
- if (v) {
- if (Math.abs(v.x - p.x) + Math.abs(v.y - p.y) < .01) {
- insertChild(n, p, x1, y1, x2, y2);
+ function move1(point, scale, i) {
+ var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max;
+ if (dragging) {
+ r0 -= position;
+ r1 -= size + position;
+ }
+ min = Math.max(r0, Math.min(r1, 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 {
- n.point = null;
- insertChild(n, v, x1, y1, x2, y2);
- insertChild(n, p, x1, y1, x2, y2);
+ max = position;
}
- } else {
- n.point = p;
}
- } else {
- insertChild(n, p, x1, y1, x2, y2);
+ if (extent[0][i] !== min || extent[1][i] !== max) {
+ extentDomain = null;
+ extent[0][i] = min;
+ extent[1][i] = 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);
+ event_({
+ type: "brushend"
+ });
+ d3_eventCancel();
}
}
- function insertChild(n, p, x1, y1, x2, y2) {
- var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = p.x >= sx, bottom = p.y >= sy, i = (bottom << 1) + right;
- n.leaf = false;
- n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
- if (right) x1 = sx; else x2 = sx;
- if (bottom) y1 = sy; else y2 = sy;
- insert(n, p, x1, y1, x2, y2);
- }
- var root = d3_geom_quadtreeNode();
- root.add = function(p) {
- insert(root, p, x1, y1, x2, y2);
+ brush.x = function(z) {
+ if (!arguments.length) return x;
+ x = z;
+ resizes = d3_svg_brushResizes[!x << 1 | !y];
+ return brush;
};
- root.visit = function(f) {
- d3_geom_quadtreeVisit(f, root, x1, y1, x2, y2);
+ brush.y = function(z) {
+ if (!arguments.length) return y;
+ y = z;
+ resizes = d3_svg_brushResizes[!x << 1 | !y];
+ return brush;
+ };
+ brush.extent = function(z) {
+ var x0, x1, y0, y1, t;
+ if (!arguments.length) {
+ z = extentDomain || extent;
+ if (x) {
+ x0 = z[0][0], x1 = z[1][0];
+ if (!extentDomain) {
+ x0 = extent[0][0], x1 = extent[1][0];
+ if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ }
+ }
+ if (y) {
+ y0 = z[0][1], y1 = z[1][1];
+ if (!extentDomain) {
+ y0 = extent[0][1], y1 = extent[1][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 ];
+ }
+ extentDomain = [ [ 0, 0 ], [ 0, 0 ] ];
+ if (x) {
+ x0 = z[0], x1 = z[1];
+ if (y) x0 = x0[0], x1 = x1[0];
+ extentDomain[0][0] = x0, extentDomain[1][0] = x1;
+ if (x.invert) x0 = x(x0), x1 = x(x1);
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ extent[0][0] = x0 | 0, extent[1][0] = x1 | 0;
+ }
+ if (y) {
+ y0 = z[0], y1 = z[1];
+ if (x) y0 = y0[1], y1 = y1[1];
+ extentDomain[0][1] = y0, extentDomain[1][1] = y1;
+ if (y.invert) y0 = y(y0), y1 = y(y1);
+ if (y1 < y0) t = y0, y0 = y1, y1 = t;
+ extent[0][1] = y0 | 0, extent[1][1] = y1 | 0;
+ }
+ return brush;
+ };
+ brush.clear = function() {
+ extentDomain = null;
+ extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0;
+ return brush;
+ };
+ brush.empty = function() {
+ return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][1];
};
- points.forEach(root.add);
- return root;
+ 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"
};
- function d3_geom_quadtreeNode() {
- return {
- leaf: true,
- nodes: [],
- point: 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);
- }
- }
+ var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
d3.time = {};
var d3_time = Date, d3_time_daySymbols = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
function d3_time_utc() {
@@ -7243,6 +8022,115 @@ d3 = function() {
var d3_time_prototype = Date.prototype;
var d3_time_formatDateTime = "%a %b %e %X %Y", d3_time_formatDate = "%m/%d/%Y", d3_time_formatTime = "%H:%M:%S";
var d3_time_days = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], d3_time_dayAbbreviations = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], d3_time_months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], d3_time_monthAbbreviations = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
+ 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_time(date - 1)), 1);
+ return date;
+ }
+ function offset(date, k) {
+ step(date = new d3_time(+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_time = d3_time_utc;
+ var utc = new d3_time_utc();
+ utc._ = t0;
+ return range(utc, t1, dt);
+ } finally {
+ d3_time = 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_time = d3_time_utc;
+ var utc = new d3_time_utc();
+ utc._ = date;
+ return method(utc, k)._;
+ } finally {
+ d3_time = 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_time(1970, 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);
+ };
+ d3_time_daySymbols.forEach(function(day, i) {
+ day = day.toLowerCase();
+ 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;
d3.time.format = function(template) {
var n = template.length;
function format(date) {
@@ -7510,7 +8398,7 @@ d3 = function() {
return format;
};
var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");
- d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso;
+ 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();
}
@@ -7519,66 +8407,6 @@ d3 = function() {
return isNaN(date) ? null : date;
};
d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
- 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_time(date - 1)), 1);
- return date;
- }
- function offset(date, k) {
- step(date = new d3_time(+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_time = d3_time_utc;
- var utc = new d3_time_utc();
- utc._ = t0;
- return range(utc, t1, dt);
- } finally {
- d3_time = 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_time = d3_time_utc;
- var utc = new d3_time_utc();
- utc._ = date;
- return method(utc, k)._;
- } finally {
- d3_time = Date;
- }
- };
- }
d3.time.second = d3_time_interval(function(date) {
return new d3_time(Math.floor(date / 1e3) * 1e3);
}, function(date, offset) {
@@ -7607,44 +8435,6 @@ d3 = function() {
});
d3.time.hours = d3.time.hour.range;
d3.time.hours.utc = d3.time.hour.utc.range;
- d3.time.day = d3_time_interval(function(date) {
- var day = new d3_time(1970, 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);
- };
- d3_time_daySymbols.forEach(function(day, i) {
- day = day.toLowerCase();
- 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;
d3.time.month = d3_time_interval(function(date) {
date = d3.time.day(date);
date.setDate(1);
@@ -7656,17 +8446,6 @@ d3 = function() {
});
d3.time.months = d3.time.month.range;
d3.time.months.utc = d3.time.month.utc.range;
- 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;
function d3_time_scale(linear, methods, format) {
function scale(x) {
return linear(x);
@@ -7685,7 +8464,7 @@ d3 = function() {
}));
};
scale.ticks = function(m, k) {
- var extent = d3_time_scaleExtent(scale.domain());
+ var extent = d3_scaleExtent(scale.domain());
if (typeof m !== "function") {
var span = extent[1] - extent[0], target = span / m, i = d3.bisect(d3_time_scaleSteps, target);
if (i == d3_time_scaleSteps.length) return methods.year(extent, m);
@@ -7703,11 +8482,7 @@ d3 = function() {
scale.copy = function() {
return d3_time_scale(linear.copy(), methods, format);
};
- return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
- }
- function d3_time_scaleExtent(domain) {
- var start = domain[0], stop = domain[domain.length - 1];
- return start < stop ? [ start, stop ] : [ stop, start ];
+ return d3_scale_linearRebind(scale, linear);
}
function d3_time_scaleDate(t) {
return new Date(t);
@@ -7786,5 +8561,25 @@ d3 = function() {
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;
+ });
return d3;
}();
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js
old mode 100644
new mode 100755
index 9b153cd..3ee7054
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js
@@ -1,4 +1,5 @@
-d3=function(){function t(t){return t.target}function n(t){return t.source}function e(t,n){try{for(var e in n)Object.defineProperty(t.prototype,e,{value:n[e],enumerable:!1})}catch(r){t.prototype=n}}function r(t){for(var n=-1,e=t.length,r=[];e>++n;)r.push(t[n]);return r}function u(t){return Array.prototype.slice.call(t)}function i(){}function a(t){return t}function o(){return!0}function c(t){return"function"==typeof t?t:function(){return t}}function l(t,n,e){return function(){var r=e.apply(n,arguments);return arguments.length?t:r}}function f(t){return null!=t&&!isNaN(t)}function s(t){return t.length}function h(t){return t.trim().replace(/\s+/g," ")}function g(t){for(var n=1;t*n%1;)n*=10;return n}function p(t){return 1===t.length?function(n,e){t(null==n?e:null)}:t}function d(t){return t.responseText}function m(t){return JSON.parse(t.responseText)}function v(t){var n=Di.createRange();return n.selectNode(Di.body),n.createContextualFragment(t.responseText)}function y(t){return t.r
esponseXML}function M(){}function b(t){function n(){for(var n,r=e,u=-1,i=r.length;i>++u;)(n=r[u].on)&&n.apply(this,arguments);return t}var e=[],r=new i;return n.on=function(n,u){var i,a=r.get(n);return 2>arguments.length?a&&a.on:(a&&(a.on=null,e=e.slice(0,i=e.indexOf(a)).concat(e.slice(i+1)),r.remove(n)),u&&e.push(r.set(n,{on:u})),t)},n}function x(t,n){return n-(t?Math.ceil(Math.log(t)/Math.LN10):1)}function _(t){return t+""}function w(t,n){var e=Math.pow(10,3*Math.abs(8-n));return{scale:n>8?function(t){return t/e}:function(t){return t*e},symbol:t}}function S(t){return function(n){return 0>=n?0:n>=1?1:t(n)}}function k(t){return function(n){return 1-t(1-n)}}function E(t){return function(n){return.5*(.5>n?t(2*n):2-t(2-2*n))}}function A(t){return t*t}function N(t){return t*t*t}function T(t){if(0>=t)return 0;if(t>=1)return 1;var n=t*t,e=n*t;return 4*(.5>t?e:3*(t-n)+e-.75)}function q(t){return function(n){return Math.pow(n,t)}}function C(t){return 1-Math.cos(t*Ni/2)}function z(t)
{return Math.pow(2,10*(t-1))}function D(t){return 1-Math.sqrt(1-t*t)}function L(t,n){var e;return 2>arguments.length&&(n=.45),arguments.length?e=n/(2*Ni)*Math.asin(1/t):(t=1,e=n/4),function(r){return 1+t*Math.pow(2,10*-r)*Math.sin(2*(r-e)*Ni/n)}}function F(t){return t||(t=1.70158),function(n){return n*n*((t+1)*n-t)}}function H(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}function j(){qi.event.stopPropagation(),qi.event.preventDefault()}function P(){for(var t,n=qi.event;t=n.sourceEvent;)n=t;return n}function R(t){for(var n=new M,e=0,r=arguments.length;r>++e;)n[arguments[e]]=b(n);return n.of=function(e,r){return function(u){try{var i=u.sourceEvent=qi.event;u.target=t,qi.event=u,n[u.type].apply(e,r)}finally{qi.event=i}}},n}function O(t){var n=[t.a,t.b],e=[t.c,t.d],r=U(n),u=Y(n,e),i=U(I(e,n,-u))||0;n[0]*e[1]<e[0]*n[1]&&(n[0]*=-1,n[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(n[1],n[0]
):Math.atan2(-e[0],e[1]))*zi,this.translate=[t.e,t.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*zi:0}function Y(t,n){return t[0]*n[0]+t[1]*n[1]}function U(t){var n=Math.sqrt(Y(t,t));return n&&(t[0]/=n,t[1]/=n),n}function I(t,n,e){return t[0]+=e*n[0],t[1]+=e*n[1],t}function V(t){return"transform"==t?qi.interpolateTransform:qi.interpolate}function X(t,n){return n=n-(t=+t)?1/(n-t):0,function(e){return(e-t)*n}}function Z(t,n){return n=n-(t=+t)?1/(n-t):0,function(e){return Math.max(0,Math.min(1,(e-t)*n))}}function B(){}function $(t,n,e){return new J(t,n,e)}function J(t,n,e){this.r=t,this.g=n,this.b=e}function G(t){return 16>t?"0"+Math.max(0,t).toString(16):Math.min(255,t).toString(16)}function K(t,n,e){var r,u,i,a=0,o=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(t))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 n(nn(u[0]),nn(u[1]),nn(u[2]))}return(i=aa.get(t))?n(i.r,i.g,i.b):(null!=t&&"#"===t.charAt(0)&&(4=
==t.length?(a=t.charAt(1),a+=a,o=t.charAt(2),o+=o,c=t.charAt(3),c+=c):7===t.length&&(a=t.substring(1,3),o=t.substring(3,5),c=t.substring(5,7)),a=parseInt(a,16),o=parseInt(o,16),c=parseInt(c,16)),n(a,o,c))}function W(t,n,e){var r,u,i=Math.min(t/=255,n/=255,e/=255),a=Math.max(t,n,e),o=a-i,c=(a+i)/2;return o?(u=.5>c?o/(a+i):o/(2-a-i),r=t==a?(n-e)/o+(e>n?6:0):n==a?(e-t)/o+2:(t-n)/o+4,r*=60):u=r=0,en(r,u,c)}function Q(t,n,e){t=tn(t),n=tn(n),e=tn(e);var r=pn((.4124564*t+.3575761*n+.1804375*e)/fa),u=pn((.2126729*t+.7151522*n+.072175*e)/sa),i=pn((.0193339*t+.119192*n+.9503041*e)/ha);return ln(116*u-16,500*(r-u),200*(u-i))}function tn(t){return.04045>=(t/=255)?t/12.92:Math.pow((t+.055)/1.055,2.4)}function nn(t){var n=parseFloat(t);return"%"===t.charAt(t.length-1)?Math.round(2.55*n):n}function en(t,n,e){return new rn(t,n,e)}function rn(t,n,e){this.h=t,this.s=n,this.l=e}function un(t,n,e){function r(t){return t>360?t-=360:0>t&&(t+=360),60>t?i+(a-i)*t/60:180>t?a:240>t?i+(a-i)*(240-t)/60
:i}function u(t){return Math.round(255*r(t))}var i,a;return t%=360,0>t&&(t+=360),n=0>n?0:n>1?1:n,e=0>e?0:e>1?1:e,a=.5>=e?e*(1+n):e+n-e*n,i=2*e-a,$(u(t+120),u(t),u(t-120))}function an(t,n,e){return new on(t,n,e)}function on(t,n,e){this.h=t,this.c=n,this.l=e}function cn(t,n,e){return ln(e,Math.cos(t*=Ci)*n,Math.sin(t)*n)}function ln(t,n,e){return new fn(t,n,e)}function fn(t,n,e){this.l=t,this.a=n,this.b=e}function sn(t,n,e){var r=(t+16)/116,u=r+n/500,i=r-e/200;return u=gn(u)*fa,r=gn(r)*sa,i=gn(i)*ha,$(dn(3.2404542*u-1.5371385*r-.4985314*i),dn(-.969266*u+1.8760108*r+.041556*i),dn(.0556434*u-.2040259*r+1.0572252*i))}function hn(t,n,e){return an(180*(Math.atan2(e,n)/Ni),Math.sqrt(n*n+e*e),t)}function gn(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function pn(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function dn(t){return Math.round(255*(.00304>=t?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}function mn(t){return Ii(t,Ma),t}function vn(t){return function(){return pa(t,this)
}}function yn(t){return function(){return da(t,this)}}function Mn(t,n){function e(){this.removeAttribute(t)}function r(){this.removeAttributeNS(t.space,t.local)}function u(){this.setAttribute(t,n)}function i(){this.setAttributeNS(t.space,t.local,n)}function a(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}function o(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}return t=qi.ns.qualify(t),null==n?t.local?r:e:"function"==typeof n?t.local?o:a:t.local?i:u}function bn(t){return RegExp("(?:^|\\s+)"+qi.requote(t)+"(?:\\s+|$)","g")}function xn(t,n){function e(){for(var e=-1;u>++e;)t[e](this,n)}function r(){for(var e=-1,r=n.apply(this,arguments);u>++e;)t[e](this,r)}t=t.trim().split(/\s+/).map(_n);var u=t.length;return"function"==typeof n?r:e}function _n(t){var n=bn(t);return function(e,r){if(u=e.classList)return r?u.add(t):u.remove(t);var u=e.className,i=null!=u.baseVal,a=i
?u.baseVal:u;r?(n.lastIndex=0,n.test(a)||(a=h(a+" "+t),i?u.baseVal=a:e.className=a)):a&&(a=h(a.replace(n," ")),i?u.baseVal=a:e.className=a)}}function wn(t,n,e){function r(){this.style.removeProperty(t)}function u(){this.style.setProperty(t,n,e)}function i(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}return null==n?r:"function"==typeof n?i:u}function Sn(t,n){function e(){delete this[t]}function r(){this[t]=n}function u(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}return null==n?e:"function"==typeof n?u:r}function kn(t){return{__data__:t}}function En(t){return function(){return ya(this,t)}}function An(t){return arguments.length||(t=qi.ascending),function(n,e){return!n-!e||t(n.__data__,e.__data__)}}function Nn(t,n,e){function r(){var n=this[i];n&&(this.removeEventListener(t,n,n.$),delete this[i])}function u(){function u(t){var e=qi.event;qi.event=t,o[0]=a.__data__;try{n.apply(a,o)}finally{qi.event=e}}var
a=this,o=Yi(arguments);r.call(this),this.addEventListener(t,this[i]=u,u.$=e),u._=n}var i="__on"+t,a=t.indexOf(".");return a>0&&(t=t.substring(0,a)),n?u:r}function Tn(t,n){for(var e=0,r=t.length;r>e;e++)for(var u,i=t[e],a=0,o=i.length;o>a;a++)(u=i[a])&&n(u,a,e);return t}function qn(t){return Ii(t,xa),t}function Cn(t,n){return Ii(t,wa),t.id=n,t}function zn(t,n,e,r){var u=t.__transition__||(t.__transition__={active:0,count:0}),a=u[e];if(!a){var o=r.time;return a=u[e]={tween:new i,event:qi.dispatch("start","end"),time:o,ease:r.ease,delay:r.delay,duration:r.duration},++u.count,qi.timer(function(r){function i(r){return u.active>e?l():(u.active=e,h.start.call(t,f,n),a.tween.forEach(function(e,r){(r=r.call(t,f,n))&&d.push(r)}),c(r)||qi.timer(c,0,o),1)}function c(r){if(u.active!==e)return l();for(var i=(r-g)/p,a=s(i),o=d.length;o>0;)d[--o].call(t,a);return i>=1?(l(),h.end.call(t,f,n),1):void 0}function l(){return--u.count?delete u[e]:delete t.__transition__,1}var f=t.__data__,s=a.eas
e,h=a.event,g=a.delay,p=a.duration,d=[];return r>=g?i(r):qi.timer(i,g,o),1},0,o),a}}function Dn(t){return null==t&&(t=""),function(){this.textContent=t}}function Ln(t,n,e,r){var u=t.id;return Tn(t,"function"==typeof e?function(t,i,a){t.__transition__[u].tween.set(n,r(e.call(t,t.__data__,i,a)))}:(e=r(e),function(t){t.__transition__[u].tween.set(n,e)}))}function Fn(){for(var t,n=Date.now(),e=qa;e;)t=n-e.then,t>=e.delay&&(e.flush=e.callback(t)),e=e.next;var r=Hn()-n;r>24?(isFinite(r)&&(clearTimeout(Aa),Aa=setTimeout(Fn,r)),Ea=0):(Ea=1,Ca(Fn))}function Hn(){for(var t=null,n=qa,e=1/0;n;)n.flush?(delete Ta[n.callback.id],n=t?t.next=n.next:qa=n.next):(e=Math.min(e,n.then+n.delay),n=(t=n).next);return e}function jn(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>za&&(Li.scrollX||Li.scrollY)){e=qi.select(Di.body).append("svg").style("position","absolute").style("top",0).style("left",0);var u=e[0][0].getScreenCTM();za=!(u.f||u.e),e.remove()}return za
?(r.x=n.pageX,r.y=n.pageY):(r.x=n.clientX,r.y=n.clientY),r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var i=t.getBoundingClientRect();return[n.clientX-i.left-t.clientLeft,n.clientY-i.top-t.clientTop]}function Pn(){}function Rn(t){var n=t[0],e=t[t.length-1];return e>n?[n,e]:[e,n]}function On(t){return t.rangeExtent?t.rangeExtent():Rn(t.range())}function Yn(t,n){var e,r=0,u=t.length-1,i=t[r],a=t[u];return i>a&&(e=r,r=u,u=e,e=i,i=a,a=e),(n=n(a-i))&&(t[r]=n.floor(i),t[u]=n.ceil(a)),t}function Un(){return Math}function In(t,n,e,r){function u(){var u=Math.min(t.length,n.length)>2?Gn:Jn,c=r?Z:X;return a=u(t,n,c,e),o=u(n,t,c,qi.interpolate),i}function i(t){return a(t)}var a,o;return i.invert=function(t){return o(t)},i.domain=function(n){return arguments.length?(t=n.map(Number),u()):t},i.range=function(t){return arguments.length?(n=t,u()):n},i.rangeRound=function(t){return i.range(t).interpolate(qi.interpolateRound)},i.clamp=function(t){return arguments.length?(r=t,u()):
r},i.interpolate=function(t){return arguments.length?(e=t,u()):e},i.ticks=function(n){return Bn(t,n)},i.tickFormat=function(n){return $n(t,n)},i.nice=function(){return Yn(t,Xn),u()},i.copy=function(){return In(t,n,e,r)},u()}function Vn(t,n){return qi.rebind(t,n,"range","rangeRound","interpolate","clamp")}function Xn(t){return t=Math.pow(10,Math.round(Math.log(t)/Math.LN10)-1),t&&{floor:function(n){return Math.floor(n/t)*t},ceil:function(n){return Math.ceil(n/t)*t}}}function Zn(t,n){var e=Rn(t),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/n)/Math.LN10)),i=n/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 Bn(t,n){return qi.range.apply(qi,Zn(t,n))}function $n(t,n){return qi.format(",."+Math.max(0,-Math.floor(Math.log(Zn(t,n)[2])/Math.LN10+.01))+"f")}function Jn(t,n,e,r){var u=e(t[0],t[1]),i=r(n[0],n[1]);return function(t){return i(u(t))}}function Gn(t,n,e,r){var u=[],i=[],a=0,o=Math.min(t.length,n.le
ngth)-1;for(t[o]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());o>=++a;)u.push(e(t[a-1],t[a])),i.push(r(n[a-1],n[a]));return function(n){var e=qi.bisect(t,n,1,o)-1;return i[e](u[e](n))}}function Kn(t,n){function e(e){return t(n(e))}var r=n.pow;return e.invert=function(n){return r(t.invert(n))},e.domain=function(u){return arguments.length?(n=0>u[0]?Qn:Wn,r=n.pow,t.domain(u.map(n)),e):t.domain().map(r)},e.nice=function(){return t.domain(Yn(t.domain(),Un)),e},e.ticks=function(){var e=Rn(t.domain()),u=[];if(e.every(isFinite)){var i=Math.floor(e[0]),a=Math.ceil(e[1]),o=r(e[0]),c=r(e[1]);if(n===Qn)for(u.push(r(i));a>i++;)for(var l=9;l>0;l--)u.push(r(i)*l);else{for(;a>i;i++)for(var l=1;10>l;l++)u.push(r(i)*l);u.push(r(i))}for(i=0;o>u[i];i++);for(a=u.length;u[a-1]>c;a--);u=u.slice(i,a)}return u},e.tickFormat=function(t,u){if(2>arguments.length&&(u=Da),!arguments.length)return u;var i,a=Math.max(.1,t/e.ticks().length),o=n===Qn?(i=-1e-12,Math.floor):(i=1e-12,Math.ceil);return fun
ction(t){return a>=t/r(o(n(t)+i))?u(t):""}},e.copy=function(){return Kn(t.copy(),n)},Vn(e,t)}function Wn(t){return Math.log(0>t?0:t)/Math.LN10}function Qn(t){return-Math.log(t>0?0:-t)/Math.LN10}function te(t,n){function e(n){return t(r(n))}var r=ne(n),u=ne(1/n);return e.invert=function(n){return u(t.invert(n))},e.domain=function(n){return arguments.length?(t.domain(n.map(r)),e):t.domain().map(u)},e.ticks=function(t){return Bn(e.domain(),t)},e.tickFormat=function(t){return $n(e.domain(),t)},e.nice=function(){return e.domain(Yn(e.domain(),Xn))},e.exponent=function(t){if(!arguments.length)return n;var i=e.domain();return r=ne(n=t),u=ne(1/n),e.domain(i)},e.copy=function(){return te(t.copy(),n)},Vn(e,t)}function ne(t){return function(n){return 0>n?-Math.pow(-n,t):Math.pow(n,t)}}function ee(t,n){function e(n){return a[((u.get(n)||u.set(n,t.push(n)))-1)%a.length]}function r(n,e){return qi.range(t.length).map(function(t){return n+e*t})}var u,a,o;return e.domain=function(r){if(!argum
ents.length)return t;t=[],u=new i;for(var a,o=-1,c=r.length;c>++o;)u.has(a=r[o])||u.set(a,t.push(a));return e[n.t].apply(e,n.a)},e.range=function(t){return arguments.length?(a=t,o=0,n={t:"range",a:arguments},e):a},e.rangePoints=function(u,i){2>arguments.length&&(i=0);var c=u[0],l=u[1],f=(l-c)/(Math.max(1,t.length-1)+i);return a=r(2>t.length?(c+l)/2:c+f*i/2,f),o=0,n={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){2>arguments.length&&(i=0),3>arguments.length&&(c=i);var l=u[1]<u[0],f=u[l-0],s=u[1-l],h=(s-f)/(t.length-i+2*c);return a=r(f+h*c,h),l&&a.reverse(),o=h*(1-i),n={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){2>arguments.length&&(i=0),3>arguments.length&&(c=i);var l=u[1]<u[0],f=u[l-0],s=u[1-l],h=Math.floor((s-f)/(t.length-i+2*c)),g=s-f-(t.length-i)*h;return a=r(f+Math.round(g/2),h),l&&a.reverse(),o=Math.round(h*(1-i)),n={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Rn(n.a[0])},e.copy
=function(){return ee(t,n)},e.domain(t)}function re(t,n){function e(){var e=0,i=n.length;for(u=[];i>++e;)u[e-1]=qi.quantile(t,e/i);return r}function r(t){return isNaN(t=+t)?0/0:n[qi.bisect(u,t)]}var u;return r.domain=function(n){return arguments.length?(t=n.filter(function(t){return!isNaN(t)}).sort(qi.ascending),e()):t},r.range=function(t){return arguments.length?(n=t,e()):n},r.quantiles=function(){return u},r.copy=function(){return re(t,n)},e()}function ue(t,n,e){function r(n){return e[Math.max(0,Math.min(a,Math.floor(i*(n-t))))]}function u(){return i=e.length/(n-t),a=e.length-1,r}var i,a;return r.domain=function(e){return arguments.length?(t=+e[0],n=+e[e.length-1],u()):[t,n]},r.range=function(t){return arguments.length?(e=t,u()):e},r.copy=function(){return ue(t,n,e)},u()}function ie(t,n){function e(e){return n[qi.bisect(t,e)]}return e.domain=function(n){return arguments.length?(t=n,e):t},e.range=function(t){return arguments.length?(n=t,e):n},e.copy=function(){return ie(t,n
)},e}function ae(t){function n(t){return+t}return n.invert=n,n.domain=n.range=function(e){return arguments.length?(t=e.map(n),n):t},n.ticks=function(n){return Bn(t,n)},n.tickFormat=function(n){return $n(t,n)},n.copy=function(){return ae(t)},n}function oe(t){return t.innerRadius}function ce(t){return t.outerRadius}function le(t){return t.startAngle}function fe(t){return t.endAngle}function se(t){function n(n){function a(){f.push("M",i(t(s),l))}for(var o,f=[],s=[],h=-1,g=n.length,p=c(e),d=c(r);g>++h;)u.call(this,o=n[h],h)?s.push([+p.call(this,o,h),+d.call(this,o,h)]):s.length&&(a(),s=[]);return s.length&&a(),f.length?f.join(""):null}var e=he,r=ge,u=o,i=pe,a=i.key,l=.7;return n.x=function(t){return arguments.length?(e=t,n):e},n.y=function(t){return arguments.length?(r=t,n):r},n.defined=function(t){return arguments.length?(u=t,n):u},n.interpolate=function(t){return arguments.length?(a="function"==typeof t?i=t:(i=Oa.get(t)||pe).key,n):a},n.tension=function(t){return arguments.len
gth?(l=t,n):l},n}function he(t){return t[0]}function ge(t){return t[1]}function pe(t){return t.join("L")}function de(t){return pe(t)+"Z"}function me(t){for(var n=0,e=t.length,r=t[0],u=[r[0],",",r[1]];e>++n;)u.push("V",(r=t[n])[1],"H",r[0]);return u.join("")}function ve(t){for(var n=0,e=t.length,r=t[0],u=[r[0],",",r[1]];e>++n;)u.push("H",(r=t[n])[0],"V",r[1]);return u.join("")}function ye(t,n){return 4>t.length?pe(t):t[1]+xe(t.slice(1,t.length-1),_e(t,n))}function Me(t,n){return 3>t.length?pe(t):t[0]+xe((t.push(t[0]),t),_e([t[t.length-2]].concat(t,[t[1]]),n))}function be(t,n){return 3>t.length?pe(t):t[0]+xe(t,_e(t,n))}function xe(t,n){if(1>n.length||t.length!=n.length&&t.length!=n.length+2)return pe(t);var e=t.length!=n.length,r="",u=t[0],i=t[1],a=n[0],o=a,c=1;if(e&&(r+="Q"+(i[0]-2*a[0]/3)+","+(i[1]-2*a[1]/3)+","+i[0]+","+i[1],u=t[1],c=2),n.length>1){o=n[1],i=t[c],c++,r+="C"+(u[0]+a[0])+","+(u[1]+a[1])+","+(i[0]-o[0])+","+(i[1]-o[1])+","+i[0]+","+i[1];for(var l=2;n.length>l;l
++,c++)i=t[c],o=n[l],r+="S"+(i[0]-o[0])+","+(i[1]-o[1])+","+i[0]+","+i[1]}if(e){var f=t[c];r+="Q"+(i[0]+2*o[0]/3)+","+(i[1]+2*o[1]/3)+","+f[0]+","+f[1]}return r}function _e(t,n){for(var e,r=[],u=(1-n)/2,i=t[0],a=t[1],o=1,c=t.length;c>++o;)e=i,i=a,a=t[o],r.push([u*(a[0]-e[0]),u*(a[1]-e[1])]);return r}function we(t){if(3>t.length)return pe(t);var n=1,e=t.length,r=t[0],u=r[0],i=r[1],a=[u,u,u,(r=t[1])[0]],o=[i,i,i,r[1]],c=[u,",",i];for(Ne(c,a,o);e>++n;)r=t[n],a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ne(c,a,o);for(n=-1;2>++n;)a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ne(c,a,o);return c.join("")}function Se(t){if(4>t.length)return pe(t);for(var n,e=[],r=-1,u=t.length,i=[0],a=[0];3>++r;)n=t[r],i.push(n[0]),a.push(n[1]);for(e.push(Ae(Ia,i)+","+Ae(Ia,a)),--r;u>++r;)n=t[r],i.shift(),i.push(n[0]),a.shift(),a.push(n[1]),Ne(e,i,a);return e.join("")}function ke(t){for(var n,e,r=-1,u=t.length,i=u+4,a=[],o=[];4>++r;)e=t[r%u],a.push(e[0]),o.push(e[1]);for(n=[Ae(Ia,a),",",Ae(Ia,o)],-
-r;i>++r;)e=t[r%u],a.shift(),a.push(e[0]),o.shift(),o.push(e[1]),Ne(n,a,o);return n.join("")}function Ee(t,n){var e=t.length-1;if(e)for(var r,u,i=t[0][0],a=t[0][1],o=t[e][0]-i,c=t[e][1]-a,l=-1;e>=++l;)r=t[l],u=l/e,r[0]=n*r[0]+(1-n)*(i+u*o),r[1]=n*r[1]+(1-n)*(a+u*c);return we(t)}function Ae(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function Ne(t,n,e){t.push("C",Ae(Ya,n),",",Ae(Ya,e),",",Ae(Ua,n),",",Ae(Ua,e),",",Ae(Ia,n),",",Ae(Ia,e))}function Te(t,n){return(n[1]-t[1])/(n[0]-t[0])}function qe(t){for(var n=0,e=t.length-1,r=[],u=t[0],i=t[1],a=r[0]=Te(u,i);e>++n;)r[n]=(a+(a=Te(u=i,i=t[n+1])))/2;return r[n]=a,r}function Ce(t){for(var n,e,r,u,i=[],a=qe(t),o=-1,c=t.length-1;c>++o;)n=Te(t[o],t[o+1]),1e-6>Math.abs(n)?a[o]=a[o+1]=0:(e=a[o]/n,r=a[o+1]/n,u=e*e+r*r,u>9&&(u=3*n/Math.sqrt(u),a[o]=u*e,a[o+1]=u*r));for(o=-1;c>=++o;)u=(t[Math.min(c,o+1)][0]-t[Math.max(0,o-1)][0])/(6*(1+a[o]*a[o])),i.push([u||0,a[o]*u||0]);return i}function ze(t){return 3>t.length?pe(t):t[0]+xe(t,Ce(
t))}function De(t){for(var n,e,r,u=-1,i=t.length;i>++u;)n=t[u],e=n[0],r=n[1]+Pa,n[0]=e*Math.cos(r),n[1]=e*Math.sin(r);return t}function Le(t){function n(n){function o(){m.push("M",l(t(y),g),h,s(t(v.reverse()),g),"Z")}for(var f,p,d,m=[],v=[],y=[],M=-1,b=n.length,x=c(e),_=c(u),w=e===r?function(){return p}:c(r),S=u===i?function(){return d}:c(i);b>++M;)a.call(this,f=n[M],M)?(v.push([p=+x.call(this,f,M),d=+_.call(this,f,M)]),y.push([+w.call(this,f,M),+S.call(this,f,M)])):v.length&&(o(),v=[],y=[]);return v.length&&o(),m.length?m.join(""):null}var e=he,r=he,u=0,i=ge,a=o,l=pe,f=l.key,s=l,h="L",g=.7;return n.x=function(t){return arguments.length?(e=r=t,n):r},n.x0=function(t){return arguments.length?(e=t,n):e},n.x1=function(t){return arguments.length?(r=t,n):r},n.y=function(t){return arguments.length?(u=i=t,n):i},n.y0=function(t){return arguments.length?(u=t,n):u},n.y1=function(t){return arguments.length?(i=t,n):i},n.defined=function(t){return arguments.length?(a=t,n):a},n.interpolate
=function(t){return arguments.length?(f="function"==typeof t?l=t:(l=Oa.get(t)||pe).key,s=l.reverse||l,h=l.closed?"M":"L",n):f},n.tension=function(t){return arguments.length?(g=t,n):g},n}function Fe(t){return t.radius}function He(t){return[t.x,t.y]}function je(t){return function(){var n=t.apply(this,arguments),e=n[0],r=n[1]+Pa;return[e*Math.cos(r),e*Math.sin(r)]}}function Pe(){return 64}function Re(){return"circle"}function Oe(t){var n=Math.sqrt(t/Ni);return"M0,"+n+"A"+n+","+n+" 0 1,1 0,"+-n+"A"+n+","+n+" 0 1,1 0,"+n+"Z"}function Ye(t,n){t.attr("transform",function(t){return"translate("+n(t)+",0)"})}function Ue(t,n){t.attr("transform",function(t){return"translate(0,"+n(t)+")"})}function Ie(t,n,e){if(r=[],e&&n.length>1){for(var r,u,i,a=Rn(t.domain()),o=-1,c=n.length,l=(n[1]-n[0])/++e;c>++o;)for(u=e;--u>0;)(i=+n[o]-u*l)>=a[0]&&r.push(i);for(--o,u=0;e>++u&&(i=+n[o]+u*l)<a[1];)r.push(i)}return r}function Ve(t){for(var n=t.source,e=t.target,r=Ze(n,e),u=[n];n!==r;)n=n.parent,u.push
(n);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Xe(t){for(var n=[],e=t.parent;null!=e;)n.push(t),t=e,e=e.parent;return n.push(t),n}function Ze(t,n){if(t===n)return t;for(var e=Xe(t),r=Xe(n),u=e.pop(),i=r.pop(),a=null;u===i;)a=u,u=e.pop(),i=r.pop();return a}function Be(t){t.fixed|=2}function $e(t){t.fixed&=-7}function Je(t){t.fixed|=4,t.px=t.x,t.py=t.y}function Ge(t){t.fixed&=-5}function Ke(t,n,e){var r=0,u=0;if(t.charge=0,!t.leaf)for(var i,a=t.nodes,o=a.length,c=-1;o>++c;)i=a[c],null!=i&&(Ke(i,n,e),t.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(t.point){t.leaf||(t.point.x+=Math.random()-.5,t.point.y+=Math.random()-.5);var l=n*e[t.point.index];t.charge+=t.pointCharge=l,r+=l*t.point.x,u+=l*t.point.y}t.cx=r/t.charge,t.cy=u/t.charge}function We(t){return t.x}function Qe(t){return t.y}function tr(t,n,e){t.y0=n,t.y=e}function nr(t){return qi.range(t.length)}function er(t){for(var n=-1,e=t[0].length,r=[];e>++n;)r[n]=0;return r}function rr(t){for
(var n,e=1,r=0,u=t[0][1],i=t.length;i>e;++e)(n=t[e][1])>u&&(r=e,u=n);return r}function ur(t){return t.reduce(ir,0)}function ir(t,n){return t+n[1]}function ar(t,n){return or(t,Math.ceil(Math.log(n.length)/Math.LN2+1))}function or(t,n){for(var e=-1,r=+t[0],u=(t[1]-r)/n,i=[];n>=++e;)i[e]=u*e+r;return i}function cr(t){return[qi.min(t),qi.max(t)]}function lr(t,n){return qi.rebind(t,n,"sort","children","value"),t.nodes=t,t.links=gr,t}function fr(t){return t.children}function sr(t){return t.value}function hr(t,n){return n.value-t.value}function gr(t){return qi.merge(t.map(function(t){return(t.children||[]).map(function(n){return{source:t,target:n}})}))}function pr(t,n){return t.value-n.value}function dr(t,n){var e=t._pack_next;t._pack_next=n,n._pack_prev=t,n._pack_next=e,e._pack_prev=n}function mr(t,n){t._pack_next=n,n._pack_prev=t}function vr(t,n){var e=n.x-t.x,r=n.y-t.y,u=t.r+n.r;return u*u-e*e-r*r>.001}function yr(t){function n(t){f=Math.min(t.x-t.r,f),s=Math.max(t.x+t.r,s),h=Ma
th.min(t.y-t.r,h),g=Math.max(t.y+t.r,g)}if((e=t.children)&&(l=e.length)){var e,r,u,i,a,o,c,l,f=1/0,s=-1/0,h=1/0,g=-1/0;if(e.forEach(Mr),r=e[0],r.x=-r.r,r.y=0,n(r),l>1&&(u=e[1],u.x=u.r,u.y=0,n(u),l>2))for(i=e[2],_r(r,u,i),n(i),dr(r,i),r._pack_prev=i,dr(i,u),u=r._pack_next,a=3;l>a;a++){_r(r,u,i=e[a]);var p=0,d=1,m=1;for(o=u._pack_next;o!==u;o=o._pack_next,d++)if(vr(o,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==o._pack_prev&&!vr(c,i);c=c._pack_prev,m++);p?(m>d||d==m&&u.r<r.r?mr(r,u=o):mr(r=c,u),a--):(dr(r,i),u=i,n(i))}var v=(f+s)/2,y=(h+g)/2,M=0;for(a=0;l>a;a++)i=e[a],i.x-=v,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));t.r=M,e.forEach(br)}}function Mr(t){t._pack_next=t._pack_prev=t}function br(t){delete t._pack_next,delete t._pack_prev}function xr(t,n,e,r){var u=t.children;if(t.x=n+=r*t.x,t.y=e+=r*t.y,t.r*=r,u)for(var i=-1,a=u.length;a>++i;)xr(u[i],n,e,r)}function _r(t,n,e){var r=t.r+e.r,u=n.x-t.x,i=n.y-t.y;if(r&&(u||i)){var a=n.r+e.r,o=u*u+i*i;a*=a,r*=r;var c=.5+(r-a)/
(2*o),l=Math.sqrt(Math.max(0,2*a*(r+o)-(r-=o)*r-a*a))/(2*o);e.x=t.x+c*u+l*i,e.y=t.y+c*i-l*u}else e.x=t.x+r,e.y=t.y}function wr(t){return 1+qi.max(t,function(t){return t.y})}function Sr(t){return t.reduce(function(t,n){return t+n.x},0)/t.length}function kr(t){var n=t.children;return n&&n.length?kr(n[0]):t}function Er(t){var n,e=t.children;return e&&(n=e.length)?Er(e[n-1]):t}function Ar(t,n){return t.parent==n.parent?1:2}function Nr(t){var n=t.children;return n&&n.length?n[0]:t._tree.thread}function Tr(t){var n,e=t.children;return e&&(n=e.length)?e[n-1]:t._tree.thread}function qr(t,n){var e=t.children;if(e&&(u=e.length))for(var r,u,i=-1;u>++i;)n(r=qr(e[i],n),t)>0&&(t=r);return t}function Cr(t,n){return t.x-n.x}function zr(t,n){return n.x-t.x}function Dr(t,n){return t.depth-n.depth}function Lr(t,n){function e(t,r){var u=t.children;if(u&&(a=u.length))for(var i,a,o=null,c=-1;a>++c;)i=u[c],e(i,o),o=i;n(t,r)}e(t,null)}function Fr(t){for(var n,e=0,r=0,u=t.children,i=u.length;--i>=0;
)n=u[i]._tree,n.prelim+=e,n.mod+=e,e+=n.shift+(r+=n.change)}function Hr(t,n,e){t=t._tree,n=n._tree;var r=e/(n.number-t.number);t.change+=r,n.change-=r,n.shift+=e,n.prelim+=e,n.mod+=e}function jr(t,n,e){return t._tree.ancestor.parent==n.parent?t._tree.ancestor:e}function Pr(t){return{x:t.x,y:t.y,dx:t.dx,dy:t.dy}}function Rr(t,n){var e=t.x+n[3],r=t.y+n[0],u=t.dx-n[1]-n[3],i=t.dy-n[0]-n[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Or(t,n){function e(t,e){return qi.xhr(t,n,e).response(r)}function r(t){return e.parse(t.responseText)}function u(n){return n.map(i).join(t)}function i(t){return a.test(t)?'"'+t.replace(/\"/g,'""')+'"':t}var a=RegExp('["'+t+"\n]"),o=t.charCodeAt(0);return e.parse=function(t){var n;return e.parseRows(t,function(t){return n?n(t):(n=Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}"),void 0)})},e.parseRows=function(t,n){function e(){if(f>=l)return a;if(u)return u=!1,i;var n=f;if(
34===t.charCodeAt(n)){for(var e=n;l>e++;)if(34===t.charCodeAt(e)){if(34!==t.charCodeAt(e+1))break;++e}f=e+2;var r=t.charCodeAt(e+1);return 13===r?(u=!0,10===t.charCodeAt(e+2)&&++f):10===r&&(u=!0),t.substring(n+1,e).replace(/""/g,'"')}for(;l>f;){var r=t.charCodeAt(f++),c=1;if(10===r)u=!0;else if(13===r)u=!0,10===t.charCodeAt(f)&&(++f,++c);else if(r!==o)continue;return t.substring(n,f-c)}return t.substring(n)}for(var r,u,i={},a={},c=[],l=t.length,f=0,s=0;(r=e())!==a;){for(var h=[];r!==i&&r!==a;)h.push(r),r=e();(!n||(h=n(h,s++)))&&c.push(h)}return c},e.format=function(t){return t.map(u).join("\n")},e}function Yr(t,n){ao.hasOwnProperty(t.type)&&ao[t.type](t,n)}function Ur(t,n,e){var r,u=-1,i=t.length-e;for(n.lineStart();i>++u;)r=t[u],n.point(r[0],r[1]);n.lineEnd()}function Ir(t,n){var e=-1,r=t.length;for(n.polygonStart();r>++e;)Ur(t[e],n,1);n.polygonEnd()}function Vr(t){return[Math.atan2(t[1],t[0]),Math.asin(Math.max(-1,Math.min(1,t[2])))]}function Xr(t,n){return Ti>Math.abs(t[0
]-n[0])&&Ti>Math.abs(t[1]-n[1])}function Zr(t){var n=t[0],e=t[1],r=Math.cos(e);return[r*Math.cos(n),r*Math.sin(n),Math.sin(e)]}function Br(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function $r(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Jr(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function Gr(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function Kr(t){var n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function Wr(t){function n(n){function r(e,r){e=t(e,r),n.point(e[0],e[1])}function i(){f=0/0,d.point=a,n.lineStart()}function a(r,i){var a=Zr([r,i]),o=t(r,i);e(f,s,l,h,g,p,f=o[0],s=o[1],l=r,h=a[0],g=a[1],p=a[2],u,n),n.point(f,s)}function o(){d.point=r,n.lineEnd()}function c(){var t,r,c,m,v,y,M;i(),d.point=function(n,e){a(t=n,r=e),c=f,m=s,v=h,y=g,M=p,d.point=a},d.lineEnd=function(){e(f,s,l,h,g,p,c,m,t,v,y,M,u,n),d.lineEnd=o,o()}}var l,f,s,h,g,p,d={point:r,lineStart:i,lineEnd:o,polygonStart:function(){n.polygonStart(),d.lineStart=c},polyg
onEnd:function(){n.polygonEnd(),d.lineStart=i}};return d}function e(n,u,i,a,o,c,l,f,s,h,g,p,d,m){var v=l-n,y=f-u,M=v*v+y*y;if(M>4*r&&d--){var b=a+h,x=o+g,_=c+p,w=Math.sqrt(b*b+x*x+_*_),S=Math.asin(_/=w),k=Ti>Math.abs(Math.abs(_)-1)?(i+s)/2:Math.atan2(x,b),E=t(k,S),A=E[0],N=E[1],T=A-n,q=N-u,C=y*T-v*q;(C*C/M>r||Math.abs((v*T+y*q)/M-.5)>.3)&&(e(n,u,i,a,o,c,A,N,k,b/=w,x/=w,_,d,m),m.point(A,N),e(A,N,k,b,x,_,l,f,s,h,g,p,d,m))}}var r=.5,u=16;return n.precision=function(t){return arguments.length?(u=(r=t*t)>0&&16,n):Math.sqrt(r)},n}function Qr(t,n){function e(t,n){var e=Math.sqrt(i-2*u*Math.sin(n))/u;return[e*Math.sin(t*=u),a-e*Math.cos(t)]}var r=Math.sin(t),u=(r+Math.sin(n))/2,i=1+r*(2*u-r),a=Math.sqrt(i)/u;return e.invert=function(t,n){var e=a-n;return[Math.atan2(t,e)/u,Math.asin((i-(t*t+e*e)*u*u)/(2*u))]},e}function tu(t){function n(t,n){r>t&&(r=t),t>i&&(i=t),u>n&&(u=n),n>a&&(a=n)}function e(){o.point=o.lineEnd=Pn}var r,u,i,a,o={point:n,lineStart:Pn,lineEnd:Pn,polygonStart:functi
on(){o.lineEnd=e},polygonEnd:function(){o.point=n}};return function(n){return a=i=-(r=u=1/0),qi.geo.stream(n,t(o)),[[r,u],[i,a]]}}function nu(t,n){if(!lo){++fo,t*=Ci;var e=Math.cos(n*=Ci);so+=(e*Math.cos(t)-so)/fo,ho+=(e*Math.sin(t)-ho)/fo,go+=(Math.sin(n)-go)/fo}}function eu(){var t,n;lo=1,ru(),lo=2;var e=po.point;po.point=function(r,u){e(t=r,n=u)},po.lineEnd=function(){po.point(t,n),uu(),po.lineEnd=uu}}function ru(){function t(t,u){t*=Ci;var i=Math.cos(u*=Ci),a=i*Math.cos(t),o=i*Math.sin(t),c=Math.sin(u),l=Math.atan2(Math.sqrt((l=e*c-r*o)*l+(l=r*a-n*c)*l+(l=n*o-e*a)*l),n*a+e*o+r*c);fo+=l,so+=l*(n+(n=a)),ho+=l*(e+(e=o)),go+=l*(r+(r=c))}var n,e,r;lo>1||(1>lo&&(lo=1,fo=so=ho=go=0),po.point=function(u,i){u*=Ci;var a=Math.cos(i*=Ci);n=a*Math.cos(u),e=a*Math.sin(u),r=Math.sin(i),po.point=t})}function uu(){po.point=nu}function iu(t,n){var e=Math.cos(t),r=Math.sin(t);return function(u,i,a,o){null!=u?(u=au(e,u),i=au(e,i),(a>0?i>u:u>i)&&(u+=2*a*Ni)):(u=t+2*a*Ni,i=t);for(var c,l=a*n,
f=u;a>0?f>i:i>f;f-=l)o.point((c=Vr([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function au(t,n){var e=Zr(n);e[0]-=t,Kr(e);var r=Math.acos(Math.max(-1,Math.min(1,-e[1])));return((0>-e[2]?-r:r)+2*Math.PI-Ti)%(2*Math.PI)}function ou(t,n,e){return function(r){function u(n,e){t(n,e)&&r.point(n,e)}function i(t,n){m.point(t,n)}function a(){v.point=i,m.lineStart()}function o(){v.point=u,m.lineEnd()}function c(t,n){M.point(t,n),d.push([t,n])}function l(){M.lineStart(),d=[]}function f(){c(d[0][0],d[0][1]),M.lineEnd();var t,n=M.clean(),e=y.buffer(),u=e.length;if(!u)return p=!0,g+=gu(d,-1),d=null,void 0;if(d=null,1&n){t=e[0],h+=gu(t,1);var i,u=t.length-1,a=-1;for(r.lineStart();u>++a;)r.point((i=t[a])[0],i[1]);return r.lineEnd(),void 0}u>1&&2&n&&e.push(e.pop().concat(e.shift())),s.push(e.filter(su))}var s,h,g,p,d,m=n(r),v={point:u,lineStart:a,lineEnd:o,polygonStart:function(){v.point=c,v.lineStart=l,v.lineEnd=f,p=!1,g=h=0,s=[],r.polygonStart()},polygonEnd:function(){v.point=u,v.lineSta
rt=a,v.lineEnd=o,s=qi.merge(s),s.length?cu(s,e,r):(-Ti>h||p&&-Ti>g)&&(r.lineStart(),e(null,null,1,r),r.lineEnd()),r.polygonEnd(),s=null},sphere:function(){r.polygonStart(),r.lineStart(),e(null,null,1,r),r.lineEnd(),r.polygonEnd()}},y=hu(),M=n(y);return v}}function cu(t,n,e){var r=[],u=[];if(t.forEach(function(t){var n=t.length;if(!(1>=n)){var e=t[0],i=t[n-1],a={point:e,points:t,other:null,visited:!1,entry:!0,subject:!0},o={point:e,points:[e],other:a,visited:!1,entry:!1,subject:!1};
-a.other=o,r.push(a),u.push(o),a={point:i,points:[i],other:null,visited:!1,entry:!1,subject:!0},o={point:i,points:[i],other:a,visited:!1,entry:!0,subject:!1},a.other=o,r.push(a),u.push(o)}}),u.sort(fu),lu(r),lu(u),r.length)for(var i,a,o,c=r[0];;){for(i=c;i.visited;)if((i=i.next)===c)return;a=i.points,e.lineStart();do{if(i.visited=i.other.visited=!0,i.entry){if(i.subject)for(var l=0;a.length>l;l++)e.point((o=a[l])[0],o[1]);else n(i.point,i.next.point,1,e);i=i.next}else{if(i.subject){a=i.prev.points;for(var l=a.length;--l>=0;)e.point((o=a[l])[0],o[1])}else n(i.point,i.prev.point,-1,e);i=i.prev}i=i.other,a=i.points}while(!i.visited);e.lineEnd()}}function lu(t){if(n=t.length){for(var n,e,r=0,u=t[0];n>++r;)u.next=e=t[r],e.prev=u,u=e;u.next=e=t[0],e.prev=u}}function fu(t,n){return(0>(t=t.point)[0]?t[1]-Ni/2-Ti:Ni/2-t[1])-(0>(n=n.point)[0]?n[1]-Ni/2-Ti:Ni/2-n[1])}function su(t){return t.length>1}function hu(){var t,n=[];return{lineStart:function(){n.push(t=[])},point:function(n,e){t
.push([n,e])},lineEnd:Pn,buffer:function(){var e=n;return n=[],t=null,e}}}function gu(t,n){if(!(e=t.length))return 0;for(var e,r,u,i=0,a=0,o=t[0],c=o[0],l=o[1],f=Math.cos(l),s=Math.atan2(n*Math.sin(c)*f,Math.sin(l)),h=1-n*Math.cos(c)*f,g=s;e>++i;)o=t[i],f=Math.cos(l=o[1]),r=Math.atan2(n*Math.sin(c=o[0])*f,Math.sin(l)),u=1-n*Math.cos(c)*f,Ti>Math.abs(h-2)&&Ti>Math.abs(u-2)||(Ti>Math.abs(u)||Ti>Math.abs(h)||(Ti>Math.abs(Math.abs(r-s)-Ni)?u+h>2&&(a+=4*(r-s)):a+=Ti>Math.abs(h-2)?4*(r-g):((3*Ni+r-s)%(2*Ni)-Ni)*(h+u)),g=s,s=r,h=u);return a}function pu(t){var n,e=0/0,r=0/0,u=0/0;return{lineStart:function(){t.lineStart(),n=1},point:function(i,a){var o=i>0?Ni:-Ni,c=Math.abs(i-e);Ti>Math.abs(c-Ni)?(t.point(e,r=(r+a)/2>0?Ni/2:-Ni/2),t.point(u,r),t.lineEnd(),t.lineStart(),t.point(o,r),t.point(i,r),n=0):u!==o&&c>=Ni&&(Ti>Math.abs(e-u)&&(e-=u*Ti),Ti>Math.abs(i-o)&&(i-=o*Ti),r=du(e,r,i,a),t.point(u,r),t.lineEnd(),t.lineStart(),t.point(o,r),n=0),t.point(e=i,r=a),u=o},lineEnd:function(){t.li
neEnd(),e=r=0/0},clean:function(){return 2-n}}}function du(t,n,e,r){var u,i,a=Math.sin(t-e);return Math.abs(a)>Ti?Math.atan((Math.sin(n)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(n))*Math.sin(t))/(u*i*a)):(n+r)/2}function mu(t,n,e,r){var u;if(null==t)u=e*Ni/2,r.point(-Ni,u),r.point(0,u),r.point(Ni,u),r.point(Ni,0),r.point(Ni,-u),r.point(0,-u),r.point(-Ni,-u),r.point(-Ni,0),r.point(-Ni,u);else if(Math.abs(t[0]-n[0])>Ti){var i=(t[0]<n[0]?1:-1)*Ni;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(n[0],n[1])}function vu(t){function n(t,n){return Math.cos(t)*Math.cos(n)>i}function e(t){var e,u,i,a;return{lineStart:function(){i=u=!1,a=1},point:function(o,c){var l,f=[o,c],s=n(o,c);!e&&(i=u=s)&&t.lineStart(),s!==u&&(l=r(e,f),(Xr(e,l)||Xr(f,l))&&(f[0]+=Ti,f[1]+=Ti,s=n(f[0],f[1]))),s!==u&&(a=0,(u=s)?(t.lineStart(),l=r(f,e),t.point(l[0],l[1])):(l=r(e,f),t.point(l[0],l[1]),t.lineEnd()),e=l),!s||e&&Xr(e,f)||t.point(f[0],f[1]),e=f},lineEnd:function(){u&&t.lineEnd(),e=
null},clean:function(){return a|(i&&u)<<1}}}function r(t,n){var e=Zr(t,0),r=Zr(n,0),u=[1,0,0],a=$r(e,r),o=Br(a,a),c=a[0],l=o-c*c;if(!l)return t;var f=i*o/l,s=-i*c/l,h=$r(u,a),g=Gr(u,f),p=Gr(a,s);Jr(g,p);var d=h,m=Br(g,d),v=Br(d,d),y=Math.sqrt(m*m-v*(Br(g,g)-1)),M=Gr(d,(-m-y)/v);return Jr(M,g),Vr(M)}var u=t*Ci,i=Math.cos(u),a=iu(u,6*Ci);return ou(n,e,a)}function yu(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return e=n.invert(e,r),e&&t.invert(e[0],e[1])}),e}function Mu(t,n){return[t,n]}function bu(t,n,e){var r=qi.range(t,n-Ti,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function xu(t,n,e){var r=qi.range(t,n-Ti,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function _u(t,n,e,r){function u(t){var n=Math.sin(t*=g)*p,e=Math.sin(g-t)*p,r=e*l+n*s,u=e*f+n*h,i=e*a+n*c;return[Math.atan2(u,r)/Ci,Math.atan2(i,Math.sqrt(r*r+u*u))/Ci]}var i=Math.cos(n),a=Math.sin(n),o=Math.cos(r),c
=Math.sin(r),l=i*Math.cos(t),f=i*Math.sin(t),s=o*Math.cos(e),h=o*Math.sin(e),g=Math.acos(Math.max(-1,Math.min(1,a*c+i*o*Math.cos(e-t)))),p=1/Math.sin(g);return u.distance=g,u}function wu(t,n){return[t/(2*Ni),Math.max(-.5,Math.min(.5,Math.log(Math.tan(Ni/4+n/2))/(2*Ni)))]}function Su(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function ku(t){var n=Wr(function(n,e){return t([n*zi,e*zi])});return function(t){return t=n(t),{point:function(n,e){t.point(n*Ci,e*Ci)},sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}}function Eu(){function t(t,n){a.push("M",t,",",n,i)}function n(t,n){a.push("M",t,",",n),o.point=e}function e(t,n){a.push("L",t,",",n)}function r(){o.point=t}function u(){a.push("Z")}var i=Su(4.5),a=[],o={point:t,lineStart:function(){o.point=n},lineEnd:r,polygonStart:function(){o.lineEnd=u},polygonEnd:function(
){o.lineEnd=r,o.point=t},pointRadius:function(t){return i=Su(t),o},result:function(){if(a.length){var t=a.join("");return a=[],t}}};return o}function Au(t){function n(n,e){t.moveTo(n,e),t.arc(n,e,a,0,2*Ni)}function e(n,e){t.moveTo(n,e),o.point=r}function r(n,e){t.lineTo(n,e)}function u(){o.point=n}function i(){t.closePath()}var a=4.5,o={point:n,lineStart:function(){o.point=e},lineEnd:u,polygonStart:function(){o.lineEnd=i},polygonEnd:function(){o.lineEnd=u,o.point=n},pointRadius:function(t){return a=t,o},result:Pn};return o}function Nu(){function t(t,n){bo+=u*t-r*n,r=t,u=n}var n,e,r,u;xo.point=function(i,a){xo.point=t,n=r=i,e=u=a},xo.lineEnd=function(){t(n,e)}}function Tu(t,n){lo||(so+=t,ho+=n,++go)}function qu(){function t(t,r){var u=t-n,i=r-e,a=Math.sqrt(u*u+i*i);so+=a*(n+t)/2,ho+=a*(e+r)/2,go+=a,n=t,e=r}var n,e;if(1!==lo){if(!(1>lo))return;lo=1,so=ho=go=0}_o.point=function(r,u){_o.point=t,n=r,e=u}}function Cu(){_o.point=Tu}function zu(){function t(t,n){var e=u*t-r*n;so+=e*
(r+t),ho+=e*(u+n),go+=3*e,r=t,u=n}var n,e,r,u;2>lo&&(lo=2,so=ho=go=0),_o.point=function(i,a){_o.point=t,n=r=i,e=u=a},_o.lineEnd=function(){t(n,e)}}function Du(){function t(t,n){t*=Ci,n=n*Ci/2+Ni/4;var e=t-r,a=Math.cos(n),o=Math.sin(n),c=i*o,l=So,f=ko,s=u*a+c*Math.cos(e),h=c*Math.sin(e);So=l*s-f*h,ko=f*s+l*h,r=t,u=a,i=o}var n,e,r,u,i;Eo.point=function(a,o){Eo.point=t,r=(n=a)*Ci,u=Math.cos(o=(e=o)*Ci/2+Ni/4),i=Math.sin(o)},Eo.lineEnd=function(){t(n,e)}}function Lu(t){return Fu(function(){return t})()}function Fu(t){function n(t){return t=a(t[0]*Ci,t[1]*Ci),[t[0]*f+o,c-t[1]*f]}function e(t){return t=a.invert((t[0]-o)/f,(c-t[1])/f),t&&[t[0]*zi,t[1]*zi]}function r(){a=yu(i=ju(d,m,v),u);var t=u(g,p);return o=s-t[0]*f,c=h+t[1]*f,n}var u,i,a,o,c,l=Wr(function(t,n){return t=u(t,n),[t[0]*f+o,c-t[1]*f]}),f=150,s=480,h=250,g=0,p=0,d=0,m=0,v=0,y=mo,M=null;return n.stream=function(t){return Hu(i,y(l(t)))},n.clipAngle=function(t){return arguments.length?(y=null==t?(M=t,mo):vu(M=+t),n):M},n
.scale=function(t){return arguments.length?(f=+t,r()):f},n.translate=function(t){return arguments.length?(s=+t[0],h=+t[1],r()):[s,h]},n.center=function(t){return arguments.length?(g=t[0]%360*Ci,p=t[1]%360*Ci,r()):[g*zi,p*zi]},n.rotate=function(t){return arguments.length?(d=t[0]%360*Ci,m=t[1]%360*Ci,v=t.length>2?t[2]%360*Ci:0,r()):[d*zi,m*zi,v*zi]},qi.rebind(n,l,"precision"),function(){return u=t.apply(this,arguments),n.invert=u.invert&&e,r()}}function Hu(t,n){return{point:function(e,r){r=t(e*Ci,r*Ci),e=r[0],n.point(e>Ni?e-2*Ni:-Ni>e?e+2*Ni:e,r[1])},sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ju(t,n,e){return t?n||e?yu(Ru(t),Ou(n,e)):Ru(t):n||e?Ou(n,e):Mu}function Pu(t){return function(n,e){return n+=t,[n>Ni?n-2*Ni:-Ni>n?n+2*Ni:n,e]}}function Ru(t){var n=Pu(t);return n.invert=Pu(-t),n}function Ou(t,n){function e(t,n){var e=Math.cos(n)
,o=Math.cos(t)*e,c=Math.sin(t)*e,l=Math.sin(n),f=l*r+o*u;return[Math.atan2(c*i-f*a,o*r-l*u),Math.asin(Math.max(-1,Math.min(1,f*i+c*a)))]}var r=Math.cos(t),u=Math.sin(t),i=Math.cos(n),a=Math.sin(n);return e.invert=function(t,n){var e=Math.cos(n),o=Math.cos(t)*e,c=Math.sin(t)*e,l=Math.sin(n),f=l*i-c*a;return[Math.atan2(c*i+l*a,o*r+f*u),Math.asin(Math.max(-1,Math.min(1,f*r-o*u)))]},e}function Yu(t,n){function e(n,e){var r=Math.cos(n),u=Math.cos(e),i=t(r*u);return[i*u*Math.sin(n),i*Math.sin(e)]}return e.invert=function(t,e){var r=Math.sqrt(t*t+e*e),u=n(r),i=Math.sin(u),a=Math.cos(u);return[Math.atan2(t*i,r*a),Math.asin(r&&e*i/r)]},e}function Uu(t,n,e,r){var u,i,a,o,c,l,f;return u=r[t],i=u[0],a=u[1],u=r[n],o=u[0],c=u[1],u=r[e],l=u[0],f=u[1],(f-a)*(o-i)-(c-a)*(l-i)>0}function Iu(t,n,e){return(e[0]-n[0])*(t[1]-n[1])<(e[1]-n[1])*(t[0]-n[0])}function Vu(t,n,e,r){var u=t[0],i=e[0],a=n[0]-u,o=r[0]-i,c=t[1],l=e[1],f=n[1]-c,s=r[1]-l,h=(o*(c-l)-s*(u-i))/(s*a-o*f);return[u+h*a,c+h*f]}funct
ion Xu(t,n){var e={list:t.map(function(t,n){return{index:n,x:t[0],y:t[1]}}).sort(function(t,n){return t.y<n.y?-1:t.y>n.y?1:t.x<n.x?-1:t.x>n.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(t,n){return{edge:t,side:n,vertex:null,l:null,r:null}},insert:function(t,n){n.l=t,n.r=t.r,t.r.l=n,t.r=n},leftBound:function(t){var n=r.leftEnd;do n=n.r;while(n!=r.rightEnd&&u.rightOf(n,t));return n=n.l},del:function(t){t.l.r=t.r,t.r.l=t.l,t.edge=null},right:function(t){return t.r},left:function(t){return t.l},leftRegion:function(t){return null==t.edge?e.bottomSite:t.edge.region[t.side]},rightRegion:function(t){return null==t.edge?e.bottomSite:t.edge.region[No[t.side]]}},u={bisect:function(t,n){var e={region:{l:t,r:n},ep:{l:null,r:null}},r=n.x-t.x,u=n.y-t.y,i=r>0?r:-r,a=u>0?u:-u;ret
urn e.c=t.x*r+t.y*u+.5*(r*r+u*u),i>a?(e.a=1,e.b=u/r,e.c/=r):(e.b=1,e.a=r/u,e.c/=u),e},intersect:function(t,n){var e=t.edge,r=n.edge;if(!e||!r||e.region.r==r.region.r)return null;var u=e.a*r.b-e.b*r.a;if(1e-10>Math.abs(u))return null;var i,a,o=(e.c*r.b-r.c*e.b)/u,c=(r.c*e.a-e.c*r.a)/u,l=e.region.r,f=r.region.r;l.y<f.y||l.y==f.y&&l.x<f.x?(i=t,a=e):(i=n,a=r);var s=o>=a.region.r.x;return s&&"l"===i.side||!s&&"r"===i.side?null:{x:o,y:c}},rightOf:function(t,n){var e=t.edge,r=e.region.r,u=n.x>r.x;if(u&&"l"===t.side)return 1;if(!u&&"r"===t.side)return 0;if(1===e.a){var i=n.y-r.y,a=n.x-r.x,o=0,c=0;if(!u&&0>e.b||u&&e.b>=0?c=o=i>=e.b*a:(c=n.x+n.y*e.b>e.c,0>e.b&&(c=!c),c||(o=1)),!o){var l=r.x-e.region.l.x;c=e.b*(a*a-i*i)<l*i*(1+2*a/l+e.b*e.b),0>e.b&&(c=!c)}}else{var f=e.c-e.a*n.x,s=n.y-f,h=n.x-r.x,g=f-r.y;c=s*s>h*h+g*g}return"l"===t.side?c:!c},endPoint:function(t,e,r){t.ep[e]=r,t.ep[No[e]]&&n(t)},distance:function(t,n){var e=t.x-n.x,r=t.y-n.y;return Math.sqrt(e*e+r*r)}},i={list:[],inser
t:function(t,n,e){t.vertex=n,t.ystar=n.y+e;for(var r=0,u=i.list,a=u.length;a>r;r++){var o=u[r];if(!(t.ystar>o.ystar||t.ystar==o.ystar&&n.x>o.vertex.x))break}u.splice(r,0,t)},del:function(t){for(var n=0,e=i.list,r=e.length;r>n&&e[n]!=t;++n);e.splice(n,1)},empty:function(){return 0===i.list.length},nextEvent:function(t){for(var n=0,e=i.list,r=e.length;r>n;++n)if(e[n]==t)return e[n+1];return null},min:function(){var t=i.list[0];return{x:t.vertex.x,y:t.ystar}},extractMin:function(){return i.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var a,o,c,l,f,s,h,g,p,d,m,v,y,M=e.list.shift();;)if(i.empty()||(a=i.min()),M&&(i.empty()||M.y<a.y||M.y==a.y&&M.x<a.x))o=r.leftBound(M),c=r.right(o),h=r.rightRegion(o),v=u.bisect(h,M),s=r.createHalfEdge(v,"l"),r.insert(o,s),d=u.intersect(o,s),d&&(i.del(o),i.insert(o,d,u.distance(d,M))),o=s,s=r.createHalfEdge(v,"r"),r.insert(o,s),d=u.intersect(s,c),d&&i.insert(s,d,u.distance(d,M)),M=e.list.shift();else{if(i.empty())break;o=i.extractMin(),l
=r.left(o),c=r.right(o),f=r.right(c),h=r.leftRegion(o),g=r.rightRegion(c),m=o.vertex,u.endPoint(o.edge,o.side,m),u.endPoint(c.edge,c.side,m),r.del(o),i.del(c),r.del(c),y="l",h.y>g.y&&(p=h,h=g,g=p,y="r"),v=u.bisect(h,g),s=r.createHalfEdge(v,y),r.insert(l,s),u.endPoint(v,No[y],m),d=u.intersect(l,s),d&&(i.del(l),i.insert(l,d,u.distance(d,h))),d=u.intersect(s,f),d&&i.insert(s,d,u.distance(d,h))}for(o=r.right(r.leftEnd);o!=r.rightEnd;o=r.right(o))n(o.edge)}function Zu(){return{leaf:!0,nodes:[],point:null}}function Bu(t,n,e,r,u,i){if(!t(n,e,r,u,i)){var a=.5*(e+u),o=.5*(r+i),c=n.nodes;c[0]&&Bu(t,c[0],e,r,a,o),c[1]&&Bu(t,c[1],a,r,u,o),c[2]&&Bu(t,c[2],e,o,a,i),c[3]&&Bu(t,c[3],a,o,u,i)}}function $u(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ju(t,n,e,r){for(var u,i,a=0,o=n.length,c=e.length;o>a;){if(r>=c)return-1;if(u=n.charCodeAt(a++),37===u){if(i=Bo[n.charAt(a++)],!i||0>(r=i(t,e,r)))return-1}else if(u!=e.charCodeAt(r++))return-1}return
r}function Gu(t){return RegExp("^(?:"+t.map(qi.requote).join("|")+")","i")}function Ku(t){for(var n=new i,e=-1,r=t.length;r>++e;)n.set(t[e].toLowerCase(),e);return n}function Wu(t,n,e){t+="";var r=t.length;return e>r?Array(e-r+1).join(n)+t:t}function Qu(t,n,e){Oo.lastIndex=0;var r=Oo.exec(n.substring(e));return r?e+=r[0].length:-1}function ti(t,n,e){Ro.lastIndex=0;var r=Ro.exec(n.substring(e));return r?e+=r[0].length:-1}function ni(t,n,e){Io.lastIndex=0;var r=Io.exec(n.substring(e));return r?(t.m=Vo.get(r[0].toLowerCase()),e+=r[0].length):-1}function ei(t,n,e){Yo.lastIndex=0;var r=Yo.exec(n.substring(e));return r?(t.m=Uo.get(r[0].toLowerCase()),e+=r[0].length):-1}function ri(t,n,e){return Ju(t,""+Zo.c,n,e)}function ui(t,n,e){return Ju(t,""+Zo.x,n,e)}function ii(t,n,e){return Ju(t,""+Zo.X,n,e)}function ai(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+4));return r?(t.y=+r[0],e+=r[0].length):-1}function oi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(
t.y=ci(+r[0]),e+=r[0].length):-1}function ci(t){return t+(t>68?1900:2e3)}function li(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.m=r[0]-1,e+=r[0].length):-1}function fi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.d=+r[0],e+=r[0].length):-1}function si(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.H=+r[0],e+=r[0].length):-1}function hi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.M=+r[0],e+=r[0].length):-1}function gi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.S=+r[0],e+=r[0].length):-1}function pi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+3));return r?(t.L=+r[0],e+=r[0].length):-1}function di(t,n,e){var r=Jo.get(n.substring(e,e+=2).toLowerCase());return null==r?-1:(t.p=r,e)}function mi(t){var n=t.getTimezoneOffset(),e=n>0?"-":"+",r=~~(Math.abs(n)/60),u=Math.abs(n)%60;return e+Wu(r,"0",2)+Wu(u,"0",2)}function vi(t){return t.toISOString()}function yi(
t,n,e){function r(n){var e=t(n),r=i(e,1);return r-n>n-e?e:r}function u(e){return n(e=t(new To(e-1)),1),e}function i(t,e){return n(t=new To(+t),e),t}function a(t,r,i){var a=u(t),o=[];if(i>1)for(;r>a;)e(a)%i||o.push(new Date(+a)),n(a,1);else for(;r>a;)o.push(new Date(+a)),n(a,1);return o}function o(t,n,e){try{To=$u;var r=new $u;return r._=t,a(r,n,e)}finally{To=Date}}t.floor=t,t.round=r,t.ceil=u,t.offset=i,t.range=a;var c=t.utc=Mi(t);return c.floor=c,c.round=Mi(r),c.ceil=Mi(u),c.offset=Mi(i),c.range=o,t}function Mi(t){return function(n,e){try{To=$u;var r=new $u;return r._=n,t(r,e)._}finally{To=Date}}}function bi(t,n,e){function r(n){return t(n)}return r.invert=function(n){return _i(t.invert(n))},r.domain=function(n){return arguments.length?(t.domain(n),r):t.domain().map(_i)},r.nice=function(t){return r.domain(Yn(r.domain(),function(){return t}))},r.ticks=function(e,u){var i=xi(r.domain());if("function"!=typeof e){var a=i[1]-i[0],o=a/e,c=qi.bisect(Ko,o);if(c==Ko.length)return n.
year(i,e);if(!c)return t.ticks(e).map(_i);Math.log(o/Ko[c-1])<Math.log(Ko[c]/o)&&--c,e=n[c],u=e[1],e=e[0].range}return e(i[0],new Date(+i[1]+1),u)},r.tickFormat=function(){return e},r.copy=function(){return bi(t.copy(),n,e)},qi.rebind(r,t,"range","rangeRound","interpolate","clamp")}function xi(t){var n=t[0],e=t[t.length-1];return e>n?[n,e]:[e,n]}function _i(t){return new Date(t)}function wi(t){return function(n){for(var e=t.length-1,r=t[e];!r[1](n);)r=t[--e];return r[0](n)}}function Si(t){var n=new Date(t,0,1);return n.setFullYear(t),n}function ki(t){var n=t.getFullYear(),e=Si(n),r=Si(n+1);return n+(t-e)/(r-e)}function Ei(t){var n=new Date(Date.UTC(t,0,1));return n.setUTCFullYear(t),n}function Ai(t){var n=t.getUTCFullYear(),e=Ei(n),r=Ei(n+1);return n+(t-e)/(r-e)}var Ni=Math.PI,Ti=1e-6,qi={version:"3.0.6"},Ci=Ni/180,zi=180/Ni,Di=document,Li=window,Fi=".",Hi=",",ji=[3,3];Date.now||(Date.now=function(){return+new Date});try{Di.createElement("div").style.setProperty("opacity",0,
"")}catch(Pi){var Ri=Li.CSSStyleDeclaration.prototype,Oi=Ri.setProperty;Ri.setProperty=function(t,n,e){Oi.call(this,t,n+"",e)}}var Yi=u;try{Yi(Di.documentElement.childNodes)[0].nodeType}catch(Ui){Yi=r}var Ii=[].__proto__?function(t,n){t.__proto__=n}:function(t,n){for(var e in n)t[e]=n[e]};qi.map=function(t){var n=new i;for(var e in t)n.set(e,t[e]);return n},e(i,{has:function(t){return Vi+t in this},get:function(t){return this[Vi+t]},set:function(t,n){return this[Vi+t]=n},remove:function(t){return t=Vi+t,t in this&&delete this[t]},keys:function(){var t=[];return this.forEach(function(n){t.push(n)}),t},values:function(){var t=[];return this.forEach(function(n,e){t.push(e)}),t},entries:function(){var t=[];return this.forEach(function(n,e){t.push({key:n,value:e})}),t},forEach:function(t){for(var n in this)n.charCodeAt(0)===Xi&&t.call(this,n.substring(1),this[n])}});var Vi="\0",Xi=Vi.charCodeAt(0);qi.functor=c,qi.rebind=function(t,n){for(var e,r=1,u=arguments.length;u>++r;)t[e=ar
guments[r]]=l(t,n,n[e]);return t},qi.ascending=function(t,n){return n>t?-1:t>n?1:t>=n?0:0/0},qi.descending=function(t,n){return t>n?-1:n>t?1:n>=t?0:0/0},qi.mean=function(t,n){var e,r=t.length,u=0,i=-1,a=0;if(1===arguments.length)for(;r>++i;)f(e=t[i])&&(u+=(e-u)/++a);else for(;r>++i;)f(e=n.call(t,t[i],i))&&(u+=(e-u)/++a);return a?u:void 0},qi.median=function(t,n){return arguments.length>1&&(t=t.map(n)),t=t.filter(f),t.length?qi.quantile(t.sort(qi.ascending),.5):void 0},qi.min=function(t,n){var e,r,u=-1,i=t.length;if(1===arguments.length){for(;i>++u&&(null==(e=t[u])||e!=e);)e=void 0;for(;i>++u;)null!=(r=t[u])&&e>r&&(e=r)}else{for(;i>++u&&(null==(e=n.call(t,t[u],u))||e!=e);)e=void 0;for(;i>++u;)null!=(r=n.call(t,t[u],u))&&e>r&&(e=r)}return e},qi.max=function(t,n){var e,r,u=-1,i=t.length;if(1===arguments.length){for(;i>++u&&(null==(e=t[u])||e!=e);)e=void 0;for(;i>++u;)null!=(r=t[u])&&r>e&&(e=r)}else{for(;i>++u&&(null==(e=n.call(t,t[u],u))||e!=e);)e=void 0;for(;i>++u;)null!=(r=n.
call(t,t[u],u))&&r>e&&(e=r)}return e},qi.extent=function(t,n){var e,r,u,i=-1,a=t.length;if(1===arguments.length){for(;a>++i&&(null==(e=u=t[i])||e!=e);)e=u=void 0;for(;a>++i;)null!=(r=t[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;a>++i&&(null==(e=u=n.call(t,t[i],i))||e!=e);)e=void 0;for(;a>++i;)null!=(r=n.call(t,t[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},qi.random={normal:function(t,n){var e=arguments.length;return 2>e&&(n=1),1>e&&(t=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 t+n*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var t=qi.random.normal.apply(qi,arguments);return function(){return Math.exp(t())}},irwinHall:function(t){return function(){for(var n=0,e=0;t>e;e++)n+=Math.random();return n/t}}},qi.sum=function(t,n){var e,r=0,u=t.length,i=-1;if(1===arguments.length)for(;u>++i;)isNaN(e=+t[i])||(r+=e);else for(;u>++i;)isNaN(e=+n.call(t,t[i],i))||(r+=e);return r},qi.quantile=function(t,n){var e=(t.length-1)*n+1,r
=Math.floor(e),u=+t[r-1],i=e-r;return i?u+i*(t[r]-u):u},qi.shuffle=function(t){for(var n,e,r=t.length;r;)e=0|Math.random()*r--,n=t[r],t[r]=t[e],t[e]=n;return t},qi.transpose=function(t){return qi.zip.apply(qi,t)},qi.zip=function(){if(!(r=arguments.length))return[];for(var t=-1,n=qi.min(arguments,s),e=Array(n);n>++t;)for(var r,u=-1,i=e[t]=Array(r);r>++u;)i[u]=arguments[u][t];return e},qi.bisector=function(t){return{left:function(n,e,r,u){for(3>arguments.length&&(r=0),4>arguments.length&&(u=n.length);u>r;){var i=r+u>>>1;e>t.call(n,n[i],i)?r=i+1:u=i}return r},right:function(n,e,r,u){for(3>arguments.length&&(r=0),4>arguments.length&&(u=n.length);u>r;){var i=r+u>>>1;t.call(n,n[i],i)>e?u=i:r=i+1}return r}}};var Zi=qi.bisector(function(t){return t});qi.bisectLeft=Zi.left,qi.bisect=qi.bisectRight=Zi.right,qi.nest=function(){function t(n,o){if(o>=a.length)return r?r.call(u,n):e?n.sort(e):n;for(var c,l,f,s=-1,h=n.length,g=a[o++],p=new i,d={};h>++s;)(f=p.get(c=g(l=n[s])))?f.push(l):p.s
et(c,[l]);return p.forEach(function(n,e){d[n]=t(e,o)}),d}function n(t,e){if(e>=a.length)return t;var r,u=[],i=o[e++];for(r in t)u.push({key:r,values:n(t[r],e)});return i&&u.sort(function(t,n){return i(t.key,n.key)}),u}var e,r,u={},a=[],o=[];return u.map=function(n){return t(n,0)},u.entries=function(e){return n(t(e,0),0)},u.key=function(t){return a.push(t),u},u.sortKeys=function(t){return o[a.length-1]=t,u},u.sortValues=function(t){return e=t,u},u.rollup=function(t){return r=t,u},u},qi.keys=function(t){var n=[];for(var e in t)n.push(e);return n},qi.values=function(t){var n=[];for(var e in t)n.push(t[e]);return n},qi.entries=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},qi.permute=function(t,n){for(var e=[],r=-1,u=n.length;u>++r;)e[r]=t[n[r]];return e},qi.merge=function(t){return Array.prototype.concat.apply([],t)},qi.range=function(t,n,e){if(3>arguments.length&&(e=1,2>arguments.length&&(n=t,t=0)),1/0===(n-t)/e)throw Error("infinite range");var r,u=[
],i=g(Math.abs(e)),a=-1;if(t*=i,n*=i,e*=i,0>e)for(;(r=t+e*++a)>n;)u.push(r/i);else for(;n>(r=t+e*++a);)u.push(r/i);return u},qi.requote=function(t){return t.replace(Bi,"\\$&")};var Bi=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;qi.round=function(t,n){return n?Math.round(t*(n=Math.pow(10,n)))/n:Math.round(t)},qi.xhr=function(t,n,e){function r(){var t=l.status;!t&&l.responseText||t>=200&&300>t||304===t?i.load.call(u,c.call(u,l)):i.error.call(u,l)}var u={},i=qi.dispatch("progress","load","error"),o={},c=a,l=new(Li.XDomainRequest&&/^(http(s)?:)?\/\//.test(t)?XDomainRequest:XMLHttpRequest);return"onload"in l?l.onload=l.onerror=r:l.onreadystatechange=function(){l.readyState>3&&r()},l.onprogress=function(t){var n=qi.event;qi.event=t;try{i.progress.call(u,l)}finally{qi.event=n}},u.header=function(t,n){return t=(t+"").toLowerCase(),2>arguments.length?o[t]:(null==n?delete o[t]:o[t]=n+"",u)},u.mimeType=function(t){return arguments.length?(n=null==t?null:t+"",u):n},u.response=function(t){return c
=t,u},["get","post"].forEach(function(t){u[t]=function(){return u.send.apply(u,[t].concat(Yi(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,t,!0),null==n||"accept"in o||(o.accept=n+",*/*"),l.setRequestHeader)for(var a in o)l.setRequestHeader(a,o[a]);return null!=n&&l.overrideMimeType&&l.overrideMimeType(n),null!=i&&u.on("error",i).on("load",function(t){i(null,t)}),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},qi.rebind(u,i,"on"),2===arguments.length&&"function"==typeof n&&(e=n,n=null),null==e?u:u.get(p(e))},qi.text=function(){return qi.xhr.apply(qi,arguments).response(d)},qi.json=function(t,n){return qi.xhr(t,"application/json",n).response(m)},qi.html=function(t,n){return qi.xhr(t,"text/html",n).response(v)},qi.xml=function(){return qi.xhr.apply(qi,arguments).response(y)};var $i={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/"};qi.ns={prefix:$i,qualify:function(t){var n=t.indexOf(":"),e=t;return n>=0&&(e=t.substring(0,n),t=t.substring(n+1)),$i.hasOwnProperty(e)?{space:$i[e],local:t}:t}},qi.dispatch=function(){for(var t=new M,n=-1,e=arguments.length;e>++n;)t[arguments[n]]=b(t);return t},M.prototype.on=function(t,n){var e=t.indexOf("."),r="";return e>0&&(r=t.substring(e+1),t=t.substring(0,e)),2>arguments.length?this[t].on(r):this[t].on(r,n)},qi.format=function(t){var n=Ji.exec(t),e=n[1]||" ",r=n[2]||">",u=n[3]||"",i=n[4]||"",a=n[5],o=+n[6],c=n[7],l=n[8],f=n[9],s=1,h="",g=!1;switch(l&&(l=+l.substring(1)),(a||"0"===e&&"="===r)&&(a=e="0",r="=",c&&(o-=Math.floor((o-1)/4))),f){case"n":c=!0,f="g";break;case"%":s=100,h="%",f="f";break;case"p":s=100,h="%",f="r";break;case"b":case"o":case"x":case"X":i&&(i="0"+f.toLowerCase());case"c":case"d":g=!0,l=0;break;case"s":s=-1,f="r"}"#"===i&&(i=""),"r"!=f||l||(f="g"),f=Gi.get(f)||_;var p=a&&c;retu
rn function(t){if(g&&t%1)return"";var n=0>t||0===t&&0>1/t?(t=-t,"-"):u;if(0>s){var d=qi.formatPrefix(t,l);t=d.scale(t),h=d.symbol}else t*=s;t=f(t,l),!a&&c&&(t=Ki(t));var m=i.length+t.length+(p?0:n.length),v=o>m?Array(m=o-m+1).join(e):"";return p&&(t=Ki(v+t)),Fi&&t.replace(".",Fi),n+=i,("<"===r?n+t+v:">"===r?v+n+t:"^"===r?v.substring(0,m>>=1)+n+t+v.substring(m):n+(p?t:v+t))+h}};var Ji=/(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,Gi=qi.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,n){return t.toPrecision(n)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},r:function(t,n){return(t=qi.round(t,x(t,n))).toFixed(Math.max(0,Math.min(20,x(t*(1+1e-15),n))))}}),Ki=a;if(ji){var Wi=ji.length;Ki=function(t){for(var n=t.lastIndexOf("."),e=n>=0?"."+t.subs
tring(n+1):(n=t.length,""),r=[],u=0,i=ji[0];n>0&&i>0;)r.push(t.substring(n-=i,n+i)),i=ji[u=(u+1)%Wi];return r.reverse().join(Hi||"")+e}}var Qi=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"].map(w);qi.formatPrefix=function(t,n){var e=0;return t&&(0>t&&(t*=-1),n&&(t=qi.round(t,x(t,n))),e=1+Math.floor(1e-12+Math.log(t)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Qi[8+e/3]};var ta=function(){return a},na=qi.map({linear:ta,poly:q,quad:function(){return A},cubic:function(){return N},sin:function(){return C},exp:function(){return z},circle:function(){return D},elastic:L,back:F,bounce:function(){return H}}),ea=qi.map({"in":a,out:k,"in-out":E,"out-in":function(t){return E(k(t))}});qi.ease=function(t){var n=t.indexOf("-"),e=n>=0?t.substring(0,n):t,r=n>=0?t.substring(n+1):"in";return e=na.get(e)||ta,r=ea.get(r)||a,S(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},qi.event=null,qi.transform=function(t){var n=Di.createElementN
S(qi.ns.prefix.svg,"g");return(qi.transform=function(t){n.setAttribute("transform",t);var e=n.transform.baseVal.consolidate();return new O(e?e.matrix:ra)})(t)},O.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var ra={a:1,b:0,c:0,d:1,e:0,f:0};qi.interpolate=function(t,n){for(var e,r=qi.interpolators.length;--r>=0&&!(e=qi.interpolators[r](t,n)););return e},qi.interpolateNumber=function(t,n){return n-=t,function(e){return t+n*e}},qi.interpolateRound=function(t,n){return n-=t,function(e){return Math.round(t+n*e)}},qi.interpolateString=function(t,n){var e,r,u,i,a,o=0,c=0,l=[],f=[];for(ua.lastIndex=0,r=0;e=ua.exec(n);++r)e.index&&l.push(n.substring(o,c=e.index)),f.push({i:l.length,x:e[0]}),l.push(null),o=ua.lastIndex;for(n.length>o&&l.push(n.substring(o)),r=0,i=f.length;(e=ua.exec(t))&&i>r;++r)if(a=f[r],a.x==e[0]){if(a.i)if(null==l[a.i+1])for(l[a.i-1]+=a.x,l.splice(a.i,1),u=r+1;i>u;++u)f[u].i--;e
lse for(l[a.i-1]+=a.x+l[a.i+1],l.splice(a.i,2),u=r+1;i>u;++u)f[u].i-=2;else if(null==l[a.i+1])l[a.i]=a.x;else for(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1),u=r+1;i>u;++u)f[u].i--;f.splice(r,1),i--,r--}else a.x=qi.interpolateNumber(parseFloat(e[0]),parseFloat(a.x));for(;i>r;)a=f.pop(),null==l[a.i+1]?l[a.i]=a.x:(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1)),i--;return 1===l.length?null==l[0]?f[0].x:function(){return n}:function(t){for(r=0;i>r;++r)l[(a=f[r]).i]=a.x(t);return l.join("")}},qi.interpolateTransform=function(t,n){var e,r=[],u=[],i=qi.transform(t),a=qi.transform(n),o=i.translate,c=a.translate,l=i.rotate,f=a.rotate,s=i.skew,h=a.skew,g=i.scale,p=a.scale;return o[0]!=c[0]||o[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:qi.interpolateNumber(o[0],c[0])},{i:3,x:qi.interpolateNumber(o[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),l!=f?(l-f>180?f+=360:f-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:qi.interpolateNumber(l,f)})):f&&r.pu
sh(r.pop()+"rotate("+f+")"),s!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:qi.interpolateNumber(s,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:qi.interpolateNumber(g[0],p[0])},{i:e-2,x:qi.interpolateNumber(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(t){for(var n,i=-1;e>++i;)r[(n=u[i]).i]=n.x(t);return r.join("")}},qi.interpolateRgb=function(t,n){t=qi.rgb(t),n=qi.rgb(n);var e=t.r,r=t.g,u=t.b,i=n.r-e,a=n.g-r,o=n.b-u;return function(t){return"#"+G(Math.round(e+i*t))+G(Math.round(r+a*t))+G(Math.round(u+o*t))}},qi.interpolateHsl=function(t,n){t=qi.hsl(t),n=qi.hsl(n);var e=t.h,r=t.s,u=t.l,i=n.h-e,a=n.s-r,o=n.l-u;return i>180?i-=360:-180>i&&(i+=360),function(t){return un(e+i*t,r+a*t,u+o*t)+""}},qi.interpolateLab=function(t,n){t=qi.lab(t),n=qi.lab(n);var e=t.l,r=t.a,u=t.b,i=n.l-e,a=n.a-r,o=n.b-u;return function(t){return sn(e+i*t,r+a*t,u+o*t)+""}},qi.interpol
ateHcl=function(t,n){t=qi.hcl(t),n=qi.hcl(n);var e=t.h,r=t.c,u=t.l,i=n.h-e,a=n.c-r,o=n.l-u;return i>180?i-=360:-180>i&&(i+=360),function(t){return cn(e+i*t,r+a*t,u+o*t)+""}},qi.interpolateArray=function(t,n){var e,r=[],u=[],i=t.length,a=n.length,o=Math.min(t.length,n.length);for(e=0;o>e;++e)r.push(qi.interpolate(t[e],n[e]));for(;i>e;++e)u[e]=t[e];for(;a>e;++e)u[e]=n[e];return function(t){for(e=0;o>e;++e)u[e]=r[e](t);return u}},qi.interpolateObject=function(t,n){var e,r={},u={};for(e in t)e in n?r[e]=V(e)(t[e],n[e]):u[e]=t[e];for(e in n)e in t||(u[e]=n[e]);return function(t){for(e in r)u[e]=r[e](t);return u}};var ua=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;qi.interpolators=[qi.interpolateObject,function(t,n){return n instanceof Array&&qi.interpolateArray(t,n)},function(t,n){return("string"==typeof t||"string"==typeof n)&&qi.interpolateString(t+"",n+"")},function(t,n){return("string"==typeof n?aa.has(n)||/^(#|rgb\(|hsl\()/.test(n):n instanceof B)&&qi.interpolateRgb(t,n)},
function(t,n){return!isNaN(t=+t)&&!isNaN(n=+n)&&qi.interpolateNumber(t,n)}],B.prototype.toString=function(){return this.rgb()+""},qi.rgb=function(t,n,e){return 1===arguments.length?t instanceof J?$(t.r,t.g,t.b):K(""+t,$,un):$(~~t,~~n,~~e)};var ia=J.prototype=new B;ia.brighter=function(t){t=Math.pow(.7,arguments.length?t:1);var n=this.r,e=this.g,r=this.b,u=30;return n||e||r?(n&&u>n&&(n=u),e&&u>e&&(e=u),r&&u>r&&(r=u),$(Math.min(255,Math.floor(n/t)),Math.min(255,Math.floor(e/t)),Math.min(255,Math.floor(r/t)))):$(u,u,u)},ia.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),$(Math.floor(t*this.r),Math.floor(t*this.g),Math.floor(t*this.b))},ia.hsl=function(){return W(this.r,this.g,this.b)},ia.toString=function(){return"#"+G(this.r)+G(this.g)+G(this.b)};var aa=qi.map({aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",
brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4
b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orch
id:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"});
-aa.forEach(function(t,n){aa.set(t,K(n,$,un))}),qi.hsl=function(t,n,e){return 1===arguments.length?t instanceof rn?en(t.h,t.s,t.l):K(""+t,W,en):en(+t,+n,+e)};var oa=rn.prototype=new B;oa.brighter=function(t){return t=Math.pow(.7,arguments.length?t:1),en(this.h,this.s,this.l/t)},oa.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),en(this.h,this.s,t*this.l)},oa.rgb=function(){return un(this.h,this.s,this.l)},qi.hcl=function(t,n,e){return 1===arguments.length?t instanceof on?an(t.h,t.c,t.l):t instanceof fn?hn(t.l,t.a,t.b):hn((t=Q((t=qi.rgb(t)).r,t.g,t.b)).l,t.a,t.b):an(+t,+n,+e)};var ca=on.prototype=new B;ca.brighter=function(t){return an(this.h,this.c,Math.min(100,this.l+la*(arguments.length?t:1)))},ca.darker=function(t){return an(this.h,this.c,Math.max(0,this.l-la*(arguments.length?t:1)))},ca.rgb=function(){return cn(this.h,this.c,this.l).rgb()},qi.lab=function(t,n,e){return 1===arguments.length?t instanceof fn?ln(t.l,t.a,t.b):t instanceof on?cn(t.l,t.c,t.h):Q((t=
qi.rgb(t)).r,t.g,t.b):ln(+t,+n,+e)};var la=18,fa=.95047,sa=1,ha=1.08883,ga=fn.prototype=new B;ga.brighter=function(t){return ln(Math.min(100,this.l+la*(arguments.length?t:1)),this.a,this.b)},ga.darker=function(t){return ln(Math.max(0,this.l-la*(arguments.length?t:1)),this.a,this.b)},ga.rgb=function(){return sn(this.l,this.a,this.b)};var pa=function(t,n){return n.querySelector(t)},da=function(t,n){return n.querySelectorAll(t)},ma=Di.documentElement,va=ma.matchesSelector||ma.webkitMatchesSelector||ma.mozMatchesSelector||ma.msMatchesSelector||ma.oMatchesSelector,ya=function(t,n){return va.call(t,n)};"function"==typeof Sizzle&&(pa=function(t,n){return Sizzle(t,n)[0]||null},da=function(t,n){return Sizzle.uniqueSort(Sizzle(t,n))},ya=Sizzle.matchesSelector);var Ma=[];qi.selection=function(){return ba},qi.selection.prototype=Ma,Ma.select=function(t){var n,e,r,u,i=[];"function"!=typeof t&&(t=vn(t));for(var a=-1,o=this.length;o>++a;){i.push(n=[]),n.parentNode=(r=this[a]).parentNode;fo
r(var c=-1,l=r.length;l>++c;)(u=r[c])?(n.push(e=t.call(u,u.__data__,c)),e&&"__data__"in u&&(e.__data__=u.__data__)):n.push(null)}return mn(i)},Ma.selectAll=function(t){var n,e,r=[];"function"!=typeof t&&(t=yn(t));for(var u=-1,i=this.length;i>++u;)for(var a=this[u],o=-1,c=a.length;c>++o;)(e=a[o])&&(r.push(n=Yi(t.call(e,e.__data__,o))),n.parentNode=e);return mn(r)},Ma.attr=function(t,n){if(2>arguments.length){if("string"==typeof t){var e=this.node();return t=qi.ns.qualify(t),t.local?e.getAttributeNS(t.space,t.local):e.getAttribute(t)}for(n in t)this.each(Mn(n,t[n]));return this}return this.each(Mn(t,n))},Ma.classed=function(t,n){if(2>arguments.length){if("string"==typeof t){var e=this.node(),r=(t=t.trim().split(/^|\s+/g)).length,u=-1;if(n=e.classList){for(;r>++u;)if(!n.contains(t[u]))return!1}else for(n=e.className,null!=n.baseVal&&(n=n.baseVal);r>++u;)if(!bn(t[u]).test(n))return!1;return!0}for(n in t)this.each(xn(n,t[n]));return this}return this.each(xn(t,n))},Ma.style=functi
on(t,n,e){var r=arguments.length;if(3>r){if("string"!=typeof t){2>r&&(n="");for(e in t)this.each(wn(e,t[e],n));return this}if(2>r)return Li.getComputedStyle(this.node(),null).getPropertyValue(t);e=""}return this.each(wn(t,n,e))},Ma.property=function(t,n){if(2>arguments.length){if("string"==typeof t)return this.node()[t];for(n in t)this.each(Sn(n,t[n]));return this}return this.each(Sn(t,n))},Ma.text=function(t){return arguments.length?this.each("function"==typeof t?function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}:null==t?function(){this.textContent=""}:function(){this.textContent=t}):this.node().textContent},Ma.html=function(t){return arguments.length?this.each("function"==typeof t?function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}:null==t?function(){this.innerHTML=""}:function(){this.innerHTML=t}):this.node().innerHTML},Ma.append=function(t){function n(){return this.appendChild(Di.createElementNS(this.namespaceURI,t))}function e(){re
turn this.appendChild(Di.createElementNS(t.space,t.local))}return t=qi.ns.qualify(t),this.select(t.local?e:n)},Ma.insert=function(t,n){function e(){return this.insertBefore(Di.createElementNS(this.namespaceURI,t),pa(n,this))}function r(){return this.insertBefore(Di.createElementNS(t.space,t.local),pa(n,this))}return t=qi.ns.qualify(t),this.select(t.local?r:e)},Ma.remove=function(){return this.each(function(){var t=this.parentNode;t&&t.removeChild(this)})},Ma.data=function(t,n){function e(t,e){var r,u,a,o=t.length,s=e.length,h=Math.min(o,s),g=Array(s),p=Array(s),d=Array(o);if(n){var m,v=new i,y=new i,M=[];for(r=-1;o>++r;)m=n.call(u=t[r],u.__data__,r),v.has(m)?d[r]=u:v.set(m,u),M.push(m);for(r=-1;s>++r;)m=n.call(e,a=e[r],r),(u=v.get(m))?(g[r]=u,u.__data__=a):y.has(m)||(p[r]=kn(a)),y.set(m,a),v.remove(m);for(r=-1;o>++r;)v.has(M[r])&&(d[r]=t[r])}else{for(r=-1;h>++r;)u=t[r],a=e[r],u?(u.__data__=a,g[r]=u):p[r]=kn(a);for(;s>r;++r)p[r]=kn(e[r]);for(;o>r;++r)d[r]=t[r]}p.update=g,p.pa
rentNode=g.parentNode=d.parentNode=t.parentNode,c.push(p),l.push(g),f.push(d)}var r,u,a=-1,o=this.length;if(!arguments.length){for(t=Array(o=(r=this[0]).length);o>++a;)(u=r[a])&&(t[a]=u.__data__);return t}var c=qn([]),l=mn([]),f=mn([]);if("function"==typeof t)for(;o>++a;)e(r=this[a],t.call(r,r.parentNode.__data__,a));else for(;o>++a;)e(r=this[a],t);return l.enter=function(){return c},l.exit=function(){return f},l},Ma.datum=function(t){return arguments.length?this.property("__data__",t):this.property("__data__")},Ma.filter=function(t){var n,e,r,u=[];"function"!=typeof t&&(t=En(t));for(var i=0,a=this.length;a>i;i++){u.push(n=[]),n.parentNode=(e=this[i]).parentNode;for(var o=0,c=e.length;c>o;o++)(r=e[o])&&t.call(r,r.__data__,o)&&n.push(r)}return mn(u)},Ma.order=function(){for(var t=-1,n=this.length;n>++t;)for(var e,r=this[t],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},Ma.sort=function(t){t=An.apply(this,arguments
);for(var n=-1,e=this.length;e>++n;)this[n].sort(t);return this.order()},Ma.on=function(t,n,e){var r=arguments.length;if(3>r){if("string"!=typeof t){2>r&&(n=!1);for(e in t)this.each(Nn(e,t[e],n));return this}if(2>r)return(r=this.node()["__on"+t])&&r._;e=!1}return this.each(Nn(t,n,e))},Ma.each=function(t){return Tn(this,function(n,e,r){t.call(n,n.__data__,e,r)})},Ma.call=function(t){var n=Yi(arguments);return t.apply(n[0]=this,n),this},Ma.empty=function(){return!this.node()},Ma.node=function(){for(var t=0,n=this.length;n>t;t++)for(var e=this[t],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},Ma.transition=function(){var t,n,e=_a||++Sa,r=[],u=Object.create(ka);u.time=Date.now();for(var i=-1,a=this.length;a>++i;){r.push(t=[]);for(var o=this[i],c=-1,l=o.length;l>++c;)(n=o[c])&&zn(n,c,e,u),t.push(n)}return Cn(r,e)};var ba=mn([[Di]]);ba[0].parentNode=ma,qi.select=function(t){return"string"==typeof t?ba.select(t):mn([[t]])},qi.selectAll=function(t){return"string"==typ
eof t?ba.selectAll(t):mn([Yi(t)])};var xa=[];qi.selection.enter=qn,qi.selection.enter.prototype=xa,xa.append=Ma.append,xa.insert=Ma.insert,xa.empty=Ma.empty,xa.node=Ma.node,xa.select=function(t){for(var n,e,r,u,i,a=[],o=-1,c=this.length;c>++o;){r=(u=this[o]).update,a.push(n=[]),n.parentNode=u.parentNode;for(var l=-1,f=u.length;f>++l;)(i=u[l])?(n.push(r[l]=e=t.call(u.parentNode,i.__data__,l)),e.__data__=i.__data__):n.push(null)}return mn(a)};var _a,wa=[],Sa=0,ka={ease:T,delay:0,duration:250};wa.call=Ma.call,wa.empty=Ma.empty,wa.node=Ma.node,qi.transition=function(t){return arguments.length?_a?t.transition():t:ba.transition()},qi.transition.prototype=wa,wa.select=function(t){var n,e,r,u=this.id,i=[];"function"!=typeof t&&(t=vn(t));for(var a=-1,o=this.length;o>++a;){i.push(n=[]);for(var c=this[a],l=-1,f=c.length;f>++l;)(r=c[l])&&(e=t.call(r,r.__data__,l))?("__data__"in r&&(e.__data__=r.__data__),zn(e,l,u,r.__transition__[u]),n.push(e)):n.push(null)}return Cn(i,u)},wa.selectAll=
function(t){var n,e,r,u,i,a=this.id,o=[];"function"!=typeof t&&(t=yn(t));for(var c=-1,l=this.length;l>++c;)for(var f=this[c],s=-1,h=f.length;h>++s;)if(r=f[s]){i=r.__transition__[a],e=t.call(r,r.__data__,s),o.push(n=[]);for(var g=-1,p=e.length;p>++g;)zn(u=e[g],g,a,i),n.push(u)}return Cn(o,a)},wa.filter=function(t){var n,e,r,u=[];"function"!=typeof t&&(t=En(t));for(var i=0,a=this.length;a>i;i++){u.push(n=[]);for(var e=this[i],o=0,c=e.length;c>o;o++)(r=e[o])&&t.call(r,r.__data__,o)&&n.push(r)}return Cn(u,this.id,this.time).ease(this.ease())},wa.attr=function(t,n){function e(){this.removeAttribute(i)}function r(){this.removeAttributeNS(i.space,i.local)}if(2>arguments.length){for(n in t)this.attr(n,t[n]);return this}var u=V(t),i=qi.ns.qualify(t);return Ln(this,"attr."+t,n,function(t){function n(){var n,e=this.getAttribute(i);return e!==t&&(n=u(e,t),function(t){this.setAttribute(i,n(t))})}function a(){var n,e=this.getAttributeNS(i.space,i.local);return e!==t&&(n=u(e,t),function(t)
{this.setAttributeNS(i.space,i.local,n(t))})}return null==t?i.local?r:e:(t+="",i.local?a:n)})},wa.attrTween=function(t,n){function e(t,e){var r=n.call(this,t,e,this.getAttribute(u));return r&&function(t){this.setAttribute(u,r(t))}}function r(t,e){var r=n.call(this,t,e,this.getAttributeNS(u.space,u.local));return r&&function(t){this.setAttributeNS(u.space,u.local,r(t))}}var u=qi.ns.qualify(t);return this.tween("attr."+t,u.local?r:e)},wa.style=function(t,n,e){function r(){this.style.removeProperty(t)}var u=arguments.length;if(3>u){if("string"!=typeof t){2>u&&(n="");for(e in t)this.style(e,t[e],n);return this}e=""}var i=V(t);return Ln(this,"style."+t,n,function(n){function u(){var r,u=Li.getComputedStyle(this,null).getPropertyValue(t);return u!==n&&(r=i(u,n),function(n){this.style.setProperty(t,r(n),e)})}return null==n?r:(n+="",u)})},wa.styleTween=function(t,n,e){return 3>arguments.length&&(e=""),this.tween("style."+t,function(r,u){var i=n.call(this,r,u,Li.getComputedStyle(this
,null).getPropertyValue(t));return i&&function(n){this.style.setProperty(t,i(n),e)}})},wa.text=function(t){return Ln(this,"text",t,Dn)},wa.remove=function(){return this.each("end.transition",function(){var t;!this.__transition__&&(t=this.parentNode)&&t.removeChild(this)})},wa.ease=function(t){var n=this.id;return 1>arguments.length?this.node().__transition__[n].ease:("function"!=typeof t&&(t=qi.ease.apply(qi,arguments)),Tn(this,function(e){e.__transition__[n].ease=t}))},wa.delay=function(t){var n=this.id;return Tn(this,"function"==typeof t?function(e,r,u){e.__transition__[n].delay=0|t.call(e,e.__data__,r,u)}:(t|=0,function(e){e.__transition__[n].delay=t}))},wa.duration=function(t){var n=this.id;return Tn(this,"function"==typeof t?function(e,r,u){e.__transition__[n].duration=Math.max(1,0|t.call(e,e.__data__,r,u))}:(t=Math.max(1,0|t),function(e){e.__transition__[n].duration=t}))},wa.each=function(t,n){var e=this.id;if(2>arguments.length){var r=ka,u=_a;_a=e,Tn(this,function(n,r
,u){ka=n.__transition__[e],t.call(n,n.__data__,r,u)}),ka=r,_a=u}else Tn(this,function(r){r.__transition__[e].event.on(t,n)});return this},wa.transition=function(){for(var t,n,e,r,u=this.id,i=++Sa,a=[],o=0,c=this.length;c>o;o++){a.push(t=[]);for(var n=this[o],l=0,f=n.length;f>l;l++)(e=n[l])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,zn(e,l,i,r)),t.push(e)}return Cn(a,i)},wa.tween=function(t,n){var e=this.id;return 2>arguments.length?this.node().__transition__[e].tween.get(t):Tn(this,null==n?function(n){n.__transition__[e].tween.remove(t)}:function(r){r.__transition__[e].tween.set(t,n)})};var Ea,Aa,Na=0,Ta={},qa=null;qi.timer=function(t,n,e){if(3>arguments.length){if(2>arguments.length)n=0;else if(!isFinite(n))return;e=Date.now()}var r=Ta[t.id];r&&r.callback===t?(r.then=e,r.delay=n):Ta[t.id=++Na]=qa={callback:t,then:e,delay:n,next:qa},Ea||(Aa=clearTimeout(Aa),Ea=1,Ca(Fn))},qi.timer.flush=function(){for(var t,n=Date.now(),e=qa;e;)t=n-e.then,e.delay||(e.flush=e.c
allback(t)),e=e.next;Hn()};var Ca=Li.requestAnimationFrame||Li.webkitRequestAnimationFrame||Li.mozRequestAnimationFrame||Li.oRequestAnimationFrame||Li.msRequestAnimationFrame||function(t){setTimeout(t,17)};qi.mouse=function(t){return jn(t,P())};var za=/WebKit/.test(Li.navigator.userAgent)?-1:0;qi.touches=function(t,n){return 2>arguments.length&&(n=P().touches),n?Yi(n).map(function(n){var e=jn(t,n);return e.identifier=n.identifier,e}):[]},qi.scale={},qi.scale.linear=function(){return In([0,1],[0,1],qi.interpolate,!1)},qi.scale.log=function(){return Kn(qi.scale.linear(),Wn)};var Da=qi.format(".0e");Wn.pow=function(t){return Math.pow(10,t)},Qn.pow=function(t){return-Math.pow(10,-t)},qi.scale.pow=function(){return te(qi.scale.linear(),1)},qi.scale.sqrt=function(){return qi.scale.pow().exponent(.5)},qi.scale.ordinal=function(){return ee([],{t:"range",a:[[]]})},qi.scale.category10=function(){return qi.scale.ordinal().range(La)},qi.scale.category20=function(){return qi.scale.ordina
l().range(Fa)},qi.scale.category20b=function(){return qi.scale.ordinal().range(Ha)},qi.scale.category20c=function(){return qi.scale.ordinal().range(ja)};var La=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],Fa=["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"],Ha=["#393b79","#5254a3","#6b6ecf","#9c9ede","#637939","#8ca252","#b5cf6b","#cedb9c","#8c6d31","#bd9e39","#e7ba52","#e7cb94","#843c39","#ad494a","#d6616b","#e7969c","#7b4173","#a55194","#ce6dbd","#de9ed6"],ja=["#3182bd","#6baed6","#9ecae1","#c6dbef","#e6550d","#fd8d3c","#fdae6b","#fdd0a2","#31a354","#74c476","#a1d99b","#c7e9c0","#756bb1","#9e9ac8","#bcbddc","#dadaeb","#636363","#969696","#bdbdbd","#d9d9d9"];qi.scale.quantile=function(){return re([],[])},qi.scale.quantize=function(){return ue(0,1,[0,1])},qi.scale.thres
hold=function(){return ie([.5],[0,1])},qi.scale.identity=function(){return ae([0,1])},qi.svg={},qi.svg.arc=function(){function t(){var t=n.apply(this,arguments),i=e.apply(this,arguments),a=r.apply(this,arguments)+Pa,o=u.apply(this,arguments)+Pa,c=(a>o&&(c=a,a=o,o=c),o-a),l=Ni>c?"0":"1",f=Math.cos(a),s=Math.sin(a),h=Math.cos(o),g=Math.sin(o);return c>=Ra?t?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+t+"A"+t+","+t+" 0 1,0 0,"+-t+"A"+t+","+t+" 0 1,0 0,"+t+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":t?"M"+i*f+","+i*s+"A"+i+","+i+" 0 "+l+",1 "+i*h+","+i*g+"L"+t*h+","+t*g+"A"+t+","+t+" 0 "+l+",0 "+t*f+","+t*s+"Z":"M"+i*f+","+i*s+"A"+i+","+i+" 0 "+l+",1 "+i*h+","+i*g+"L0,0"+"Z"}var n=oe,e=ce,r=le,u=fe;return t.innerRadius=function(e){return arguments.length?(n=c(e),t):n},t.outerRadius=function(n){return arguments.length?(e=c(n),t):e},t.startAngle=function(n){return arguments.length?(r=c(n),t):r},t.endAngle=function(n){return arguments
.length?(u=c(n),t):u},t.centroid=function(){var t=(n.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+Pa;return[Math.cos(i)*t,Math.sin(i)*t]},t};var Pa=-Ni/2,Ra=2*Ni-1e-6;qi.svg.line=function(){return se(a)};var Oa=qi.map({linear:pe,"linear-closed":de,"step-before":me,"step-after":ve,basis:we,"basis-open":Se,"basis-closed":ke,bundle:Ee,cardinal:be,"cardinal-open":ye,"cardinal-closed":Me,monotone:ze});Oa.forEach(function(t,n){n.key=t,n.closed=/-closed$/.test(t)});var Ya=[0,2/3,1/3,0],Ua=[0,1/3,2/3,0],Ia=[0,1/6,2/3,1/6];qi.svg.line.radial=function(){var t=se(De);return t.radius=t.x,delete t.x,t.angle=t.y,delete t.y,t},me.reverse=ve,ve.reverse=me,qi.svg.area=function(){return Le(a)},qi.svg.area.radial=function(){var t=Le(De);return t.radius=t.x,delete t.x,t.innerRadius=t.x0,delete t.x0,t.outerRadius=t.x1,delete t.x1,t.angle=t.y,delete t.y,t.startAngle=t.y0,delete t.y0,t.endAngle=t.y1,delete t.y1,t},qi.svg.chord=function(){fu
nction e(t,n){var e=r(this,o,t,n),c=r(this,l,t,n);return"M"+e.p0+i(e.r,e.p1,e.a1-e.a0)+(u(e,c)?a(e.r,e.p1,e.r,e.p0):a(e.r,e.p1,c.r,c.p0)+i(c.r,c.p1,c.a1-c.a0)+a(c.r,c.p1,e.r,e.p0))+"Z"}function r(t,n,e,r){var u=n.call(t,e,r),i=f.call(t,u,r),a=s.call(t,u,r)+Pa,o=h.call(t,u,r)+Pa;return{r:i,a0:a,a1:o,p0:[i*Math.cos(a),i*Math.sin(a)],p1:[i*Math.cos(o),i*Math.sin(o)]}}function u(t,n){return t.a0==n.a0&&t.a1==n.a1}function i(t,n,e){return"A"+t+","+t+" 0 "+ +(e>Ni)+",1 "+n}function a(t,n,e,r){return"Q 0,0 "+r}var o=n,l=t,f=Fe,s=le,h=fe;return e.radius=function(t){return arguments.length?(f=c(t),e):f},e.source=function(t){return arguments.length?(o=c(t),e):o},e.target=function(t){return arguments.length?(l=c(t),e):l},e.startAngle=function(t){return arguments.length?(s=c(t),e):s},e.endAngle=function(t){return arguments.length?(h=c(t),e):h},e},qi.svg.diagonal=function(){function e(t,n){var e=r.call(this,t,n),a=u.call(this,t,n),o=(e.y+a.y)/2,c=[e,{x:e.x,y:o},{x:a.x,y:o},a];return c=c.
map(i),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var r=n,u=t,i=He;return e.source=function(t){return arguments.length?(r=c(t),e):r},e.target=function(t){return arguments.length?(u=c(t),e):u},e.projection=function(t){return arguments.length?(i=t,e):i},e},qi.svg.diagonal.radial=function(){var t=qi.svg.diagonal(),n=He,e=t.projection;return t.projection=function(t){return arguments.length?e(je(n=t)):n},t},qi.svg.symbol=function(){function t(t,r){return(Va.get(n.call(this,t,r))||Oe)(e.call(this,t,r))}var n=Re,e=Pe;return t.type=function(e){return arguments.length?(n=c(e),t):n},t.size=function(n){return arguments.length?(e=c(n),t):e},t};var Va=qi.map({circle:Oe,cross:function(t){var n=Math.sqrt(t/5)/2;return"M"+-3*n+","+-n+"H"+-n+"V"+-3*n+"H"+n+"V"+-n+"H"+3*n+"V"+n+"H"+n+"V"+3*n+"H"+-n+"V"+n+"H"+-3*n+"Z"},diamond:function(t){var n=Math.sqrt(t/(2*Za)),e=n*Za;return"M0,"+-n+"L"+e+",0"+" 0,"+n+" "+-e+",0"+"Z"},square:function(t){var n=Math.sqrt(t)/2;return"M"+-n+","+-n+"L"+n+","+-n+" "+n+"
,"+n+" "+-n+","+n+"Z"},"triangle-down":function(t){var n=Math.sqrt(t/Xa),e=n*Xa/2;return"M0,"+e+"L"+n+","+-e+" "+-n+","+-e+"Z"},"triangle-up":function(t){var n=Math.sqrt(t/Xa),e=n*Xa/2;return"M0,"+-e+"L"+n+","+e+" "+-n+","+e+"Z"}});qi.svg.symbolTypes=Va.keys();var Xa=Math.sqrt(3),Za=Math.tan(30*Ci);qi.svg.axis=function(){function t(t){t.each(function(){var t,s=qi.select(this),h=null==l?e.ticks?e.ticks.apply(e,c):e.domain():l,g=null==n?e.tickFormat?e.tickFormat.apply(e,c):String:n,p=Ie(e,h,f),d=s.selectAll(".tick.minor").data(p,String),m=d.enter().insert("line",".tick").attr("class","tick minor").style("opacity",1e-6),v=qi.transition(d.exit()).style("opacity",1e-6).remove(),y=qi.transition(d).style("opacity",1),M=s.selectAll(".tick.major").data(h,String),b=M.enter().insert("g","path").attr("class","tick major").style("opacity",1e-6),x=qi.transition(M.exit()).style("opacity",1e-6).remove(),_=qi.transition(M).style("opacity",1),w=On(e),S=s.selectAll(".domain").data([0]),k=(S.en
ter().append("path").attr("class","domain"),qi.transition(S)),E=e.copy(),A=this.__chart__||E;this.__chart__=E,b.append("line"),b.append("text");var N=b.select("line"),T=_.select("line"),q=M.select("text").text(g),C=b.select("text"),z=_.select("text");switch(r){case"bottom":t=Ye,m.attr("y2",i),y.attr("x2",0).attr("y2",i),N.attr("y2",u),C.attr("y",Math.max(u,0)+o),T.attr("x2",0).attr("y2",u),z.attr("x",0).attr("y",Math.max(u,0)+o),q.attr("dy",".71em").style("text-anchor","middle"),k.attr("d","M"+w[0]+","+a+"V0H"+w[1]+"V"+a);break;case"top":t=Ye,m.attr("y2",-i),y.attr("x2",0).attr("y2",-i),N.attr("y2",-u),C.attr("y",-(Math.max(u,0)+o)),T.attr("x2",0).attr("y2",-u),z.attr("x",0).attr("y",-(Math.max(u,0)+o)),q.attr("dy","0em").style("text-anchor","middle"),k.attr("d","M"+w[0]+","+-a+"V0H"+w[1]+"V"+-a);break;case"left":t=Ue,m.attr("x2",-i),y.attr("x2",-i).attr("y2",0),N.attr("x2",-u),C.attr("x",-(Math.max(u,0)+o)),T.attr("x2",-u).attr("y2",0),z.attr("x",-(Math.max(u,0)+o)).attr("y
",0),q.attr("dy",".32em").style("text-anchor","end"),k.attr("d","M"+-a+","+w[0]+"H0V"+w[1]+"H"+-a);break;case"right":t=Ue,m.attr("x2",i),y.attr("x2",i).attr("y2",0),N.attr("x2",u),C.attr("x",Math.max(u,0)+o),T.attr("x2",u).attr("y2",0),z.attr("x",Math.max(u,0)+o).attr("y",0),q.attr("dy",".32em").style("text-anchor","start"),k.attr("d","M"+a+","+w[0]+"H0V"+w[1]+"H"+a)}if(e.ticks)b.call(t,A),_.call(t,E),x.call(t,E),m.call(t,A),y.call(t,E),v.call(t,E);else{var D=E.rangeBand()/2,L=function(t){return E(t)+D};b.call(t,L),_.call(t,L)}})}var n,e=qi.scale.linear(),r=Ba,u=6,i=6,a=6,o=3,c=[10],l=null,f=0;return t.scale=function(n){return arguments.length?(e=n,t):e},t.orient=function(n){return arguments.length?(r=n in $a?n+"":Ba,t):r},t.ticks=function(){return arguments.length?(c=arguments,t):c},t.tickValues=function(n){return arguments.length?(l=n,t):l},t.tickFormat=function(e){return arguments.length?(n=e,t):n},t.tickSize=function(n,e){if(!arguments.length)return u;var r=arguments.len
gth-1;return u=+n,i=r>1?+e:u,a=r>0?+arguments[r]:u,t},t.tickPadding=function(n){return arguments.length?(o=+n,t):o},t.tickSubdivide=function(n){return arguments.length?(f=+n,t):f},t};var Ba="bottom",$a={top:1,right:1,bottom:1,left:1};qi.svg.brush=function(){function t(i){i.each(function(){var i,a=qi.select(this),f=a.selectAll(".background").data([0]),s=a.selectAll(".extent").data([0]),h=a.selectAll(".resize").data(l,String);a.style("pointer-events","all").on("mousedown.brush",u).on("touchstart.brush",u),f.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),s.enter().append("rect").attr("class","extent").style("cursor","move"),h.enter().append("g").attr("class",function(t){return"resize "+t}).style("cursor",function(t){return Ja[t]}).append("rect").attr("x",function(t){return/[ew]$/.test(t)?-3:null}).attr("y",function(t){return/^[ns]/.test(t)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),h.style(
"display",t.empty()?"none":null),h.exit().remove(),o&&(i=On(o),f.attr("x",i[0]).attr("width",i[1]-i[0]),e(a)),c&&(i=On(c),f.attr("y",i[0]).attr("height",i[1]-i[0]),r(a)),n(a)})}function n(t){t.selectAll(".resize").attr("transform",function(t){return"translate("+f[+/e$/.test(t)][0]+","+f[+/^s/.test(t)][1]+")"})}function e(t){t.select(".extent").attr("x",f[0][0]),t.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1][0]-f[0][0])}function r(t){t.select(".extent").attr("y",f[0][1]),t.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1][1]-f[0][1])}function u(){function u(){var t=qi.event.changedTouches;return t?qi.touches(v,t)[0]:qi.mouse(v)}function l(){32==qi.event.keyCode&&(S||(d=null,k[0]-=f[1][0],k[1]-=f[1][1],S=2),j())}function s(){32==qi.event.keyCode&&2==S&&(k[0]+=f[1][0],k[1]+=f[1][1],S=0,j())}function h(){var t=u(),i=!1;m&&(t[0]+=m[0],t[1]+=m[1]),S||(qi.event.altKey?(d||(d=[(f[0][0]+f[1][0])/2,(f[0][1]+f[1][1])/2]),k[0]=f[+(t[0]<d[0])][0],k[1]=f[+(t[1]<d[1])][1]):
d=null),_&&g(t,o,0)&&(e(b),i=!0),w&&g(t,c,1)&&(r(b),i=!0),i&&(n(b),M({type:"brush",mode:S?"move":"resize"}))}function g(t,n,e){var r,u,a=On(n),o=a[0],c=a[1],l=k[e],s=f[1][e]-f[0][e];return S&&(o-=l,c-=s+l),r=Math.max(o,Math.min(c,t[e])),S?u=(r+=l)+s:(d&&(l=Math.max(o,Math.min(c,2*d[e]-r))),r>l?(u=r,r=l):u=l),f[0][e]!==r||f[1][e]!==u?(i=null,f[0][e]=r,f[1][e]=u,!0):void 0}function p(){h(),b.style("pointer-events","all").selectAll(".resize").style("display",t.empty()?"none":null),qi.select("body").style("cursor",null),E.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),M({type:"brushend"}),j()}var d,m,v=this,y=qi.select(qi.event.target),M=a.of(v,arguments),b=qi.select(v),x=y.datum(),_=!/^(n|s)$/.test(x)&&o,w=!/^(e|w)$/.test(x)&&c,S=y.classed("extent"),k=u(),E=qi.select(Li).on("mousemove.brush",h).on("mouseup.brush",p).on("touchmove.brush",h).on("touchend.brush",p).on("keydown
.brush",l).on("keyup.brush",s);if(S)k[0]=f[0][0]-k[0],k[1]=f[0][1]-k[1];else if(x){var A=+/w$/.test(x),N=+/^n/.test(x);m=[f[1-A][0]-k[0],f[1-N][1]-k[1]],k[0]=f[A][0],k[1]=f[N][1]}else qi.event.altKey&&(d=k.slice());b.style("pointer-events","none").selectAll(".resize").style("display",null),qi.select("body").style("cursor",y.style("cursor")),M({type:"brushstart"}),h(),j()}var i,a=R(t,"brushstart","brush","brushend"),o=null,c=null,l=Ga[0],f=[[0,0],[0,0]];return t.x=function(n){return arguments.length?(o=n,l=Ga[!o<<1|!c],t):o},t.y=function(n){return arguments.length?(c=n,l=Ga[!o<<1|!c],t):c},t.extent=function(n){var e,r,u,a,l;return arguments.length?(i=[[0,0],[0,0]],o&&(e=n[0],r=n[1],c&&(e=e[0],r=r[0]),i[0][0]=e,i[1][0]=r,o.invert&&(e=o(e),r=o(r)),e>r&&(l=e,e=r,r=l),f[0][0]=0|e,f[1][0]=0|r),c&&(u=n[0],a=n[1],o&&(u=u[1],a=a[1]),i[0][1]=u,i[1][1]=a,c.invert&&(u=c(u),a=c(a)),u>a&&(l=u,u=a,a=l),f[0][1]=0|u,f[1][1]=0|a),t):(n=i||f,o&&(e=n[0][0],r=n[1][0],i||(e=f[0][0],r=f[1][0],o.in
vert&&(e=o.invert(e),r=o.invert(r)),e>r&&(l=e,e=r,r=l))),c&&(u=n[0][1],a=n[1][1],i||(u=f[0][1],a=f[1][1],c.invert&&(u=c.invert(u),a=c.invert(a)),u>a&&(l=u,u=a,a=l))),o&&c?[[e,u],[r,a]]:o?[e,r]:c&&[u,a])},t.clear=function(){return i=null,f[0][0]=f[0][1]=f[1][0]=f[1][1]=0,t},t.empty=function(){return o&&f[0][0]===f[1][0]||c&&f[0][1]===f[1][1]},qi.rebind(t,a,"on")};var Ja={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ga=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]];qi.behavior={},qi.behavior.drag=function(){function t(){this.on("mousedown.drag",n).on("touchstart.drag",n)}function n(){function t(){var t=o.parentNode;return null!=f?qi.touches(t).filter(function(t){return t.identifier===f})[0]:qi.mouse(t)}function n(){if(!o.parentNode)return u();var n=t(),e=n[0]-s[0],r=n[1]-s[1];h|=e|r,s=n,j(),c({type:"drag",x:n[0]+a[0],y:n[1]+a[1],dx:e,dy:r})}function u(){c({type:"dragend"}),h&&(j(),q
i.event.target===l&&g.on("click.drag",i,!0)),g.on(null!=f?"touchmove.drag-"+f:"mousemove.drag",null).on(null!=f?"touchend.drag-"+f:"mouseup.drag",null)}function i(){j(),g.on("click.drag",null)}var a,o=this,c=e.of(o,arguments),l=qi.event.target,f=qi.event.touches?qi.event.changedTouches[0].identifier:null,s=t(),h=0,g=qi.select(Li).on(null!=f?"touchmove.drag-"+f:"mousemove.drag",n).on(null!=f?"touchend.drag-"+f:"mouseup.drag",u,!0);r?(a=r.apply(o,arguments),a=[a.x-s[0],a.y-s[1]]):a=[0,0],null==f&&j(),c({type:"dragstart"})}var e=R(t,"drag","dragstart","dragend"),r=null;return t.origin=function(n){return arguments.length?(r=n,t):r},qi.rebind(t,e,"on")},qi.behavior.zoom=function(){function t(){this.on("mousedown.zoom",o).on("mousemove.zoom",l).on(Qa+".zoom",c).on("dblclick.zoom",f).on("touchstart.zoom",s).on("touchmove.zoom",h).on("touchend.zoom",s)}function n(t){return[(t[0]-b[0])/x,(t[1]-b[1])/x]}function e(t){return[t[0]*x+b[0],t[1]*x+b[1]]}function r(t){x=Math.max(_[0],Math.m
in(_[1],t))}function u(t,n){n=e(n),b[0]+=t[0]-n[0],b[1]+=t[1]-n[1]}function i(){m&&m.domain(d.range().map(function(t){return(t-b[0])/x}).map(d.invert)),y&&y.domain(v.range().map(function(t){return(t-b[1])/x}).map(v.invert))}function a(t){i(),qi.event.preventDefault(),t({type:"zoom",scale:x,translate:b})}function o(){function t(){l=1,u(qi.mouse(i),s),a(o)}function e(){l&&j(),f.on("mousemove.zoom",null).on("mouseup.zoom",null),l&&qi.event.target===c&&f.on("click.zoom",r,!0)}function r(){j(),f.on("click.zoom",null)}var i=this,o=w.of(i,arguments),c=qi.event.target,l=0,f=qi.select(Li).on("mousemove.zoom",t).on("mouseup.zoom",e),s=n(qi.mouse(i));Li.focus(),j()}function c(){g||(g=n(qi.mouse(this))),r(Math.pow(2,.002*Ka())*x),u(qi.mouse(this),g),a(w.of(this,arguments))}function l(){g=null}function f(){var t=qi.mouse(this),e=n(t),i=Math.log(x)/Math.LN2;r(Math.pow(2,qi.event.shiftKey?Math.ceil(i)-1:Math.floor(i)+1)),u(t,e),a(w.of(this,arguments))}function s(){var t=qi.touches(this),e=
Date.now();if(p=x,g={},t.forEach(function(t){g[t.identifier]=n(t)}),j(),1===t.length){if(500>e-M){var i=t[0],o=n(t[0]);r(2*x),u(i,o),a(w.of(this,arguments))}M=e}}function h(){var t=qi.touches(this),n=t[0],e=g[n.identifier];if(i=t[1]){var i,o=g[i.identifier];n=[(n[0]+i[0])/2,(n[1]+i[1])/2],e=[(e[0]+o[0])/2,(e[1]+o[1])/2],r(qi.event.scale*p)}u(n,e),M=null,a(w.of(this,arguments))}var g,p,d,m,v,y,M,b=[0,0],x=1,_=Wa,w=R(t,"zoom");return t.translate=function(n){return arguments.length?(b=n.map(Number),i(),t):b},t.scale=function(n){return arguments.length?(x=+n,i(),t):x},t.scaleExtent=function(n){return arguments.length?(_=null==n?Wa:n.map(Number),t):_},t.x=function(n){return arguments.length?(m=n,d=n.copy(),b=[0,0],x=1,t):m},t.y=function(n){return arguments.length?(y=n,v=n.copy(),b=[0,0],x=1,t):y},qi.rebind(t,w,"on")};var Ka,Wa=[0,1/0],Qa="onwheel"in document?(Ka=function(){return-qi.event.deltaY*(qi.event.deltaMode?120:1)},"wheel"):"onmousewheel"in document?(Ka=function(){return
qi.event.wheelDelta},"mousewheel"):(Ka=function(){return-qi.event.detail},"MozMousePixelScroll");qi.layout={},qi.layout.bundle=function(){return function(t){for(var n=[],e=-1,r=t.length;r>++e;)n.push(Ve(t[e]));return n}},qi.layout.chord=function(){function t(){var t,l,s,h,g,p={},d=[],m=qi.range(i),v=[];for(e=[],r=[],t=0,h=-1;i>++h;){for(l=0,g=-1;i>++g;)l+=u[h][g];d.push(l),v.push(qi.range(i)),t+=l}for(a&&m.sort(function(t,n){return a(d[t],d[n])}),o&&v.forEach(function(t,n){t.sort(function(t,e){return o(u[n][t],u[n][e])})}),t=(2*Ni-f*i)/t,l=0,h=-1;i>++h;){for(s=l,g=-1;i>++g;){var y=m[h],M=v[y][g],b=u[y][M],x=l,_=l+=b*t;p[y+"-"+M]={index:y,subindex:M,startAngle:x,endAngle:_,value:b}}r[y]={index:y,startAngle:s,endAngle:l,value:(l-s)/t},l+=f}for(h=-1;i>++h;)for(g=h-1;i>++g;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&n()}function n(){e.sort(function(t,n){return c((t.source.value+t.target.value)/2,(n.source
.value+n.target.value)/2)})}var e,r,u,i,a,o,c,l={},f=0;return l.matrix=function(t){return arguments.length?(i=(u=t)&&u.length,e=r=null,l):u},l.padding=function(t){return arguments.length?(f=t,e=r=null,l):f},l.sortGroups=function(t){return arguments.length?(a=t,e=r=null,l):a},l.sortSubgroups=function(t){return arguments.length?(o=t,e=null,l):o},l.sortChords=function(t){return arguments.length?(c=t,e&&n(),l):c},l.chords=function(){return e||t(),e},l.groups=function(){return r||t(),r},l},qi.layout.force=function(){function t(t){return function(n,e,r,u){if(n.point!==t){var i=n.cx-t.x,a=n.cy-t.y,o=1/Math.sqrt(i*i+a*a);if(m>(u-e)*o){var c=n.charge*o*o;return t.px-=i*c,t.py-=a*c,!0}if(n.point&&isFinite(o)){var c=n.pointCharge*o*o;t.px-=i*c,t.py-=a*c}}return!n.charge}}function n(t){t.px=qi.event.x,t.py=qi.event.y,c.resume()}var e,r,u,i,o,c={},l=qi.dispatch("start","tick","end"),f=[1,1],s=.9,h=to,g=no,p=-30,d=.1,m=.8,v=[],y=[];return c.tick=function(){if(.005>(r*=.99))return l.end({t
ype:"end",alpha:r=0}),!0;var n,e,a,c,h,g,m,M,b,x=v.length,_=y.length;for(e=0;_>e;++e)a=y[e],c=a.source,h=a.target,M=h.x-c.x,b=h.y-c.y,(g=M*M+b*b)&&(g=r*i[e]*((g=Math.sqrt(g))-u[e])/g,M*=g,b*=g,h.x-=M*(m=c.weight/(h.weight+c.weight)),h.y-=b*m,c.x+=M*(m=1-m),c.y+=b*m);if((m=r*d)&&(M=f[0]/2,b=f[1]/2,e=-1,m))for(;x>++e;)a=v[e],a.x+=(M-a.x)*m,a.y+=(b-a.y)*m;if(p)for(Ke(n=qi.geom.quadtree(v),r,o),e=-1;x>++e;)(a=v[e]).fixed||n.visit(t(a));for(e=-1;x>++e;)a=v[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*s,a.y-=(a.py-(a.py=a.y))*s);l.tick({type:"tick",alpha:r})},c.nodes=function(t){return arguments.length?(v=t,c):v},c.links=function(t){return arguments.length?(y=t,c):y},c.size=function(t){return arguments.length?(f=t,c):f},c.linkDistance=function(t){return arguments.length?(h="function"==typeof t?t:+t,c):h},c.distance=c.linkDistance,c.linkStrength=function(t){return arguments.length?(g="function"==typeof t?t:+t,c):g},c.friction=function(t){return arguments.length?(s=+t,c):s
},c.charge=function(t){return arguments.length?(p="function"==typeof t?t:+t,c):p},c.gravity=function(t){return arguments.length?(d=+t,c):d},c.theta=function(t){return arguments.length?(m=+t,c):m},c.alpha=function(t){return arguments.length?(t=+t,r?r=t>0?t:0:t>0&&(l.start({type:"start",alpha:r=t}),qi.timer(c.tick)),c):r},c.start=function(){function t(t,r){for(var u,i=n(e),a=-1,o=i.length;o>++a;)if(!isNaN(u=i[a][t]))return u;
-return Math.random()*r}function n(){if(!a){for(a=[],r=0;s>r;++r)a[r]=[];for(r=0;d>r;++r){var t=y[r];a[t.source.index].push(t.target),a[t.target.index].push(t.source)}}return a[e]}var e,r,a,l,s=v.length,d=y.length,m=f[0],M=f[1];for(e=0;s>e;++e)(l=v[e]).index=e,l.weight=0;for(e=0;d>e;++e)l=y[e],"number"==typeof l.source&&(l.source=v[l.source]),"number"==typeof l.target&&(l.target=v[l.target]),++l.source.weight,++l.target.weight;for(e=0;s>e;++e)l=v[e],isNaN(l.x)&&(l.x=t("x",m)),isNaN(l.y)&&(l.y=t("y",M)),isNaN(l.px)&&(l.px=l.x),isNaN(l.py)&&(l.py=l.y);if(u=[],"function"==typeof h)for(e=0;d>e;++e)u[e]=+h.call(this,y[e],e);else for(e=0;d>e;++e)u[e]=h;if(i=[],"function"==typeof g)for(e=0;d>e;++e)i[e]=+g.call(this,y[e],e);else for(e=0;d>e;++e)i[e]=g;if(o=[],"function"==typeof p)for(e=0;s>e;++e)o[e]=+p.call(this,v[e],e);else for(e=0;s>e;++e)o[e]=p;return c.resume()},c.resume=function(){return c.alpha(.1)},c.stop=function(){return c.alpha(0)},c.drag=function(){return e||(e=qi.behavio
r.drag().origin(a).on("dragstart.force",Be).on("drag.force",n).on("dragend.force",$e)),arguments.length?(this.on("mouseover.force",Je).on("mouseout.force",Ge).call(e),void 0):e},qi.rebind(c,l,"on")};var to=20,no=1;qi.layout.partition=function(){function t(n,e,r,u){var i=n.children;if(n.x=e,n.y=n.depth*u,n.dx=r,n.dy=u,i&&(a=i.length)){var a,o,c,l=-1;for(r=n.value?r/n.value:0;a>++l;)t(o=i[l],e,c=o.value*r,u),e+=c}}function n(t){var e=t.children,r=0;if(e&&(u=e.length))for(var u,i=-1;u>++i;)r=Math.max(r,n(e[i]));return 1+r}function e(e,i){var a=r.call(this,e,i);return t(a[0],0,u[0],u[1]/n(a[0])),a}var r=qi.layout.hierarchy(),u=[1,1];return e.size=function(t){return arguments.length?(u=t,e):u},lr(e,r)},qi.layout.pie=function(){function t(i){var a=i.map(function(e,r){return+n.call(t,e,r)}),o=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-r)/qi.sum(a),l=qi.range(i.length);null!=e&&l.sort(e===eo?function(t,n){return a[n]-a[t]}:f
unction(t,n){return e(i[t],i[n])});var f=[];return l.forEach(function(t){var n;f[t]={data:i[t],value:n=a[t],startAngle:o,endAngle:o+=n*c}}),f}var n=Number,e=eo,r=0,u=2*Ni;return t.value=function(e){return arguments.length?(n=e,t):n},t.sort=function(n){return arguments.length?(e=n,t):e},t.startAngle=function(n){return arguments.length?(r=n,t):r},t.endAngle=function(n){return arguments.length?(u=n,t):u},t};var eo={};qi.layout.stack=function(){function t(a,c){var l=a.map(function(e,r){return n.call(t,e,r)}),f=l.map(function(n){return n.map(function(n,e){return[i.call(t,n,e),o.call(t,n,e)]})}),s=e.call(t,f,c);l=qi.permute(l,s),f=qi.permute(f,s);var h,g,p,d=r.call(t,f,c),m=l.length,v=l[0].length;for(g=0;v>g;++g)for(u.call(t,l[0][g],p=d[g],f[0][g][1]),h=1;m>h;++h)u.call(t,l[h][g],p+=f[h-1][g][1],f[h][g][1]);return a}var n=a,e=nr,r=er,u=tr,i=We,o=Qe;return t.values=function(e){return arguments.length?(n=e,t):n},t.order=function(n){return arguments.length?(e="function"==typeof n?n:r
o.get(n)||nr,t):e},t.offset=function(n){return arguments.length?(r="function"==typeof n?n:uo.get(n)||er,t):r},t.x=function(n){return arguments.length?(i=n,t):i},t.y=function(n){return arguments.length?(o=n,t):o},t.out=function(n){return arguments.length?(u=n,t):u},t};var ro=qi.map({"inside-out":function(t){var n,e,r=t.length,u=t.map(rr),i=t.map(ur),a=qi.range(r).sort(function(t,n){return u[t]-u[n]}),o=0,c=0,l=[],f=[];for(n=0;r>n;++n)e=a[n],c>o?(o+=i[e],l.push(e)):(c+=i[e],f.push(e));return f.reverse().concat(l)},reverse:function(t){return qi.range(t.length).reverse()},"default":nr}),uo=qi.map({silhouette:function(t){var n,e,r,u=t.length,i=t[0].length,a=[],o=0,c=[];for(e=0;i>e;++e){for(n=0,r=0;u>n;n++)r+=t[n][e][1];r>o&&(o=r),a.push(r)}for(e=0;i>e;++e)c[e]=(o-a[e])/2;return c},wiggle:function(t){var n,e,r,u,i,a,o,c,l,f=t.length,s=t[0],h=s.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(n=0,u=0;f>n;++n)u+=t[n][e][1];for(n=0,i=0,o=s[e][0]-s[e-1][0];f>n;++n){for(r=0,a=(t[n][e][1]-t[
n][e-1][1])/(2*o);n>r;++r)a+=(t[r][e][1]-t[r][e-1][1])/o;i+=a*t[n][e][1]}g[e]=c-=u?i/u*o:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(t){var n,e,r,u=t.length,i=t[0].length,a=1/u,o=[];for(e=0;i>e;++e){for(n=0,r=0;u>n;n++)r+=t[n][e][1];if(r)for(n=0;u>n;n++)t[n][e][1]/=r;else for(n=0;u>n;n++)t[n][e][1]=a}for(e=0;i>e;++e)o[e]=0;return o},zero:er});qi.layout.histogram=function(){function t(t,i){for(var a,o,c=[],l=t.map(e,this),f=r.call(this,l,i),s=u.call(this,f,l,i),i=-1,h=l.length,g=s.length-1,p=n?1:1/h;g>++i;)a=c[i]=[],a.dx=s[i+1]-(a.x=s[i]),a.y=0;if(g>0)for(i=-1;h>++i;)o=l[i],o>=f[0]&&f[1]>=o&&(a=c[qi.bisect(s,o,1,g)-1],a.y+=p,a.push(t[i]));return c}var n=!0,e=Number,r=cr,u=ar;return t.value=function(n){return arguments.length?(e=n,t):e},t.range=function(n){return arguments.length?(r=c(n),t):r},t.bins=function(n){return arguments.length?(u="number"==typeof n?function(t){return or(t,n)}:c(n),t):u},t.frequency=function(e){return arguments.length?(n=!!e,t):n},t}
,qi.layout.hierarchy=function(){function t(n,a,o){var c=u.call(e,n,a);if(n.depth=a,o.push(n),c&&(l=c.length)){for(var l,f,s=-1,h=n.children=[],g=0,p=a+1;l>++s;)f=t(c[s],p,o),f.parent=n,h.push(f),g+=f.value;r&&h.sort(r),i&&(n.value=g)}else i&&(n.value=+i.call(e,n,a)||0);return n}function n(t,r){var u=t.children,a=0;if(u&&(o=u.length))for(var o,c=-1,l=r+1;o>++c;)a+=n(u[c],l);else i&&(a=+i.call(e,t,r)||0);return i&&(t.value=a),a}function e(n){var e=[];return t(n,0,e),e}var r=hr,u=fr,i=sr;return e.sort=function(t){return arguments.length?(r=t,e):r},e.children=function(t){return arguments.length?(u=t,e):u},e.value=function(t){return arguments.length?(i=t,e):i},e.revalue=function(t){return n(t,0),t},e},qi.layout.pack=function(){function t(t,u){var i=n.call(this,t,u),a=i[0];a.x=0,a.y=0,Lr(a,function(t){t.r=Math.sqrt(t.value)}),Lr(a,yr);var o=r[0],c=r[1],l=Math.max(2*a.r/o,2*a.r/c);if(e>0){var f=e*l/2;Lr(a,function(t){t.r+=f}),Lr(a,yr),Lr(a,function(t){t.r-=f}),l=Math.max(2*a.r/o,2*
a.r/c)}return xr(a,o/2,c/2,1/l),i}var n=qi.layout.hierarchy().sort(pr),e=0,r=[1,1];return t.size=function(n){return arguments.length?(r=n,t):r},t.padding=function(n){return arguments.length?(e=+n,t):e},lr(t,n)},qi.layout.cluster=function(){function t(t,u){var i,a=n.call(this,t,u),o=a[0],c=0;Lr(o,function(t){var n=t.children;n&&n.length?(t.x=Sr(n),t.y=wr(n)):(t.x=i?c+=e(t,i):0,t.y=0,i=t)});var l=kr(o),f=Er(o),s=l.x-e(l,f)/2,h=f.x+e(f,l)/2;return Lr(o,function(t){t.x=(t.x-s)/(h-s)*r[0],t.y=(1-(o.y?t.y/o.y:1))*r[1]}),a}var n=qi.layout.hierarchy().sort(null).value(null),e=Ar,r=[1,1];return t.separation=function(n){return arguments.length?(e=n,t):e},t.size=function(n){return arguments.length?(r=n,t):r},lr(t,n)},qi.layout.tree=function(){function t(t,u){function i(t,n){var r=t.children,u=t._tree;if(r&&(a=r.length)){for(var a,c,l,f=r[0],s=f,h=-1;a>++h;)l=r[h],i(l,c),s=o(l,c,s),c=l;Fr(t);var g=.5*(f._tree.prelim+l._tree.prelim);n?(u.prelim=n._tree.prelim+e(t,n),u.mod=u.prelim-g):u.p
relim=g}else n&&(u.prelim=n._tree.prelim+e(t,n))}function a(t,n){t.x=t._tree.prelim+n;var e=t.children;if(e&&(r=e.length)){var r,u=-1;for(n+=t._tree.mod;r>++u;)a(e[u],n)}}function o(t,n,r){if(n){for(var u,i=t,a=t,o=n,c=t.parent.children[0],l=i._tree.mod,f=a._tree.mod,s=o._tree.mod,h=c._tree.mod;o=Tr(o),i=Nr(i),o&&i;)c=Nr(c),a=Tr(a),a._tree.ancestor=t,u=o._tree.prelim+s-i._tree.prelim-l+e(o,i),u>0&&(Hr(jr(o,t,r),t,u),l+=u,f+=u),s+=o._tree.mod,l+=i._tree.mod,h+=c._tree.mod,f+=a._tree.mod;o&&!Tr(a)&&(a._tree.thread=o,a._tree.mod+=s-f),i&&!Nr(c)&&(c._tree.thread=i,c._tree.mod+=l-h,r=t)}return r}var c=n.call(this,t,u),l=c[0];Lr(l,function(t,n){t._tree={ancestor:t,prelim:0,mod:0,change:0,shift:0,number:n?n._tree.number+1:0}}),i(l),a(l,-l._tree.prelim);var f=qr(l,zr),s=qr(l,Cr),h=qr(l,Dr),g=f.x-e(f,s)/2,p=s.x+e(s,f)/2,d=h.depth||1;return Lr(l,function(t){t.x=(t.x-g)/(p-g)*r[0],t.y=t.depth/d*r[1],delete t._tree}),c}var n=qi.layout.hierarchy().sort(null).value(null),e=Ar,r=[1,1];retu
rn t.separation=function(n){return arguments.length?(e=n,t):e},t.size=function(n){return arguments.length?(r=n,t):r},lr(t,n)},qi.layout.treemap=function(){function t(t,n){for(var e,r,u=-1,i=t.length;i>++u;)r=(e=t[u]).value*(0>n?0:n),e.area=isNaN(r)||0>=r?0:r}function n(e){var i=e.children;if(i&&i.length){var a,o,c,l=s(e),f=[],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(t(h,l.dx*l.dy/e.value),f.area=0;(c=h.length)>0;)f.push(a=h[c-1]),f.area+=a.area,"squarify"!==g||p>=(o=r(f,d))?(h.pop(),p=o):(f.area-=f.pop().area,u(f,d,l,!1),d=Math.min(l.dx,l.dy),f.length=f.area=0,p=1/0);f.length&&(u(f,d,l,!0),f.length=f.area=0),i.forEach(n)}}function e(n){var r=n.children;if(r&&r.length){var i,a=s(n),o=r.slice(),c=[];for(t(o,a.dx*a.dy/n.value),c.area=0;i=o.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?a.dx:a.dy,a,!o.length),c.length=c.area=0);r.forEach(e)}}function r(t,n){for(var e,r=t.area,u=0,i=1/0,a=-1,o=t.length;
o>++a;)(e=t[a].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,n*=n,r?Math.max(n*u*p/r,r/(n*i*p)):1/0}function u(t,n,e,r){var u,i=-1,a=t.length,o=e.x,l=e.y,f=n?c(t.area/n):0;if(n==e.dx){for((r||f>e.dy)&&(f=e.dy);a>++i;)u=t[i],u.x=o,u.y=l,u.dy=f,o+=u.dx=Math.min(e.x+e.dx-o,f?c(u.area/f):0);u.z=!0,u.dx+=e.x+e.dx-o,e.y+=f,e.dy-=f}else{for((r||f>e.dx)&&(f=e.dx);a>++i;)u=t[i],u.x=o,u.y=l,u.dx=f,l+=u.dy=Math.min(e.y+e.dy-l,f?c(u.area/f):0);u.z=!1,u.dy+=e.y+e.dy-l,e.x+=f,e.dx-=f}}function i(r){var u=a||o(r),i=u[0];return i.x=0,i.y=0,i.dx=l[0],i.dy=l[1],a&&o.revalue(i),t([i],i.dx*i.dy/i.value),(a?e:n)(i),h&&(a=u),u}var a,o=qi.layout.hierarchy(),c=Math.round,l=[1,1],f=null,s=Pr,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(t){return arguments.length?(l=t,i):l},i.padding=function(t){function n(n){var e=t.call(i,n,n.depth);return null==e?Pr(n):Rr(n,"number"==typeof e?[e,e,e,e]:e)}function e(n){return Rr(n,t)}if(!arguments.length)return f;var r;return s=null==(f=t)?Pr:"funct
ion"==(r=typeof t)?n:"number"===r?(t=[t,t,t,t],e):e,i},i.round=function(t){return arguments.length?(c=t?Math.round:Number,i):c!=Number},i.sticky=function(t){return arguments.length?(h=t,a=null,i):h},i.ratio=function(t){return arguments.length?(p=t,i):p},i.mode=function(t){return arguments.length?(g=t+"",i):g},lr(i,o)},qi.csv=Or(",","text/csv"),qi.tsv=Or(" ","text/tab-separated-values"),qi.geo={},qi.geo.stream=function(t,n){io.hasOwnProperty(t.type)?io[t.type](t,n):Yr(t,n)};var io={Feature:function(t,n){Yr(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,u=e.length;u>++r;)Yr(e[r].geometry,n)}},ao={Sphere:function(t,n){n.sphere()},Point:function(t,n){var e=t.coordinates;n.point(e[0],e[1])},MultiPoint:function(t,n){for(var e,r=t.coordinates,u=-1,i=r.length;i>++u;)e=r[u],n.point(e[0],e[1])},LineString:function(t,n){Ur(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,u=e.length;u>++r;)Ur(e[r],n,0)},Polygon:function(t,n){Ir(t.c
oordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,u=e.length;u>++r;)Ir(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,u=e.length;u>++r;)Yr(e[r],n)}};qi.geo.albersUsa=function(){function t(t){return n(t)(t)}function n(t){var n=t[0],a=t[1];return a>50?r:-140>n?u:21>a?i:e}var e=qi.geo.albers(),r=qi.geo.albers().rotate([160,0]).center([0,60]).parallels([55,65]),u=qi.geo.albers().rotate([160,0]).center([0,20]).parallels([8,18]),i=qi.geo.albers().rotate([60,0]).center([0,10]).parallels([8,18]);return t.scale=function(n){return arguments.length?(e.scale(n),r.scale(.6*n),u.scale(n),i.scale(1.5*n),t.translate(e.translate())):e.scale()},t.translate=function(n){if(!arguments.length)return e.translate();var a=e.scale(),o=n[0],c=n[1];return e.translate(n),r.translate([o-.4*a,c+.17*a]),u.translate([o-.19*a,c+.2*a]),i.translate([o+.58*a,c+.43*a]),t},t.scale(e.scale())},(qi.geo.albers=function(){var t=29.5*Ci,n=45.5*Ci,e=Fu(Qr),r=e(t,n);return r.p
arallels=function(r){return arguments.length?e(t=r[0]*Ci,n=r[1]*Ci):[t*zi,n*zi]},r.rotate([98,0]).center([0,38]).scale(1e3)}).raw=Qr;var oo=Yu(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(qi.geo.azimuthalEqualArea=function(){return Lu(oo)}).raw=oo;var co=Yu(function(t){var n=Math.acos(t);return n&&n/Math.sin(n)},a);(qi.geo.azimuthalEquidistant=function(){return Lu(co)}).raw=co,qi.geo.bounds=tu(a),qi.geo.centroid=function(t){lo=fo=so=ho=go=0,qi.geo.stream(t,po);var n;return fo&&Math.abs(n=Math.sqrt(so*so+ho*ho+go*go))>Ti?[Math.atan2(ho,so)*zi,Math.asin(Math.max(-1,Math.min(1,go/n)))*zi]:void 0};var lo,fo,so,ho,go,po={sphere:function(){2>lo&&(lo=2,fo=so=ho=go=0)},point:nu,lineStart:ru,lineEnd:uu,polygonStart:function(){2>lo&&(lo=2,fo=so=ho=go=0),po.lineStart=eu},polygonEnd:function(){po.lineStart=ru}};qi.geo.circle=function(){function t(){var t="function"==typeof r?r.apply(this,arguments):r,n=ju(-t[0]*Ci,-t[1]*Ci,0).invert,u=[];return e(null,nu
ll,1,{point:function(t,e){u.push(t=n(t,e)),t[0]*=zi,t[1]*=zi}}),{type:"Polygon",coordinates:[u]}}var n,e,r=[0,0],u=6;return t.origin=function(n){return arguments.length?(r=n,t):r},t.angle=function(r){return arguments.length?(e=iu((n=+r)*Ci,u*Ci),t):n},t.precision=function(r){return arguments.length?(e=iu(n*Ci,(u=+r)*Ci),t):u},t.angle(90)};var mo=ou(o,pu,mu);(qi.geo.equirectangular=function(){return Lu(Mu).scale(250/Ni)}).raw=Mu.invert=Mu;var vo=Yu(function(t){return 1/t},Math.atan);(qi.geo.gnomonic=function(){return Lu(vo)}).raw=vo,qi.geo.graticule=function(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return qi.range(Math.ceil(r/c)*c,e,c).map(a).concat(qi.range(Math.ceil(i/l)*l,u,l).map(o))}var e,r,u,i,a,o,c=22.5,l=c,f=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[a(r).concat(o(u).slice(1),a(e).reverse().slice(1),o(i).reverse().slice(1))
]}},t.extent=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],i=+n[0][1],u=+n[1][1],r>e&&(n=r,r=e,e=n),i>u&&(n=i,i=u,u=n),t.precision(f)):[[r,i],[e,u]]},t.step=function(n){return arguments.length?(c=+n[0],l=+n[1],t):[c,l]},t.precision=function(n){return arguments.length?(f=+n,a=bu(i,u,f),o=xu(r,e,f),t):f},t.extent([[-180+Ti,-90+Ti],[180-Ti,90-Ti]])},qi.geo.interpolate=function(t,n){return _u(t[0]*Ci,t[1]*Ci,n[0]*Ci,n[1]*Ci)},qi.geo.greatArc=function(){function e(){for(var t=r||a.apply(this,arguments),n=u||o.apply(this,arguments),e=i||qi.geo.interpolate(t,n),l=0,f=c/e.distance,s=[t];1>(l+=f);)s.push(e(l));return s.push(n),{type:"LineString",coordinates:s}}var r,u,i,a=n,o=t,c=6*Ci;return e.distance=function(){return(i||qi.geo.interpolate(r||a.apply(this,arguments),u||o.apply(this,arguments))).distance},e.source=function(t){return arguments.length?(a=t,r="function"==typeof t?null:t,i=r&&u?qi.geo.interpolate(r,u):null,e):a},e.target=function(t){return arguments.length?
(o=t,u="function"==typeof t?null:t,i=r&&u?qi.geo.interpolate(r,u):null,e):o},e.precision=function(t){return arguments.length?(c=t*Ci,e):c/Ci},e},wu.invert=function(t,n){return[2*Ni*t,2*Math.atan(Math.exp(2*Ni*n))-Ni/2]},(qi.geo.mercator=function(){return Lu(wu).scale(500)}).raw=wu;var yo=Yu(function(){return 1},Math.asin);(qi.geo.orthographic=function(){return Lu(yo)}).raw=yo,qi.geo.path=function(){function t(t){return t&&qi.geo.stream(t,r(u.pointRadius("function"==typeof i?+i.apply(this,arguments):i))),u.result()}var n,e,r,u,i=4.5;return t.area=function(t){return Mo=0,qi.geo.stream(t,r(xo)),Mo},t.centroid=function(t){return lo=so=ho=go=0,qi.geo.stream(t,r(_o)),go?[so/go,ho/go]:void 0},t.bounds=function(t){return tu(r)(t)},t.projection=function(e){return arguments.length?(r=(n=e)?e.stream||ku(e):a,t):n},t.context=function(n){return arguments.length?(u=null==(e=n)?new Eu:new Au(n),t):e},t.pointRadius=function(n){return arguments.length?(i="function"==typeof n?n:+n,t):i},t.pro
jection(qi.geo.albersUsa()).context(null)};var Mo,bo,xo={point:Pn,lineStart:Pn,lineEnd:Pn,polygonStart:function(){bo=0,xo.lineStart=Nu},polygonEnd:function(){xo.lineStart=xo.lineEnd=xo.point=Pn,Mo+=Math.abs(bo/2)}},_o={point:Tu,lineStart:qu,lineEnd:Cu,polygonStart:function(){_o.lineStart=zu},polygonEnd:function(){_o.point=Tu,_o.lineStart=qu,_o.lineEnd=Cu}};qi.geo.area=function(t){return wo=0,qi.geo.stream(t,Eo),wo};var wo,So,ko,Eo={sphere:function(){wo+=4*Ni},point:Pn,lineStart:Pn,lineEnd:Pn,polygonStart:function(){So=1,ko=0,Eo.lineStart=Du},polygonEnd:function(){var t=2*Math.atan2(ko,So);wo+=0>t?4*Ni+t:t,Eo.lineStart=Eo.lineEnd=Eo.point=Pn}};qi.geo.projection=Lu,qi.geo.projectionMutator=Fu;var Ao=Yu(function(t){return 1/(1+t)},function(t){return 2*Math.atan(t)});(qi.geo.stereographic=function(){return Lu(Ao)}).raw=Ao,qi.geom={},qi.geom.hull=function(t){if(3>t.length)return[];var n,e,r,u,i,a,o,c,l,f,s=t.length,h=s-1,g=[],p=[],d=0;for(n=1;s>n;++n)t[n][1]<t[d][1]?d=n:t[n][1]==
t[d][1]&&(d=t[n][0]<t[d][0]?n:d);for(n=0;s>n;++n)n!==d&&(u=t[n][1]-t[d][1],r=t[n][0]-t[d][0],g.push({angle:Math.atan2(u,r),index:n}));for(g.sort(function(t,n){return t.angle-n.angle}),l=g[0].angle,c=g[0].index,o=0,n=1;h>n;++n)e=g[n].index,l==g[n].angle?(r=t[c][0]-t[d][0],u=t[c][1]-t[d][1],i=t[e][0]-t[d][0],a=t[e][1]-t[d][1],r*r+u*u>=i*i+a*a?g[n].index=-1:(g[o].index=-1,l=g[n].angle,o=n,c=e)):(l=g[n].angle,o=n,c=e);for(p.push(d),n=0,e=0;2>n;++e)-1!==g[e].index&&(p.push(g[e].index),n++);for(f=p.length;h>e;++e)if(-1!==g[e].index){for(;!Uu(p[f-2],p[f-1],g[e].index,t);)--f;p[f++]=g[e].index}var m=[];for(n=0;f>n;++n)m.push(t[p[n]]);return m},qi.geom.polygon=function(t){return t.area=function(){for(var n=0,e=t.length,r=t[e-1][1]*t[0][0]-t[e-1][0]*t[0][1];e>++n;)r+=t[n-1][1]*t[n][0]-t[n-1][0]*t[n][1];return.5*r},t.centroid=function(n){var e,r,u=-1,i=t.length,a=0,o=0,c=t[i-1];for(arguments.length||(n=-1/(6*t.area()));i>++u;)e=c,c=t[u],r=e[0]*c[1]-c[0]*e[1],a+=(e[0]+c[0])*r,o+=(e[1]+c
[1])*r;return[a*n,o*n]},t.clip=function(n){for(var e,r,u,i,a,o,c=-1,l=t.length,f=t[l-1];l>++c;){for(e=n.slice(),n.length=0,i=t[c],a=e[(u=e.length)-1],r=-1;u>++r;)o=e[r],Iu(o,f,i)?(Iu(a,f,i)||n.push(Vu(a,o,f,i)),n.push(o)):Iu(a,f,i)&&n.push(Vu(a,o,f,i)),a=o;f=i}return n},t},qi.geom.voronoi=function(t){var n=t.map(function(){return[]}),e=1e6;return Xu(t,function(t){var r,u,i,a,o,c;1===t.a&&t.b>=0?(r=t.ep.r,u=t.ep.l):(r=t.ep.l,u=t.ep.r),1===t.a?(o=r?r.y:-e,i=t.c-t.b*o,c=u?u.y:e,a=t.c-t.b*c):(i=r?r.x:-e,o=t.c-t.a*i,a=u?u.x:e,c=t.c-t.a*a);var l=[i,o],f=[a,c];n[t.region.l.index].push(l,f),n[t.region.r.index].push(l,f)}),n=n.map(function(n,e){var r=t[e][0],u=t[e][1],i=n.map(function(t){return Math.atan2(t[0]-r,t[1]-u)}),a=qi.range(n.length).sort(function(t,n){return i[t]-i[n]});return a.filter(function(t,n){return!n||i[t]-i[a[n-1]]>Ti}).map(function(t){return n[t]})}),n.forEach(function(n,r){var u=n.length;if(!u)return n.push([-e,-e],[-e,e],[e,e],[e,-e]);if(!(u>2)){var i=t[r],a=n[0
],o=n[1],c=i[0],l=i[1],f=a[0],s=a[1],h=o[0],g=o[1],p=Math.abs(h-f),d=g-s;if(Ti>Math.abs(d)){var m=s>l?-e:e;n.push([-e,m],[e,m])}else if(Ti>p){var v=f>c?-e:e;n.push([v,-e],[v,e])}else{var m=(f-c)*(g-s)>(h-f)*(s-l)?e:-e,y=Math.abs(d)-p;Ti>Math.abs(y)?n.push([0>d?m:-m,m]):(y>0&&(m*=-1),n.push([-e,m],[e,m]))}}}),n};var No={l:"r",r:"l"};qi.geom.delaunay=function(t){var n=t.map(function(){return[]}),e=[];return Xu(t,function(e){n[e.region.l.index].push(t[e.region.r.index])}),n.forEach(function(n,r){var u=t[r],i=u[0],a=u[1];n.forEach(function(t){t.angle=Math.atan2(t[0]-i,t[1]-a)}),n.sort(function(t,n){return t.angle-n.angle});for(var o=0,c=n.length-1;c>o;o++)e.push([u,n[o],n[o+1]])}),e},qi.geom.quadtree=function(t,n,e,r,u){function i(t,n,e,r,u,i){if(!isNaN(n.x)&&!isNaN(n.y))if(t.leaf){var o=t.point;o?.01>Math.abs(o.x-n.x)+Math.abs(o.y-n.y)?a(t,n,e,r,u,i):(t.point=null,a(t,o,e,r,u,i),a(t,n,e,r,u,i)):t.point=n}else a(t,n,e,r,u,i)}function a(t,n,e,r,u,a){var o=.5*(e+u),c=.5*(r+a),l=n.
x>=o,f=n.y>=c,s=(f<<1)+l;t.leaf=!1,t=t.nodes[s]||(t.nodes[s]=Zu()),l?e=o:u=o,f?r=c:a=c,i(t,n,e,r,u,a)}var o,c=-1,l=t.length;if(5>arguments.length)if(3===arguments.length)u=e,r=n,e=n=0;else for(n=e=1/0,r=u=-1/0;l>++c;)o=t[c],n>o.x&&(n=o.x),e>o.y&&(e=o.y),o.x>r&&(r=o.x),o.y>u&&(u=o.y);var f=r-n,s=u-e;f>s?u=e+f:r=n+s;var h=Zu();return h.add=function(t){i(h,t,n,e,r,u)},h.visit=function(t){Bu(t,h,n,e,r,u)},t.forEach(h.add),h},qi.time={};var To=Date,qo=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];$u.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._.getT
ime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){Co.setUTCDate.apply(this._,arguments)},setDay:function(){Co.setUTCDay.apply(this._,arguments)},setFullYear:function(){Co.setUTCFullYear.apply(this._,arguments)},setHours:function(){Co.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){Co.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){Co.setUTCMinutes.apply(this._,arguments)},setMonth:function(){Co.setUTCMonth.apply(this._,arguments)},setSeconds:function(){Co.setUTCSeconds.apply(this._,arguments)},setTime:function(){Co.setTime.apply(this._,arguments)}};var Co=Date.prototype,zo="%a %b %e %X %Y",Do="%m/%d/%Y",Lo="%H:%M:%S",Fo=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],Ho=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],jo=["January","February","March","April","May","June","July","August","September","October","November","December"],Po=["Jan","Feb","Mar","Apr","May"
,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"];qi.time.format=function(t){function n(n){for(var r,u,i,a=[],o=-1,c=0;e>++o;)37===t.charCodeAt(o)&&(a.push(t.substring(c,o)),null!=(u=Xo[r=t.charAt(++o)])&&(r=t.charAt(++o)),(i=Zo[r])&&(r=i(n,null==u?"e"===r?" ":"0":u)),a.push(r),c=o+1);return a.push(t.substring(c,o)),a.join("")}var e=t.length;return n.parse=function(n){var e={y:1900,m:0,d:1,H:0,M:0,S:0,L:0},r=Ju(e,t,n,0);if(r!=n.length)return null;"p"in e&&(e.H=e.H%12+12*e.p);var u=new To;return u.setFullYear(e.y,e.m,e.d),u.setHours(e.H,e.M,e.S,e.L),u},n.toString=function(){return t},n};var Ro=Gu(Fo),Oo=Gu(Ho),Yo=Gu(jo),Uo=Ku(jo),Io=Gu(Po),Vo=Ku(Po),Xo={"-":"",_:" ",0:"0"},Zo={a:function(t){return Ho[t.getDay()]},A:function(t){return Fo[t.getDay()]},b:function(t){return Po[t.getMonth()]},B:function(t){return jo[t.getMonth()]},c:qi.time.format(zo),d:function(t,n){return Wu(t.getDate(),n,2)},e:function(t,n){return Wu(t.getDate(),n,2)},H:function(t,n){return Wu(t.getHours(),n,2)},I:fu
nction(t,n){return Wu(t.getHours()%12||12,n,2)},j:function(t,n){return Wu(1+qi.time.dayOfYear(t),n,3)},L:function(t,n){return Wu(t.getMilliseconds(),n,3)},m:function(t,n){return Wu(t.getMonth()+1,n,2)},M:function(t,n){return Wu(t.getMinutes(),n,2)},p:function(t){return t.getHours()>=12?"PM":"AM"},S:function(t,n){return Wu(t.getSeconds(),n,2)},U:function(t,n){return Wu(qi.time.sundayOfYear(t),n,2)},w:function(t){return t.getDay()},W:function(t,n){return Wu(qi.time.mondayOfYear(t),n,2)},x:qi.time.format(Do),X:qi.time.format(Lo),y:function(t,n){return Wu(t.getFullYear()%100,n,2)},Y:function(t,n){return Wu(t.getFullYear()%1e4,n,4)},Z:mi,"%":function(){return"%"}},Bo={a:Qu,A:ti,b:ni,B:ei,c:ri,d:fi,e:fi,H:si,I:si,L:pi,m:li,M:hi,p:di,S:gi,x:ui,X:ii,y:oi,Y:ai},$o=/^\s*\d+/,Jo=qi.map({am:0,pm:1});qi.time.format.utc=function(t){function n(t){try{To=$u;var n=new To;return n._=t,e(n)}finally{To=Date}}var e=qi.time.format(t);return n.parse=function(t){try{To=$u;var n=e.parse(t);return n&
&n._}finally{To=Date}},n.toString=e.toString,n};var Go=qi.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");qi.time.format.iso=Date.prototype.toISOString?vi:Go,vi.parse=function(t){var n=new Date(t);return isNaN(n)?null:n},vi.toString=Go.toString,qi.time.second=yi(function(t){return new To(1e3*Math.floor(t/1e3))},function(t,n){t.setTime(t.getTime()+1e3*Math.floor(n))},function(t){return t.getSeconds()}),qi.time.seconds=qi.time.second.range,qi.time.seconds.utc=qi.time.second.utc.range,qi.time.minute=yi(function(t){return new To(6e4*Math.floor(t/6e4))},function(t,n){t.setTime(t.getTime()+6e4*Math.floor(n))},function(t){return t.getMinutes()}),qi.time.minutes=qi.time.minute.range,qi.time.minutes.utc=qi.time.minute.utc.range,qi.time.hour=yi(function(t){var n=t.getTimezoneOffset()/60;return new To(36e5*(Math.floor(t/36e5-n)+n))},function(t,n){t.setTime(t.getTime()+36e5*Math.floor(n))},function(t){return t.getHours()}),qi.time.hours=qi.time.hour.range,qi.time.hours.utc=qi.time.hour.utc.ran
ge,qi.time.day=yi(function(t){var n=new To(1970,0);return n.setFullYear(t.getFullYear(),t.getMonth(),t.getDate()),n},function(t,n){t.setDate(t.getDate()+n)},function(t){return t.getDate()-1}),qi.time.days=qi.time.day.range,qi.time.days.utc=qi.time.day.utc.range,qi.time.dayOfYear=function(t){var n=qi.time.year(t);return Math.floor((t-n-6e4*(t.getTimezoneOffset()-n.getTimezoneOffset()))/864e5)},qo.forEach(function(t,n){t=t.toLowerCase(),n=7-n;var e=qi.time[t]=yi(function(t){return(t=qi.time.day(t)).setDate(t.getDate()-(t.getDay()+n)%7),t},function(t,n){t.setDate(t.getDate()+7*Math.floor(n))},function(t){var e=qi.time.year(t).getDay();return Math.floor((qi.time.dayOfYear(t)+(e+n)%7)/7)-(e!==n)});qi.time[t+"s"]=e.range,qi.time[t+"s"].utc=e.utc.range,qi.time[t+"OfYear"]=function(t){var e=qi.time.year(t).getDay();return Math.floor((qi.time.dayOfYear(t)+(e+n)%7)/7)}}),qi.time.week=qi.time.sunday,qi.time.weeks=qi.time.sunday.range,qi.time.weeks.utc=qi.time.sunday.utc.range,qi.time.w
eekOfYear=qi.time.sundayOfYear,qi.time.month=yi(function(t){return t=qi.time.day(t),t.setDate(1),t},function(t,n){t.setMonth(t.getMonth()+n)},function(t){return t.getMonth()}),qi.time.months=qi.time.month.range,qi.time.months.utc=qi.time.month.utc.range,qi.time.year=yi(function(t){return t=qi.time.day(t),t.setMonth(0,1),t},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t){return t.getFullYear()}),qi.time.years=qi.time.year.range,qi.time.years.utc=qi.time.year.utc.range;var Ko=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Wo=[[qi.time.second,1],[qi.time.second,5],[qi.time.second,15],[qi.time.second,30],[qi.time.minute,1],[qi.time.minute,5],[qi.time.minute,15],[qi.time.minute,30],[qi.time.hour,1],[qi.time.hour,3],[qi.time.hour,6],[qi.time.hour,12],[qi.time.day,1],[qi.time.day,2],[qi.time.week,1],[qi.time.month,1],[qi.time.month,3],[qi.time.year,1]],Qo=[[qi.time.format("%Y"),o],[qi.time.format("%B"),function(t){re
turn t.getMonth()}],[qi.time.format("%b %d"),function(t){return 1!=t.getDate()}],[qi.time.format("%a %d"),function(t){return t.getDay()&&1!=t.getDate()}],[qi.time.format("%I %p"),function(t){return t.getHours()}],[qi.time.format("%I:%M"),function(t){return t.getMinutes()}],[qi.time.format(":%S"),function(t){return t.getSeconds()}],[qi.time.format(".%L"),function(t){return t.getMilliseconds()}]],tc=qi.scale.linear(),nc=wi(Qo);Wo.year=function(t,n){return tc.domain(t.map(ki)).ticks(n).map(Si)},qi.time.scale=function(){return bi(qi.scale.linear(),Wo,nc)};var ec=Wo.map(function(t){return[t[0].utc,t[1]]}),rc=[[qi.time.format.utc("%Y"),o],[qi.time.format.utc("%B"),function(t){return t.getUTCMonth()}],[qi.time.format.utc("%b %d"),function(t){return 1!=t.getUTCDate()}],[qi.time.format.utc("%a %d"),function(t){return t.getUTCDay()&&1!=t.getUTCDate()}],[qi.time.format.utc("%I %p"),function(t){return t.getUTCHours()}],[qi.time.format.utc("%I:%M"),function(t){return t.getUTCMinutes()}],
[qi.time.format.utc(":%S"),function(t){return t.getUTCSeconds()}],[qi.time.format.utc(".%L"),function(t){return t.getUTCMilliseconds()}]],uc=wi(rc);return ec.year=function(t,n){return tc.domain(t.map(Ai)).ticks(n).map(Ei)},qi.time.scale.utc=function(){return bi(qi.scale.linear(),ec,uc)},qi}();
\ No newline at end of file
+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 i(){}function u(){}function a(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function o(){}function c(n){function t(){for(var t,r=e,i=-1,u=r.length;++i<u;)(t=r[i].on)&&t.apply(this,arguments);return n}var e=[],r=new i;return t.on=function(t,i){var u,a=r.get(t);return arguments.length<2?a&&a.on:(a&&(a.on=null,e=e.slice(0,u=e.indexOf(a)).concat(e.slice(u+1)),r.remove(t)),i&&e.push(r.set(t,{on:i})),n)},t}function l(){ua.event.stopPropagation(),ua.event.preventDefault()}function f(){for(var n,t=ua.event;n=t.sourceEvent;)t=n;return t}function s(n,t){function e(){n.on(t,null)}n.on(t,function(){l(),e()},!0),setTimeout(e,0)}function h(n){for(var t=new o,e=0,r=arguments.length;++e<r;)t[arguments[e]]=c(
t);return t.of=function(e,r){return function(i){try{var u=i.sourceEvent=ua.event;i.target=n,ua.event=i,t[i.type].apply(e,r)}finally{ua.event=u}}},t}function g(n,t){var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>pa&&(oa.scrollX||oa.scrollY)){e=ua.select(aa.body).append("svg").style("position","absolute").style("top",0).style("left",0);var i=e[0][0].getScreenCTM();pa=!(i.f||i.e),e.remove()}return pa?(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 u=n.getBoundingClientRect();return[t.clientX-u.left-n.clientLeft,t.clientY-u.top-n.clientTop]}function p(n){for(var t=-1,e=n.length,r=[];++t<e;)r.push(n[t]);return r}function d(n){return Array.prototype.slice.call(n)}function m(n){return va(n,wa),n}function v(n){return function(){return ya(n,this)}}function y(n){return function(){return Ma(n,this)}}function M(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS
(n.space,n.local)}function i(){this.setAttribute(n,t)}function u(){this.setAttributeNS(n.space,n.local,t)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ua.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?o:a:n.local?u:i}function x(n){return n.trim().replace(/\s+/g," ")}function b(n){return RegExp("(?:^|\\s+)"+ua.requote(n)+"(?:\\s+|$)","g")}function _(n,t){function e(){for(var e=-1;++e<i;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<i;)n[e](this,r)}n=n.trim().split(/\s+/).map(w);var i=n.length;return"function"==typeof t?r:e}function w(n){var t=b(n);return function(e,r){if(i=e.classList)return r?i.add(n):i.remove(n);var i=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(i)||e.setAttribute("class",x(i+" "+n))):e.setAttribute("class",x(i.replace(t,"
")))}}function S(n,t,e){function r(){this.style.removeProperty(n)}function i(){this.style.setProperty(n,t,e)}function u(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?u:i}function E(n,t){function e(){delete this[n]}function r(){this[n]=t}function i(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?i:r}function k(n){return{__data__:n}}function A(n){return function(){return _a(this,n)}}function N(n){return arguments.length||(n=ua.ascending),function(t,e){return!t-!e||n(t.__data__,e.__data__)}}function q(){}function T(n,t,e){function r(){var t=this[a];t&&(this.removeEventListener(n,t,t.$),delete this[a])}function i(){var i=c(t,da(arguments));r.call(this),this.addEventListener(n,this[a]=i,i.$=e),i._=t}function u(){var t,e=RegExp("^__on([^.]+)"+ua.requote(n)+"$");for(var r in this)if(t=r.match(e)){var i=this[r];this.removeEventListener(t[1
],i,i.$),delete this[r]}}var a="__on"+n,o=n.indexOf("."),c=C;o>0&&(n=n.substring(0,o));var l=ka.get(n);return l&&(n=l,c=z),o?t?i:r:t?q:u}function C(n,t){return function(e){var r=ua.event;ua.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ua.event=r}}}function z(n,t){var e=C(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||r.compareDocumentPosition(t)&8)||e.call(t,n)}}function D(n,t){for(var e=0,r=n.length;r>e;e++)for(var i,u=n[e],a=0,o=u.length;o>a;a++)(i=u[a])&&t(i,a,e);return n}function j(n){return va(n,Aa),n}function L(){}function F(n,t,e){return new H(n,t,e)}function H(n,t,e){this.h=n,this.s=t,this.l=e}function P(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(a-u)*n/60:180>n?a:240>n?u+(a-u)*(240-n)/60:u}function i(n){return Math.round(r(n)*255)}var u,a;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,a=.5>=e?e*(1+t):e+t-e*t,u=2*e-a,tt(i(n+120),i(n),i(n-120))}function R(n){return n>0?1:0>n?-1:0}functio
n O(n){return Math.acos(Math.max(-1,Math.min(1,n)))}function Y(n){return n>1?Da/2:-1>n?-Da/2:Math.asin(n)}function U(n){return(Math.exp(n)-Math.exp(-n))/2}function I(n){return(Math.exp(n)+Math.exp(-n))/2}function V(n){return(n=Math.sin(n/2))*n}function X(n,t,e){return new Z(n,t,e)}function Z(n,t,e){this.h=n,this.c=t,this.l=e}function B(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),$(e,Math.cos(n*=La)*t,Math.sin(n)*t)}function $(n,t,e){return new J(n,t,e)}function J(n,t,e){this.l=n,this.a=t,this.b=e}function G(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=W(i)*Ra,r=W(r)*Oa,u=W(u)*Ya,tt(nt(3.2404542*i-1.5371385*r-.4985314*u),nt(-.969266*i+1.8760108*r+.041556*u),nt(.0556434*i-.2040259*r+1.0572252*u))}function K(n,t,e){return n>0?X(Math.atan2(e,t)*Fa,Math.sqrt(t*t+e*e),n):X(0/0,0/0,n)}function W(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function Q(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function nt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.po
w(n,1/2.4)-.055))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.r=n,this.g=t,this.b=e}function rt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function it(n,t,e){var r,i,u,a=0,o=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(ct(i[0]),ct(i[1]),ct(i[2]))}return(u=Va.get(n))?t(u.r,u.g,u.b):(null!=n&&n.charAt(0)==="#"&&(n.length===4?(a=n.charAt(1),a+=a,o=n.charAt(2),o+=o,c=n.charAt(3),c+=c):n.length===7&&(a=n.substring(1,3),o=n.substring(3,5),c=n.substring(5,7)),a=parseInt(a,16),o=parseInt(o,16),c=parseInt(c,16)),t(a,o,c))}function ut(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),a=Math.max(n,t,e),o=a-u,c=(a+u)/2;return o?(i=.5>c?o/(a+u):o/(2-a-u),r=n==a?(t-e)/o+(e>t?6:0):t==a?(e-n)/o+2:(n-t)/o+4,r*=60):(r=0/0,i=c>0&&1>c?0:r),F(r,i,c)}function at(n,t,e){n=ot(n),t=ot(t),e=ot(e);var r=Q((.4124564*n+.3575761*t+.18
04375*e)/Ra),i=Q((.2126729*n+.7151522*t+.072175*e)/Oa),u=Q((.0193339*n+.119192*t+.9503041*e)/Ya);return $(116*i-16,500*(r-i),200*(i-u))}function ot(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function ct(n){var t=parseFloat(n);return n.charAt(n.length-1)==="%"?Math.round(2.55*t):t}function lt(n){return"function"==typeof n?n:function(){return n}}function ft(n){return n}function st(n){return function(t,e,r){return arguments.length===2&&"function"==typeof e&&(r=e,e=null),ht(t,e,n,r)}}function ht(n,t,e,r){function i(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(u,c)}catch(r){return a.error.call(u,r),void 0}a.load.call(u,n)}else a.error.call(u,c)}var u={},a=ua.dispatch("progress","load","error"),o={},c=new(oa.XDomainRequest&&/^(http(s)?:)?\/\//.test(n)?XDomainRequest:XMLHttpRequest);return"onload"in c?c.onload=c.onerror=i:c.onreadystatechange=function(){c.readyState>3&&i()},c.onprogress=function(n){var t=ua.event;ua.event=n;try{
a.progress.call(u,c)}finally{ua.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?o[n]:(null==t?delete o[n]:o[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(da(arguments)))}}),u.send=function(e,r,i){if(arguments.length===2&&"function"==typeof r&&(i=r,r=null),c.open(e,n,!0),null==t||"accept"in o||(o.accept=t+",*/*"),c.setRequestHeader)for(var a in o)c.setRequestHeader(a,o[a]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),c.send(null==r?null:r),u},u.abort=function(){return c.abort(),u},ua.rebind(u,a,"on"),null==r?u:u.get(gt(r))}function gt(n){return n.length===1?function(t,e){n(null==t?e:null)}:n}function pt(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var a=ua.xhr(n,t,u);return a.row=function(n){return argu
ments.length?a.response((e=n)==null?r:i(n)):e},a.row(e)}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function a(t){return t.map(o).join(n)}function o(n){return c.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var c=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 i=Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return a;if(i)return i=!1,u;var t=f;if(n.charCodeAt(t)===34){for(var e=t;e++<c;)if(n.charCodeAt(e)===34){if(n.charCodeAt(e+1)!==34)break;++e}f=e+2;var r=n.charCodeAt(e+1);return 13===r?(i=!0,n.charCodeAt(e+2)===10&&++f):10===r&&(i=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;c>f;){var r=n.charCodeAt(f++),o=1;if(10===r)i=!0;else if(13===r)i=!0,n.charCodeAt(f)===10&&(++f,++o);else if(r!==
l)continue;return n.substring(t,f-o)}return n.substring(t)}for(var r,i,u={},a={},o=[],c=n.length,f=0,s=0;(r=e())!==a;){for(var h=[];r!==u&&r!==a;)h.push(r),r=e();(!t||(h=t(h,s++)))&&o.push(h)}return o},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new u,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(a).join("\n")},e}function dt(){var n=mt(),t=vt()-n;t>24?(isFinite(t)&&(clearTimeout($a),$a=setTimeout(dt,t)),Ba=0):(Ba=1,Ja(dt))}function mt(){for(var n=Date.now(),t=Xa;t;)n>=t.time&&(t.flush=t.callback(n-t.time)),t=t.next;return n}function vt(){for(var n,t=Xa,e=1/0;t;)t.flush?t=n?n.next=t.next:Xa=t.next:(t.time<e&&(e=t.time),t=(n=t).next);return Za=n,e}function yt(n,t){var e=Math.pow(10,Math.abs(8-t)*3);return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}
function Mt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function xt(n){return n+""}function bt(n,t){n&&uo.hasOwnProperty(n.type)&&uo[n.type](n,t)}function _t(n,t,e){var r,i=-1,u=n.length-e;for(t.lineStart();++i<u;)r=n[i],t.point(r[0],r[1]);t.lineEnd()}function wt(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)_t(n[e],t,1);t.polygonEnd()}function St(){function n(n,t){n*=La,t=t*La/2+Da/4;var e=n-r,a=Math.cos(t),o=Math.sin(t),c=u*o,l=i*a+c*Math.cos(e),f=c*Math.sin(e);oo+=Math.atan2(f,l),r=n,i=a,u=o}var t,e,r,i,u;co.point=function(a,o){co.point=n,r=(t=a)*La,i=Math.cos(o=(e=o)*La/2+Da/4),u=Math.sin(o)},co.lineEnd=function(){n(t,e)}}function Et(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function kt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function At(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Nt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function qt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function
Tt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function Ct(n){return[Math.atan2(n[1],n[0]),Math.asin(Math.max(-1,Math.min(1,n[2])))]}function zt(n,t){return Math.abs(n[0]-t[0])<ja&&Math.abs(n[1]-t[1])<ja}function Dt(n,t){if(!lo){++fo,n*=La;var e=Math.cos(t*=La);so+=(e*Math.cos(n)-so)/fo,ho+=(e*Math.sin(n)-ho)/fo,go+=(Math.sin(t)-go)/fo}}function jt(){var n,t;lo=1,Lt(),lo=2;var e=po.point;po.point=function(r,i){e(n=r,t=i)},po.lineEnd=function(){po.point(n,t),Ft(),po.lineEnd=Ft}}function Lt(){function n(n,i){n*=La;var u=Math.cos(i*=La),a=u*Math.cos(n),o=u*Math.sin(n),c=Math.sin(i),l=Math.atan2(Math.sqrt((l=e*c-r*o)*l+(l=r*a-t*c)*l+(l=t*o-e*a)*l),t*a+e*o+r*c);fo+=l,so+=l*(t+(t=a)),ho+=l*(e+(e=o)),go+=l*(r+(r=c))}var t,e,r;lo>1||(1>lo&&(lo=1,fo=so=ho=go=0),po.point=function(i,u){i*=La;var a=Math.cos(u*=La);t=a*Math.cos(i),e=a*Math.sin(i),r=Math.sin(u),po.point=n})}function Ft(){po.point=Dt}function Ht(){return!0}function Pt(n,t,e,r,i){var u=[],a=[];
if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(zt(e,r)){i.lineStart();for(var o=0;t>o;++o)i.point((e=n[o])[0],e[1]);return i.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,u.push(c),a.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,u.push(c),a.push(l)}}),a.sort(t),Rt(u),Rt(a),u.length){if(e)for(var o=1,c=!e(a[0].point),l=a.length;l>o;++o)a[o].entry=c=!c;for(var f,s,h,g=u[0];;){for(f=g;f.visited;)if((f=f.next)===g)return;s=f.points,i.lineStart();do{if(f.visited=f.other.visited=!0,f.entry){if(f.subject)for(var o=0;o<s.length;o++)i.point((h=s[o])[0],h[1]);else r(f.point,f.next.point,1,i);f=f.next}else{if(f.subject){s=f.prev.points;for(var o=s.length;--o>=0;)i.point((h=s[o])[0],h[1])}else r(f.point,f.prev.point,-1,i);f=f.prev}f=f.other,s=f.points}whil
e(!f.visited);i.lineEnd()}}}function Rt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r<t;)i.next=e=n[r],e.prev=i,i=e;i.next=e=n[0],e.prev=i}}function Ot(n,t,e){return function(r){function i(t,e){n(t,e)&&r.point(t,e)}function u(n,t){m.point(n,t)}function a(){v.point=u,m.lineStart()}function o(){v.point=i,m.lineEnd()}function c(n,t){M.point(n,t),d.push([n,t])}function l(){M.lineStart(),d=[]}function f(){c(d[0][0],d[0][1]),M.lineEnd();var n,t=M.clean(),e=y.buffer(),i=e.length;if(!i)return p=!0,g+=It(d,-1),d=null,void 0;if(d=null,1&t){n=e[0],h+=It(n,1);var u,i=n.length-1,a=-1;for(r.lineStart();++a<i;)r.point((u=n[a])[0],u[1]);return r.lineEnd(),void 0}i>1&&2&t&&e.push(e.pop().concat(e.shift())),s.push(e.filter(Yt))}var s,h,g,p,d,m=t(r),v={point:i,lineStart:a,lineEnd:o,polygonStart:function(){v.point=c,v.lineStart=l,v.lineEnd=f,p=!1,g=h=0,s=[],r.polygonStart()},polygonEnd:function(){v.point=i,v.lineStart=a,v.lineEnd=o,s=ua.merge(s),s.length?Pt(s,Vt,null,e,r):(-ja>h||p&&-ja>g)&&(r.l
ineStart(),e(null,null,1,r),r.lineEnd()),r.polygonEnd(),s=null},sphere:function(){r.polygonStart(),r.lineStart(),e(null,null,1,r),r.lineEnd(),r.polygonEnd()}},y=Ut(),M=t(y);return v}}function Yt(n){return n.length>1}function Ut(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:q,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function It(n,t){if(!(e=n.length))return 0;for(var e,r,i,u=0,a=0,o=n[0],c=o[0],l=o[1],f=Math.cos(l),s=Math.atan2(t*Math.sin(c)*f,Math.sin(l)),h=1-t*Math.cos(c)*f,g=s;++u<e;)o=n[u],f=Math.cos(l=o[1]),r=Math.atan2(t*Math.sin(c=o[0])*f,Math.sin(l)),i=1-t*Math.cos(c)*f,Math.abs(h-2)<ja&&Math.abs(i-2)<ja||(Math.abs(i)<ja||Math.abs(h)<ja||(Math.abs(Math.abs(r-s)-Da)<ja?i+h>2&&(a+=4*(r-s)):a+=Math.abs(h-2)<ja?4*(r-g):((3*Da+r-s)%(2*Da)-Da)*(h+i)),g=s,s=r,h=i);return a}function Vt(n,t){return((n=n.point)[0]<0?n[1]-Da/2-ja:Da/2-n[1])-((t=t.point)[0]<
0?t[1]-Da/2-ja:Da/2-t[1])}function Xt(n){var t,e=0/0,r=0/0,i=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(u,a){var o=u>0?Da:-Da,c=Math.abs(u-e);Math.abs(c-Da)<ja?(n.point(e,r=(r+a)/2>0?Da/2:-Da/2),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(o,r),n.point(u,r),t=0):i!==o&&c>=Da&&(Math.abs(e-i)<ja&&(e-=i*ja),Math.abs(u-o)<ja&&(u-=o*ja),r=Zt(e,r,u,a),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(o,r),t=0),n.point(e=u,r=a),i=o},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function Zt(n,t,e,r){var i,u,a=Math.sin(n-e);return Math.abs(a)>ja?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*a)):(t+r)/2}function Bt(n,t,e,r){var i;if(null==n)i=e*Da/2,r.point(-Da,i),r.point(0,i),r.point(Da,i),r.point(Da,0),r.point(Da,-i),r.point(0,-i),r.point(-Da,-i),r.point(-Da,0),r.point(-Da,i);else if(Math.abs(n[0]-t[0])>ja){var u=(n[0]<t[0]?1:-1)*Da;i=e*u/2,r.point(-u,i),r.point(0,i),r.point(u,i)}else r.
point(t[0],t[1])}function $t(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,c,l,f;return{lineStart:function(){l=c=!1,f=1},point:function(s,h){var g,p=[s,h],d=t(s,h),m=a?d?0:i(s,h):d?i(s+(0>s?Da:-Da),h):0;if(!e&&(l=c=d)&&n.lineStart(),d!==c&&(g=r(e,p),(zt(e,g)||zt(p,g))&&(p[0]+=ja,p[1]+=ja,d=t(p[0],p[1]))),d!==c)f=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(o&&e&&a^d){var v;m&u||!(v=r(p,e,!0))||(f=0,a?(n.lineStart(),n.point(v[0][0],v[0][1]),n.point(v[1][0],v[1][1]),n.lineEnd()):(n.point(v[1][0],v[1][1]),n.lineEnd(),n.lineStart(),n.point(v[0][0],v[0][1])))}!d||e&&zt(e,p)||n.point(p[0],p[1]),e=p,c=d,u=m},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return f|(l&&c)<<1}}}function r(n,t,e){var r=Et(n),i=Et(t),a=[1,0,0],o=At(r,i),c=kt(o,o),l=o[0],f=c-l*l;if(!f)return!e&&n;var s=u*c/f,h=-u*l/f,g=At(a,o),p=qt(a,s),d=qt(o,h);Nt(p,d);var m=g,v=kt(p,m),y=kt(m,m),M=v*v-y*(kt(p,p)-1);if(!(0>
M)){var x=Math.sqrt(M),b=qt(m,(-v-x)/y);if(Nt(b,p),b=Ct(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-Da)<ja,q=N||ja>A;if(!N&&E>k&&(_=E,E=k,k=_),q?N?E+k>0^b[1]<(Math.abs(b[0]-w)<ja?E:k):E<=b[1]&&b[1]<=k:A>Da^(w<=b[0]&&b[0]<=S)){var T=qt(m,(-v+x)/y);return Nt(T,p),[b,Ct(T)]}}}function i(t,e){var r=a?n:Da-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),a=u>0,o=Math.abs(u)>ja,c=oe(n,6*La);return Ot(t,e,c)}function Jt(n,t,e,r){function i(r,i){return Math.abs(r[0]-n)<ja?i>0?0:3:Math.abs(r[0]-e)<ja?i>0?2:1:Math.abs(r[1]-t)<ja?i>0?1:0:i>0?3:2}function u(n,t){return a(n.point,t.point)}function a(n,t){var e=i(n,1),r=i(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 o(i,u){var a=u[0]-i[0],o=u[1]-i[1],c=[0,1];return Math.abs(a)<ja&&Math.abs(o)<ja?n<=i[0]&&i[0]<=e&&t<=i[1]&&i[1]<=r:Gt(n-i[0],a,c)&&Gt(i[0]-e,-a,c)&&Gt(t-i[1],o,c)&&Gt(i[1]-r,-o,c)?(c[1]<1&&(u[0]=i[0]+c[1]*a,u[
1]=i[1]+c[1]*o),c[0]>0&&(i[0]+=c[0]*a,i[1]+=c[0]*o),!0):!1}return function(c){function l(u){var a=i(u,-1),o=f([0===a||3===a?n:e,a>1?r:t]);return o}function f(n){for(var t=0,e=M.length,r=n[1],i=0;e>i;++i)for(var u,a=1,o=M[i],c=o.length,l=o[0];c>a;++a)u=o[a],l[1]<=r?u[1]>r&&s(l,u,n)>0&&++t:u[1]<=r&&s(l,u,n)<0&&--t,l=u;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 h(u,o,c,l){var f=0,s=0;if(null==u||(f=i(u,c))!==(s=i(o,c))||a(u,o)<0^c>0){do l.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+c+4)%4)!==s)}else l.point(o[0],o[1])}function g(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function p(n,t){g(n,t)&&c.point(n,t)}function d(){T.point=v,M&&M.push(x=[]),A=!0,k=!1,S=E=0/0}function m(){y&&(v(b,_),w&&k&&q.rejoin(),y.push(q.buffer())),T.point=p,k&&c.lineEnd()}function v(n,t){n=Math.max(-vo,Math.min(vo,n)),t=Math.max(-vo,Math.min(vo,t));var e=g(n,t);if(M&&x.push([n,t]),A)b=n,_=t,w=e,A=!1,e&&(c.lineStart(),c.point(n,t));else if(e&&k)c.point(n,t);els
e{var r=[S,E],i=[n,t];o(r,i)?(k||(c.lineStart(),c.point(r[0],r[1])),c.point(i[0],i[1]),e||c.lineEnd()):e&&(c.lineStart(),c.point(n,t))}S=n,E=t,k=e}var y,M,x,b,_,w,S,E,k,A,N=c,q=Ut(),T={point:p,lineStart:d,lineEnd:m,polygonStart:function(){c=q,y=[],M=[]},polygonEnd:function(){c=N,(y=ua.merge(y)).length?(c.polygonStart(),Pt(y,u,l,h,c),c.polygonEnd()):f([n,t])&&(c.polygonStart(),c.lineStart(),h(null,null,1,c),c.lineEnd(),c.polygonEnd()),y=M=x=null}};return T}}function Gt(n,t,e){if(Math.abs(t)<ja)return 0>=n;var r=n/t;if(t>0){if(r>e[1])return!1;r>e[0]&&(e[0]=r)}else{if(r<e[0])return!1;r<e[1]&&(e[1]=r)}return!0}function Kt(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function Wt(n){function t(t){function r(e,r){e=n(e,r),t.point(e[0],e[1])}function u(){f=0/0,d.point=a,t.lineStart()}function a(r,u){var a=Et([r,u]),o=n(r,u);e(f,s,l,h,g,p,f=o[0],s=o[1],l=r,h=a[0],g=a[1],p=a[2],i,
t),t.point(f,s)}function o(){d.point=r,t.lineEnd()}function c(){var n,r,c,m,v,y,M;u(),d.point=function(t,e){a(n=t,r=e),c=f,m=s,v=h,y=g,M=p,d.point=a},d.lineEnd=function(){e(f,s,l,h,g,p,c,m,n,v,y,M,i,t),d.lineEnd=o,o()}}var l,f,s,h,g,p,d={point:r,lineStart:u,lineEnd:o,polygonStart:function(){t.polygonStart(),d.lineStart=c},polygonEnd:function(){t.polygonEnd(),d.lineStart=u}};return d}function e(t,i,u,a,o,c,l,f,s,h,g,p,d,m){var v=l-t,y=f-i,M=v*v+y*y;if(M>4*r&&d--){var x=a+h,b=o+g,_=c+p,w=Math.sqrt(x*x+b*b+_*_),S=Math.asin(_/=w),E=Math.abs(Math.abs(_)-1)<ja?(u+s)/2:Math.atan2(b,x),k=n(E,S),A=k[0],N=k[1],q=A-t,T=N-i,C=y*q-v*T;(C*C/M>r||Math.abs((v*q+y*T)/M-.5)>.3)&&(e(t,i,u,a,o,c,A,N,E,x/=w,b/=w,_,d,m),m.point(A,N),e(A,N,E,x,b,_,l,f,s,h,g,p,d,m))}}var r=.5,i=16;return t.precision=function(n){return arguments.length?(i=(r=n*n)>0&&16,t):Math.sqrt(r)},t}function Qt(n){return ne(function(){return n})()}function ne(n){function t(n){return n=a(n[0]*La,n[1]*La),[n[0]*f+o,c-n[1]*f]}func
tion e(n){return n=a.invert((n[0]-o)/f,(c-n[1])/f),n&&[n[0]*Fa,n[1]*Fa]}function r(){a=Kt(u=re(d,m,v),i);var n=i(g,p);return o=s-n[0]*f,c=h+n[1]*f,t}var i,u,a,o,c,l=Wt(function(n,t){return n=i(n,t),[n[0]*f+o,c-n[1]*f]}),f=150,s=480,h=250,g=0,p=0,d=0,m=0,v=0,y=mo,M=ft,x=null,b=null;return t.stream=function(n){return te(u,y(l(M(n))))},t.clipAngle=function(n){return arguments.length?(y=null==n?(x=n,mo):$t((x=+n)*La),t):x},t.clipExtent=function(n){return arguments.length?(b=n,M=null==n?ft:Jt(n[0][0],n[0][1],n[1][0],n[1][1]),t):b},t.scale=function(n){return arguments.length?(f=+n,r()):f},t.translate=function(n){return arguments.length?(s=+n[0],h=+n[1],r()):[s,h]},t.center=function(n){return arguments.length?(g=n[0]%360*La,p=n[1]%360*La,r()):[g*Fa,p*Fa]},t.rotate=function(n){return arguments.length?(d=n[0]%360*La,m=n[1]%360*La,v=n.length>2?n[2]%360*La:0,r()):[d*Fa,m*Fa,v*Fa]},ua.rebind(t,l,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function
te(n,t){return{point:function(e,r){r=n(e*La,r*La),e=r[0],t.point(e>Da?e-2*Da:-Da>e?e+2*Da:e,r[1])},sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}function ee(n,t){return[n,t]}function re(n,t,e){return n?t||e?Kt(ue(n),ae(t,e)):ue(n):t||e?ae(t,e):ee}function ie(n){return function(t,e){return t+=n,[t>Da?t-2*Da:-Da>t?t+2*Da:t,e]}}function ue(n){var t=ie(n);return t.invert=ie(-n),t}function ae(n,t){function e(n,t){var e=Math.cos(t),o=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),f=l*r+o*i;return[Math.atan2(c*u-f*a,o*r-l*i),Math.asin(Math.max(-1,Math.min(1,f*u+c*a)))]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),a=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),o=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),f=l*u-c*a;return[Math.atan2(c*u+l*a,o*r+f*i),Math.asin(Math.max(-1,Math.min(1,f*r-o*i)))]},e}function oe(n,t){var e=Math.cos(n),r=Math.s
in(n);return function(i,u,a,o){null!=i?(i=ce(e,i),u=ce(e,u),(a>0?u>i:i>u)&&(i+=2*a*Da)):(i=n+2*a*Da,u=n);for(var c,l=a*t,f=i;a>0?f>u:u>f;f-=l)o.point((c=Ct([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function ce(n,t){var e=Et(t);e[0]-=n,Tt(e);var r=O(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-ja)%(2*Math.PI)}function le(n,t,e){var r=ua.range(n,t-ja,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fe(n,t,e){var r=ua.range(n,t-ja,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function se(n){return n.source}function he(n){return n.target}function ge(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),a=Math.cos(r),o=Math.sin(r),c=i*Math.cos(n),l=i*Math.sin(n),f=a*Math.cos(e),s=a*Math.sin(e),h=2*Math.asin(Math.sqrt(V(r-t)+i*a*V(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*f,i=e*l+t*s,a=e*u+t*o;return[Math.atan2(i,r)*Fa,Math.atan2(a,Math.sqrt(r*r+i*i))*Fa]}:function(){return[n*Fa,t*Fa]};return
p.distance=h,p}function pe(){function n(n,i){var u=Math.sin(i*=La),a=Math.cos(i),o=Math.abs((n*=La)-t),c=Math.cos(o);yo+=Math.atan2(Math.sqrt((o=a*Math.sin(o))*o+(o=r*u-e*a*c)*o),e*u+r*a*c),t=n,e=u,r=a}var t,e,r;Mo.point=function(i,u){t=i*La,e=Math.sin(u*=La),r=Math.cos(u),Mo.point=n},Mo.lineEnd=function(){Mo.point=Mo.lineEnd=q}}function de(n){var t=0,e=Da/3,r=ne(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Da/180,e=n[1]*Da/180):[180*(t/Da),180*(e/Da)]},i}function me(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),a-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),a=Math.sqrt(u)/i;return e.invert=function(n,t){var e=a-t;return[Math.atan2(n,e)/i,Y((u-(n*n+e*e)*i*i)/(2*i))]},e}function ve(){function n(n,t){bo+=i*n-r*t,r=n,i=t}var t,e,r,i;ko.point=function(u,a){ko.point=n,t=r=u,e=i=a},ko.lineEnd=function(){n(t,e)}}function ye(n,t){_o>n&&(_o=n),n>So&&(So=n),wo>t&&(wo=t),t>Eo&&(Eo=t)}function Me(){
function n(n,t){a.push("M",n,",",t,u)}function t(n,t){a.push("M",n,",",t),o.point=e}function e(n,t){a.push("L",n,",",t)}function r(){o.point=n}function i(){a.push("Z")}var u=xe(4.5),a=[],o={point:n,lineStart:function(){o.point=t},lineEnd:r,polygonStart:function(){o.lineEnd=i},polygonEnd:function(){o.lineEnd=r,o.point=n},pointRadius:function(n){return u=xe(n),o},result:function(){if(a.length){var n=a.join("");return a=[],n}}};return o}function xe(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function be(n,t){lo||(so+=n,ho+=t,++go)}function _e(){function n(n,r){var i=n-t,u=r-e,a=Math.sqrt(i*i+u*u);so+=a*(t+n)/2,ho+=a*(e+r)/2,go+=a,t=n,e=r}var t,e;if(1!==lo){if(!(1>lo))return;lo=1,so=ho=go=0}No.point=function(r,i){No.point=n,t=r,e=i}}function we(){No.point=be}function Se(){function n(n,t){var e=i*n-r*t;so+=e*(r+n),ho+=e*(i+t),go+=3*e,r=n,i=t}var t,e,r,i;2>lo&&(lo=2,so=ho=go=0),No.point=function(u,a){No.point=n,t=r=u,e=i=a},No.lineEnd=function(){n
(t,e)}}function Ee(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,a,0,2*Da)}function e(t,e){n.moveTo(t,e),o.point=r}function r(t,e){n.lineTo(t,e)}function i(){o.point=t}function u(){n.closePath()}var a=4.5,o={point:t,lineStart:function(){o.point=e},lineEnd:i,polygonStart:function(){o.lineEnd=u},polygonEnd:function(){o.lineEnd=i,o.point=t},pointRadius:function(n){return a=n,o},result:q};return o}function ke(n){var t=Wt(function(t,e){return n([t*Fa,e*Fa])});return function(n){return n=t(n),{point:function(t,e){n.point(t*La,e*La)},sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}}function Ae(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),a=Math.cos(i);return[Math.atan2(n*u,r*a),Math.asin(r&&e*u/r)]},e}function Ne(n,t){function
e(n,t){var e=Math.abs(Math.abs(t)-Da/2)<ja?0:a/Math.pow(i(t),u);return[e*Math.sin(u*n),a-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Da/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),a=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=a-t,r=R(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(a/r,1/u))-Da/2]},e):Te}function qe(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return Math.abs(i)<ja?ee:(e.invert=function(n,t){var e=u-t;return[Math.atan2(n,e)/i,u-R(i)*Math.sqrt(n*n+e*e)]},e)}function Te(n,t){return[n,Math.log(Math.tan(Da/4+t/2))]}function Ce(n){var t,e=Qt(n),r=e.scale,i=e.translate,u=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=i.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){v
ar a=u.apply(e,arguments);if(a===e){if(t=null==n){var o=Da*r(),c=i();u([[c[0]-o,c[1]-o],[c[0]+o,c[1]+o]])}}else t&&(a=null);return a},e.clipExtent(null)}function ze(n,t){var e=Math.cos(t)*Math.sin(n);return[Math.log((1+e)/(1-e))/2,Math.atan2(Math.tan(t),Math.cos(n))]}function De(n){function t(t){function a(){l.push("M",u(n(f),o))}for(var c,l=[],f=[],s=-1,h=t.length,g=lt(e),p=lt(r);++s<h;)i.call(this,c=t[s],s)?f.push([+g.call(this,c,s),+p.call(this,c,s)]):f.length&&(a(),f=[]);return f.length&&a(),l.length?l.join(""):null}var e=je,r=Le,i=Ht,u=Fe,a=u.key,o=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(i=n,t):i},t.interpolate=function(n){return arguments.length?(a="function"==typeof n?u=n:(u=jo.get(n)||Fe).key,t):a},t.tension=function(n){return arguments.length?(o=n,t):o},t}function je(n){return n[0]}function Le(n){return n[1]}function Fe(n){return n.join("L")}functio
n He(n){return Fe(n)+"Z"}function Pe(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("V",(r=n[t])[1],"H",r[0]);return i.join("")}function Re(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r=n[t])[0],"V",r[1]);return i.join("")}function Oe(n,t){return n.length<4?Fe(n):n[1]+Ie(n.slice(1,n.length-1),Ve(n,t))}function Ye(n,t){return n.length<3?Fe(n):n[0]+Ie((n.push(n[0]),n),Ve([n[n.length-2]].concat(n,[n[1]]),t))}function Ue(n,t){return n.length<3?Fe(n):n[0]+Ie(n,Ve(n,t))}function Ie(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return Fe(n);var e=n.length!=t.length,r="",i=n[0],u=n[1],a=t[0],o=a,c=1;if(e&&(r+="Q"+(u[0]-a[0]*2/3)+","+(u[1]-a[1]*2/3)+","+u[0]+","+u[1],i=n[1],c=2),t.length>1){o=t[1],u=n[c],c++,r+="C"+(i[0]+a[0])+","+(i[1]+a[1])+","+(u[0]-o[0])+","+(u[1]-o[1])+","+u[0]+","+u[1];for(var l=2;l<t.length;l++,c++)u=n[c],o=t[l],r+="S"+(u[0]-o[0])+","+(u[1]-o[1])+","+u[0]+","+u[1]}if(e){var f=n[c];r+="Q"+(u[0]+o[0]*2/3
)+","+(u[1]+o[1]*2/3)+","+f[0]+","+f[1]}return r}function Ve(n,t){for(var e,r=[],i=(1-t)/2,u=n[0],a=n[1],o=1,c=n.length;++o<c;)e=u,u=a,a=n[o],r.push([i*(a[0]-e[0]),i*(a[1]-e[1])]);return r}function Xe(n){if(n.length<3)return Fe(n);var t=1,e=n.length,r=n[0],i=r[0],u=r[1],a=[i,i,i,(r=n[1])[0]],o=[u,u,u,r[1]],c=[i,",",u];for(Ge(c,a,o);++t<e;)r=n[t],a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ge(c,a,o);for(t=-1;++t<2;)a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ge(c,a,o);return c.join("")}function Ze(n){if(n.length<4)return Fe(n);for(var t,e=[],r=-1,i=n.length,u=[0],a=[0];++r<3;)t=n[r],u.push(t[0]),a.push(t[1]);for(e.push(Je(Ho,u)+","+Je(Ho,a)),--r;++r<i;)t=n[r],u.shift(),u.push(t[0]),a.shift(),a.push(t[1]),Ge(e,u,a);return e.join("")}function Be(n){for(var t,e,r=-1,i=n.length,u=i+4,a=[],o=[];++r<4;)e=n[r%i],a.push(e[0]),o.push(e[1]);for(t=[Je(Ho,a),",",Je(Ho,o)],--r;++r<u;)e=n[r%i],a.shift(),a.push(e[0]),o.shift(),o.push(e[1]),Ge(t,a,o);return t.join("")}function $e(n,t){va
r e=n.length-1;if(e)for(var r,i,u=n[0][0],a=n[0][1],o=n[e][0]-u,c=n[e][1]-a,l=-1;++l<=e;)r=n[l],i=l/e,r[0]=t*r[0]+(1-t)*(u+i*o),r[1]=t*r[1]+(1-t)*(a+i*c);return Xe(n)}function Je(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Ge(n,t,e){n.push("C",Je(Lo,t),",",Je(Lo,e),",",Je(Fo,t),",",Je(Fo,e),",",Je(Ho,t),",",Je(Ho,e))}function Ke(n,t){return(t[1]-n[1])/(t[0]-n[0])
+}function We(n){for(var t=0,e=n.length-1,r=[],i=n[0],u=n[1],a=r[0]=Ke(i,u);++t<e;)r[t]=(a+(a=Ke(i=u,u=n[t+1])))/2;return r[t]=a,r}function Qe(n){for(var t,e,r,i,u=[],a=We(n),o=-1,c=n.length-1;++o<c;)t=Ke(n[o],n[o+1]),Math.abs(t)<1e-6?a[o]=a[o+1]=0:(e=a[o]/t,r=a[o+1]/t,i=e*e+r*r,i>9&&(i=3*t/Math.sqrt(i),a[o]=i*e,a[o+1]=i*r));for(o=-1;++o<=c;)i=(n[Math.min(c,o+1)][0]-n[Math.max(0,o-1)][0])/(6*(1+a[o]*a[o])),u.push([i||0,a[o]*i||0]);return u}function nr(n){return n.length<3?Fe(n):n[0]+Ie(n,Qe(n))}function tr(n,t,e,r){var i,u,a,o,c,l,f;return i=r[n],u=i[0],a=i[1],i=r[t],o=i[0],c=i[1],i=r[e],l=i[0],f=i[1],(f-a)*(o-u)-(c-a)*(l-u)>0}function er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function rr(n,t,e,r){var i=n[0],u=e[0],a=t[0]-i,o=r[0]-u,c=n[1],l=e[1],f=t[1]-c,s=r[1]-l,h=(o*(c-l)-s*(i-u))/(s*a-o*f);return[i+h*a,c+h*f]}function ir(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.y<t.y?-1:n.y>t.y?1:n.x<t.x?-1:n.x>
t.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&&i.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 n.edge==null?e.bottomSite:n.edge.region[n.side]},rightRegion:function(n){return n.edge==null?e.bottomSite:n.edge.region[Po[n.side]]}},i={bisect:function(n,t){var e={region:{l:n,r:t},ep:{l:null,r:null}},r=t.x-n.x,i=t.y-n.y,u=r>0?r:-r,a=i>0?i:-i;return e.c=n.x*r+n.y*i+.5*(r*r+i*i),u>a?(e.a=1,e.b=i/r,e.c/=r):(e.b=1,e.a=r/i,e.c/=i),e},intersect:function(n,t){var e=n.edge,r=t.edge;if(!e|
|!r||e.region.r==r.region.r)return null;var i=e.a*r.b-e.b*r.a;if(Math.abs(i)<1e-10)return null;var u,a,o=(e.c*r.b-r.c*e.b)/i,c=(r.c*e.a-e.c*r.a)/i,l=e.region.r,f=r.region.r;l.y<f.y||l.y==f.y&&l.x<f.x?(u=n,a=e):(u=t,a=r);var s=o>=a.region.r.x;return s&&u.side==="l"||!s&&u.side==="r"?null:{x:o,y:c}},rightOf:function(n,t){var e=n.edge,r=e.region.r,i=t.x>r.x;if(i&&n.side==="l")return 1;if(!i&&n.side==="r")return 0;if(e.a===1){var u=t.y-r.y,a=t.x-r.x,o=0,c=0;if(!i&&e.b<0||i&&e.b>=0?c=o=u>=e.b*a:(c=t.x+t.y*e.b>e.c,e.b<0&&(c=!c),c||(o=1)),!o){var l=r.x-e.region.l.x;c=e.b*(a*a-u*u)<l*u*(1+2*a/l+e.b*e.b),e.b<0&&(c=!c)}}else{var f=e.c-e.a*t.x,s=t.y-f,h=t.x-r.x,g=f-r.y;c=s*s>h*h+g*g}return n.side==="l"?c:!c},endPoint:function(n,e,r){n.ep[e]=r,n.ep[Po[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)}},u={list:[],insert:function(n,t,e){n.vertex=t,n.ystar=t.y+e;for(var r=0,i=u.list,a=i.length;a>r;r++){var o=i[r];if(!(n.ystar>o.ystar||n.ystar==o.ystar&&t.
x>o.vertex.x))break}i.splice(r,0,n)},del:function(n){for(var t=0,e=u.list,r=e.length;r>t&&e[t]!=n;++t);e.splice(t,1)},empty:function(){return u.list.length===0},nextEvent:function(n){for(var t=0,e=u.list,r=e.length;r>t;++t)if(e[t]==n)return e[t+1];return null},min:function(){var n=u.list[0];return{x:n.vertex.x,y:n.ystar}},extractMin:function(){return u.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var a,o,c,l,f,s,h,g,p,d,m,v,y,M=e.list.shift();;)if(u.empty()||(a=u.min()),M&&(u.empty()||M.y<a.y||M.y==a.y&&M.x<a.x))o=r.leftBound(M),c=r.right(o),h=r.rightRegion(o),v=i.bisect(h,M),s=r.createHalfEdge(v,"l"),r.insert(o,s),d=i.intersect(o,s),d&&(u.del(o),u.insert(o,d,i.distance(d,M))),o=s,s=r.createHalfEdge(v,"r"),r.insert(o,s),d=i.intersect(s,c),d&&u.insert(s,d,i.distance(d,M)),M=e.list.shift();else{if(u.empty())break;o=u.extractMin(),l=r.left(o),c=r.right(o),f=r.right(c),h=r.leftRegion(o),g=r.rightRegion(c),m=o.vertex,i.endPoint(o.edge,o.side,m),i.endPoint(c.edge,c.side
,m),r.del(o),u.del(c),r.del(c),y="l",h.y>g.y&&(p=h,h=g,g=p,y="r"),v=i.bisect(h,g),s=r.createHalfEdge(v,y),r.insert(l,s),i.endPoint(v,Po[y],m),d=i.intersect(l,s),d&&(u.del(l),u.insert(l,d,i.distance(d,h))),d=i.intersect(s,f),d&&u.insert(s,d,i.distance(d,h))}for(o=r.right(r.leftEnd);o!=r.rightEnd;o=r.right(o))t(o.edge)}function ur(n){return n.x}function ar(n){return n.y}function or(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function cr(n,t,e,r,i,u){if(!n(t,e,r,i,u)){var a=.5*(e+i),o=.5*(r+u),c=t.nodes;c[0]&&cr(n,c[0],e,r,a,o),c[1]&&cr(n,c[1],a,r,i,o),c[2]&&cr(n,c[2],e,o,a,u),c[3]&&cr(n,c[3],a,o,i,u)}}function lr(n,t){n=ua.rgb(n),t=ua.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,a=t.g-r,o=t.b-i;return function(n){return"#"+rt(Math.round(e+u*n))+rt(Math.round(r+a*n))+rt(Math.round(i+o*n))}}function fr(n){var t=[n.a,n.b],e=[n.c,n.d],r=hr(t),i=sr(t,e),u=hr(gr(e,t,-i))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,i*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1
]))*Fa,this.translate=[n.e,n.f],this.scale=[r,u],this.skew=u?Math.atan2(i,u)*Fa:0}function sr(n,t){return n[0]*t[0]+n[1]*t[1]}function hr(n){var t=Math.sqrt(sr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function gr(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function pr(n,t){return t-=n=+n,function(e){return n+t*e}}function dr(n,t){var e,r=[],i=[],u=ua.transform(n),a=ua.transform(t),o=u.translate,c=a.translate,l=u.rotate,f=a.rotate,s=u.skew,h=a.skew,g=u.scale,p=a.scale;return o[0]!=c[0]||o[1]!=c[1]?(r.push("translate(",null,",",null,")"),i.push({i:1,x:pr(o[0],c[0])},{i:3,x:pr(o[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),l!=f?(l-f>180?f+=360:f-l>180&&(l+=360),i.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:pr(l,f)})):f&&r.push(r.pop()+"rotate("+f+")"),s!=h?i.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:pr(s,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),i.push({i:e-4,x:pr(g[0],p[0])},{i:e-2,x:pr(g[1],p[1]
)})):(p[0]!=1||p[1]!=1)&&r.push(r.pop()+"scale("+p+")"),e=i.length,function(n){for(var t,u=-1;++u<e;)r[(t=i[u]).i]=t.x(n);return r.join("")}}function mr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(e)(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function vr(n,t){var e,r,i,u,a,o=0,c=0,l=[],f=[];for(n+="",t+="",Oo.lastIndex=0,r=0;e=Oo.exec(t);++r)e.index&&l.push(t.substring(o,c=e.index)),f.push({i:l.length,x:e[0]}),l.push(null),o=Oo.lastIndex;for(o<t.length&&l.push(t.substring(o)),r=0,u=f.length;(e=Oo.exec(n))&&u>r;++r)if(a=f[r],a.x==e[0]){if(a.i)if(l[a.i+1]==null)for(l[a.i-1]+=a.x,l.splice(a.i,1),i=r+1;u>i;++i)f[i].i--;else for(l[a.i-1]+=a.x+l[a.i+1],l.splice(a.i,2),i=r+1;u>i;++i)f[i].i-=2;else if(l[a.i+1]==null)l[a.i]=a.x;else for(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1),i=r+1;u>i;++i)f[i].i--;f.splice(r,1),u--,r--}else a.x=pr(parseFloat(e[0]),parseFloat(a.x));for(;u>r;)a=f.pop(),l[a.i+1]==null?l[a.i]=a.x:(l[a.i]=a.x
+l[a.i+1],l.splice(a.i+1,1)),u--;return l.length===1?l[0]==null?(a=f[0].x,function(n){return a(n)+""}):function(){return t}:function(n){for(r=0;u>r;++r)l[(a=f[r]).i]=a.x(n);return l.join("")}}function yr(n,t){for(var e,r=ua.interpolators.length;--r>=0&&!(e=ua.interpolators[r](n,t)););return e}function Mr(n){return"transform"==n?dr:yr}function xr(n,t){var e,r=[],i=[],u=n.length,a=t.length,o=Math.min(n.length,t.length);for(e=0;o>e;++e)r.push(yr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;a>e;++e)i[e]=t[e];return function(n){for(e=0;o>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function Er(n){return n*n*n}function kr(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 Ar(n){return function(t){return Math.pow(t,n)}}function Nr(n){return 1-Math.cos(n*Da/
2)}function qr(n){return Math.pow(2,10*(n-1))}function Tr(n){return 1-Math.sqrt(1-n*n)}function Cr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/(2*Da)*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,10*-r)*Math.sin(2*(r-e)*Da/t)}}function zr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Dr(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 jr(n,t){n=ua.hcl(n),t=ua.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,a=t.c-r,o=t.l-i;return isNaN(a)&&(a=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return B(e+u*n,r+a*n,i+o*n)+""}}function Lr(n,t){n=ua.hsl(n),t=ua.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,a=t.s-r,o=t.l-i;return isNaN(a)&&(a=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return P(e+u*n,r+a*n,i+o*n)+""}}function Fr(n,t){n=ua.lab(n),t=ua
.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,a=t.a-r,o=t.b-i;return function(n){return G(e+u*n,r+a*n,i+o*n)+""}}function Hr(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pr(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Rr(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Or(n){for(var t=n.source,e=n.target,r=Ur(t,e),i=[t];t!==r;)t=t.parent,i.push(t);for(var u=i.length;e!==r;)i.splice(u,0,e),e=e.parent;return i}function Yr(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Ur(n,t){if(n===t)return n;for(var e=Yr(n),r=Yr(t),i=e.pop(),u=r.pop(),a=null;i===u;)a=i,i=e.pop(),u=r.pop();return a}function Ir(n){n.fixed|=2}function Vr(n){n.fixed&=-7}function Xr(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Zr(n){n.fixed&=-5}function Br(n,t,e){var r=0,i=0;if(n.charge=0,!n.leaf)for(var u,a=n.nodes,o=a.length,c=-1;++c<o;)u=a[c],null!=u&&(Br(u,t,e),n.charge+=u.charge,r+=u.charge*u
.cx,i+=u.charge*u.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var l=t*e[n.point.index];n.charge+=n.pointCharge=l,r+=l*n.point.x,i+=l*n.point.y}n.cx=r/n.charge,n.cy=i/n.charge}function $r(n,t){return ua.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wr,n}function Jr(n){return n.children}function Gr(n){return n.value}function Kr(n,t){return t.value-n.value}function Wr(n){return ua.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Qr(n){return n.x}function ni(n){return n.y}function ti(n,t,e){n.y0=t,n.y=e}function ei(n){return ua.range(n.length)}function ri(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ii(n){for(var t,e=1,r=0,i=n[0][1],u=n.length;u>e;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function ui(n){return n.reduce(ai,0)}function ai(n,t){return n+t[1]}function oi(n,t){return ci(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ci(n,t){for(var e=-1,r=+n[0
],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function li(n){return[ua.min(n),ua.max(n)]}function fi(n,t){return n.parent==t.parent?1:2}function si(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function hi(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function gi(n,t){var e=n.children;if(e&&(i=e.length))for(var r,i,u=-1;++u<i;)t(r=gi(e[u],t),n)>0&&(n=r);return n}function pi(n,t){return n.x-t.x}function di(n,t){return t.x-n.x}function mi(n,t){return n.depth-t.depth}function vi(n,t){function e(n,r){var i=n.children;if(i&&(a=i.length))for(var u,a,o=null,c=-1;++c<a;)u=i[c],e(u,o),o=u;t(n,r)}e(n,null)}function yi(n){for(var t,e=0,r=0,i=n.children,u=i.length;--u>=0;)t=i[u]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function Mi(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 xi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function bi(n,t){return
n.value-t.value}function _i(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function wi(n,t){n._pack_next=t,t._pack_prev=n}function Si(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return i*i-e*e-r*r>.001}function Ei(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),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,i,u,a,o,c,l,f=1/0,s=-1/0,h=1/0,g=-1/0;if(e.forEach(ki),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(i=e[1],i.x=i.r,i.y=0,t(i),l>2))for(u=e[2],qi(r,i,u),t(u),_i(r,u),r._pack_prev=u,_i(u,i),i=r._pack_next,a=3;l>a;a++){qi(r,i,u=e[a]);var p=0,d=1,m=1;for(o=i._pack_next;o!==i;o=o._pack_next,d++)if(Si(o,u)){p=1;break}if(1==p)for(c=r._pack_prev;c!==o._pack_prev&&!Si(c,u);c=c._pack_prev,m++);p?(m>d||d==m&&i.r<r.r?wi(r,i=o):wi(r=c,i),a--):(_i(r,u),i=u,t(u))}var v=(f+s)/2,y=(h+g)/2,M=0;for(a=0;l>a;a++)u=e[a],u.x-=v,u.y-=y,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function ki(n){n._pack_n
ext=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ni(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,a=i.length;++u<a;)Ni(i[u],t,e,r)}function qi(n,t,e){var r=n.r+e.r,i=t.x-n.x,u=t.y-n.y;if(r&&(i||u)){var a=t.r+e.r,o=i*i+u*u;a*=a,r*=r;var c=.5+(r-a)/(2*o),l=Math.sqrt(Math.max(0,2*a*(r+o)-(r-=o)*r-a*a))/(2*o);e.x=n.x+c*i+l*u,e.y=n.y+c*u-l*i}else e.x=n.x+r,e.y=n.y}function Ti(n){return 1+ua.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function zi(n){var t=n.children;return t&&t.length?zi(t[0]):n}function Di(n){var t,e=n.children;return e&&(t=e.length)?Di(e[t-1]):n}function ji(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Li(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Fi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Hi(n){return n.rangeExtent?n.rangeEx
tent():Fi(n.range())}function Pi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Ri(n,t){var e,r=0,i=n.length-1,u=n[r],a=n[i];return u>a&&(e=r,r=i,i=e,e=u,u=a,a=e),(t=t(a-u))&&(n[r]=t.floor(u),n[i]=t.ceil(a)),n}function Oi(n,t,e,r){var i=[],u=[],a=0,o=Math.min(n.length,t.length)-1;for(n[o]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++a<=o;)i.push(e(n[a-1],n[a])),u.push(r(t[a-1],t[a]));return function(t){var e=ua.bisect(n,t,1,o)-1;return u[e](i[e](t))}}function Yi(n,t,e,r){function i(){var i=Math.min(n.length,t.length)>2?Oi:Pi,c=r?Rr:Pr;return a=i(n,t,c,e),o=i(t,n,c,yr),u}function u(n){return a(n)}var a,o;return u.invert=function(n){return o(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Hr)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.l
ength?(e=n,i()):e},u.ticks=function(t){return Xi(n,t)},u.tickFormat=function(t,e){return Zi(n,t,e)},u.nice=function(){return Ri(n,Ii),i()},u.copy=function(){return Yi(n,t,e,r)},i()}function Ui(n,t){return ua.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Ii(n){return n=Math.pow(10,Math.round(Math.log(n)/Math.LN10)-1),n&&{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}}function Vi(n,t){var e=Fi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Xi(n,t){return ua.range.apply(ua,Vi(n,t))}function Zi(n,t,e){var r=-Math.floor(Math.log(Vi(n,t)[2])/Math.LN10+.01);return ua.format(e?e.replace(no,function(n,t,e,i,u,a,o,c,l,f){return[t,e,i,u,a,o,c,l||"."+(r-2*("%"===f)),f].join("")}):",."+r+"f")}function Bi(n,t,e,r,i){function u(t){return n(e(t))}function a(){return e===$i?{floor:o,ceil:c}
:{floor:function(n){return-c(-n)},ceil:function(n){return-o(-n)}}}function o(n){return Math.pow(t,Math.floor(Math.log(n)/Math.log(t)))}function c(n){return Math.pow(t,Math.ceil(Math.log(n)/Math.log(t)))}return u.invert=function(t){return r(n.invert(t))},u.domain=function(t){return arguments.length?(t[0]<0?(e=Gi,r=Ki):(e=$i,r=Ji),n.domain((i=t.map(Number)).map(e)),u):i},u.base=function(n){return arguments.length?(t=+n,u):t},u.nice=function(){return n.domain(Ri(i,a).map(e)),u},u.ticks=function(){var i=Fi(n.domain()),u=[];if(i.every(isFinite)){var a=Math.log(t),o=Math.floor(i[0]/a),c=Math.ceil(i[1]/a),l=r(i[0]),f=r(i[1]),s=t%1?2:t;if(e===Gi)for(u.push(-Math.pow(t,-o));o++<c;)for(var h=s-1;h>0;h--)u.push(-Math.pow(t,-o)*h);else{for(;c>o;o++)for(var h=1;s>h;h++)u.push(Math.pow(t,o)*h);u.push(Math.pow(t,o))}for(o=0;u[o]<l;o++);for(c=u.length;u[c-1]>f;c--);u=u.slice(o,c)}return u},u.tickFormat=function(n,i){if(arguments.length<2&&(i=Jo),!arguments.length)return i;var a,o=Math.log(t
),c=Math.max(.1,n/u.ticks().length),l=e===Gi?(a=-1e-12,Math.floor):(a=1e-12,Math.ceil);return function(n){return n/r(o*l(e(n)/o+a))<=c?i(n):""}},u.copy=function(){return Bi(n.copy(),t,e,r,i)},Ui(u,n)}function $i(n){return Math.log(0>n?0:n)}function Ji(n){return Math.exp(n)}function Gi(n){return-Math.log(n>0?0:-n)}function Ki(n){return-Math.exp(-n)}function Wi(n,t,e){function r(t){return n(i(t))}var i=Qi(t),u=Qi(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(){return r.domain(Ri(e,Ii))},r.exponent=function(a){return arguments.length?(i=Qi(t=a),u=Qi(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return Wi(n.copy(),t,e)},Ui(r,n)}function Qi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function nu(n,t){function e(t){return a[((u.get(t)||u.set(t,n.push(t)))-1)%a.length]}
function r(t,e){return ua.range(n.length).map(function(n){return t+e*n})}var u,a,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new i;for(var a,o=-1,c=r.length;++o<c;)u.has(a=r[o])||u.set(a,n.push(a));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(a=n,o=0,t={t:"range",a:arguments},e):a},e.rangePoints=function(i,u){arguments.length<2&&(u=0);var c=i[0],l=i[1],f=(l-c)/(Math.max(1,n.length-1)+u);return a=r(n.length<2?(c+l)/2:c+f*u/2,f),o=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(i,u,c){arguments.length<2&&(u=0),arguments.length<3&&(c=u);var l=i[1]<i[0],f=i[l-0],s=i[1-l],h=(s-f)/(n.length-u+2*c);return a=r(f+h*c,h),l&&a.reverse(),o=h*(1-u),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(i,u,c){arguments.length<2&&(u=0),arguments.length<3&&(c=u);var l=i[1]<i[0],f=i[l-0],s=i[1-l],h=Math.floor((s-f)/(n.length-u+2*c)),g=s-f-(n.length-u)*h;return a=r(f+Math.round(g/2),h),l&&a.reverse(),o=Math.round(h*(1-u)),t=
{t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Fi(t.a[0])},e.copy=function(){return nu(n,t)},e.domain(n)}function tu(n,t){function e(){var e=0,u=t.length;for(i=[];++e<u;)i[e-1]=ua.quantile(n,e/u);return r}function r(n){return isNaN(n=+n)?0/0:t[ua.bisect(i,n)]}var i;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(ua.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return i},r.copy=function(){return tu(n,t)},e()}function eu(n,t,e){function r(t){return e[Math.max(0,Math.min(a,Math.floor(u*(t-n))))]}function i(){return u=e.length/(t-n),a=e.length-1,r}var u,a;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],i()):[n,t]},r.range=function(n){return arguments.length?(e=n,i()):e},r.copy=function(){return eu(n,t,e)},i()}function ru(n,t){function e(e){return t[ua.bisect(n,e)]}return e.domain=function(t){r
eturn arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.copy=function(){return ru(n,t)},e}function iu(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 Xi(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return iu(n)},t}function uu(n){return n.innerRadius}function au(n){return n.outerRadius}function ou(n){return n.startAngle}function cu(n){return n.endAngle}function lu(n){for(var t,e,r,i=-1,u=n.length;++i<u;)t=n[i],e=t[0],r=t[1]+nc,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function fu(n){function t(t){function c(){d.push("M",o(n(v),s),f,l(n(m.reverse()),s),"Z")}for(var h,g,p,d=[],m=[],v=[],y=-1,M=t.length,x=lt(e),b=lt(i),_=e===r?function(){return g}:lt(r),w=i===u?function(){return p}:lt(u);++y<M;)a.call(this,h=t[y],y)?(m.push([g=+x.call(this,h,y),p=+b.call(this,h,y)]),v.push([+_.call(this,h,y),+w.call(this,h,y)])):m.length&&(
c(),m=[],v=[]);return m.length&&c(),d.length?d.join(""):null}var e=je,r=je,i=0,u=Le,a=Ht,o=Fe,c=o.key,l=o,f="L",s=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(i=u=n,t):u},t.y0=function(n){return arguments.length?(i=n,t):i},t.y1=function(n){return arguments.length?(u=n,t):u},t.defined=function(n){return arguments.length?(a=n,t):a},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?o=n:(o=jo.get(n)||Fe).key,l=o.reverse||o,f=o.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(s=n,t):s},t}function su(n){return n.radius}function hu(n){return[n.x,n.y]}function gu(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+nc;return[e*Math.cos(r),e*Math.sin(r)]}}function pu(){return 64}function du(){return"circle"}function mu(n){var t=Math.sqrt(n/Da);return"M0,"+t+"A"+t+","+t+
" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function vu(n,t){return va(n,ac),n.id=t,n}function yu(n,t,e,r){var i=n.id;return D(n,"function"==typeof e?function(n,u,a){n.__transition__[i].tween.set(t,r(e.call(n,n.__data__,u,a)))}:(e=r(e),function(n){n.__transition__[i].tween.set(t,e)}))}function Mu(n){return null==n&&(n=""),function(){this.textContent=n}}function xu(n,t,e,r){var u=n.__transition__||(n.__transition__={active:0,count:0}),a=u[e];if(!a){var o=r.time;return a=u[e]={tween:new i,event:ua.dispatch("start","end"),time:o,ease:r.ease,delay:r.delay,duration:r.duration},++u.count,ua.timer(function(r){function i(r){return u.active>e?l():(u.active=e,h.start.call(n,f,t),a.tween.forEach(function(e,r){(r=r.call(n,f,t))&&d.push(r)}),c(r)||ua.timer(c,0,o),1)}function c(r){if(u.active!==e)return l();for(var i=(r-g)/p,a=s(i),o=d.length;o>0;)d[--o].call(n,a);return i>=1?(l(),h.end.call(n,f,t),1):void 0}function l(){return--u.count?delete u[e]:delete n.__transition__,1}var f=n.__dat
a__,s=a.ease,h=a.event,g=a.delay,p=a.duration,d=[];return r>=g?i(r):ua.timer(i,g,o),1},0,o),a}}function bu(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function _u(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function wu(n,t,e){if(r=[],e&&t.length>1){for(var r,i,u,a=Fi(n.domain()),o=-1,c=t.length,l=(t[1]-t[0])/++e;++o<c;)for(i=e;--i>0;)(u=+t[o]-i*l)>=a[0]&&r.push(u);for(--o,i=0;++i<e&&(u=+t[o]+i*l)<a[1];)r.push(u)}return r}function Su(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Eu(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new gc(e-1)),1),e}function u(n,e){return t(n=new gc(+n),e),n}function a(n,r,u){var a=i(n),o=[];if(u>1)for(;r>a;)e(a)%u||o.push(new Date(+a)),t(a,1);else for(;r>a;)o.push(new Date(+a)),t(a,1);return o}function o(n,t,e){try{gc=Su;var r=new Su;return r._=n,a(r,t,e)}finally{gc=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.r
ange=a;var c=n.utc=ku(n);return c.floor=c,c.round=ku(r),c.ceil=ku(i),c.offset=ku(u),c.range=o,n}function ku(n){return function(t,e){try{gc=Su;var r=new Su;return r._=t,n(r,e)._}finally{gc=Date}}}function Au(n,t,e,r){for(var i,u,a=0,o=t.length,c=e.length;o>a;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(u=Cc[t.charAt(a++)],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function Nu(n){return RegExp("^(?:"+n.map(ua.requote).join("|")+")","i")}function qu(n){for(var t=new i,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Tu(n,t,e){n+="";var r=n.length;return e>r?Array(e-r+1).join(t)+n:n}function Cu(n,t,e){Sc.lastIndex=0;var r=Sc.exec(t.substring(e));return r?e+=r[0].length:-1}function zu(n,t,e){wc.lastIndex=0;var r=wc.exec(t.substring(e));return r?e+=r[0].length:-1}function Du(n,t,e){Ac.lastIndex=0;var r=Ac.exec(t.substring(e));return r?(n.m=Nc.get(r[0].toLowerCase()),e+=r[0].length):-1}function ju(n,t,e){Ec.lastIndex=0;var
r=Ec.exec(t.substring(e));return r?(n.m=kc.get(r[0].toLowerCase()),e+=r[0].length):-1}function Lu(n,t,e){return Au(n,""+Tc.c,t,e)}function Fu(n,t,e){return Au(n,""+Tc.x,t,e)}function Hu(n,t,e){return Au(n,""+Tc.X,t,e)}function Pu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+=r[0].length):-1}function Ru(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.y=Ou(+r[0]),e+=r[0].length):-1}function Ou(n){return n+(n>68?1900:2e3)}function Yu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+=r[0].length):-1}function Uu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+=r[0].length):-1}function Iu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+=r[0].length):-1}function Vu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+=r[0].length):-1}function Xu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.S=+
r[0],e+=r[0].length):-1}function Zu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+=r[0].length):-1}function Bu(n,t,e){var r=Dc.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}function $u(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(Math.abs(t)/60),i=Math.abs(t)%60;return e+Tu(r,"0",2)+Tu(i,"0",2)}function Ju(n){return n.toISOString()}function Gu(n,t,e){function r(t){return n(t)}return r.invert=function(t){return Ku(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Ku)},r.nice=function(n){return r.domain(Ri(r.domain(),function(){return n}))},r.ticks=function(e,i){var u=Fi(r.domain());if("function"!=typeof e){var a=u[1]-u[0],o=a/e,c=ua.bisect(Lc,o);if(c==Lc.length)return t.year(u,e);if(!c)return n.ticks(e).map(Ku);Math.log(o/Lc[c-1])<Math.log(Lc[c]/o)&&--c,e=t[c],i=e[1],e=e[0].range}return e(u[0],new Date(+u[1]+1),i)},r.tickFormat=function(){return e},r.copy=function(){return Gu(n.c
opy(),t,e)},Ui(r,n)}function Ku(n){return new Date(n)}function Wu(n){return function(t){for(var e=n.length-1,r=n[e];!r[1](t);)r=n[--e];return r[0](t)}}function Qu(n){var t=new Date(n,0,1);return t.setFullYear(n),t}function na(n){var t=n.getFullYear(),e=Qu(t),r=Qu(t+1);return t+(n-e)/(r-e)}function ta(n){var t=new Date(Date.UTC(n,0,1));return t.setUTCFullYear(n),t}function ea(n){var t=n.getUTCFullYear(),e=ta(t),r=ta(t+1);return t+(n-e)/(r-e)}function ra(n){return JSON.parse(n.responseText)}function ia(n){var t=aa.createRange();return t.selectNode(aa.body),t.createContextualFragment(n.responseText)}var ua={version:"3.1.10"};Date.now||(Date.now=function(){return+new Date});var aa=document,oa=window;try{aa.createElement("div").style.setProperty("opacity",0,"")}catch(ca){var la=oa.CSSStyleDeclaration.prototype,fa=la.setProperty;la.setProperty=function(n,t,e){fa.call(this,n,t+"",e)}}ua.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},ua.descending=function(n,t){return n>t?-
1:t>n?1:t>=n?0:0/0},ua.min=function(n,t){var e,r,i=-1,u=n.length;if(arguments.length===1){for(;++i<u&&((e=n[i])==null||e!=e);)e=void 0;for(;++i<u;)(r=n[i])!=null&&e>r&&(e=r)}else{for(;++i<u&&((e=t.call(n,n[i],i))==null||e!=e);)e=void 0;for(;++i<u;)(r=t.call(n,n[i],i))!=null&&e>r&&(e=r)}return e},ua.max=function(n,t){var e,r,i=-1,u=n.length;if(arguments.length===1){for(;++i<u&&((e=n[i])==null||e!=e);)e=void 0;for(;++i<u;)(r=n[i])!=null&&r>e&&(e=r)}else{for(;++i<u&&((e=t.call(n,n[i],i))==null||e!=e);)e=void 0;for(;++i<u;)(r=t.call(n,n[i],i))!=null&&r>e&&(e=r)}return e},ua.extent=function(n,t){var e,r,i,u=-1,a=n.length;if(arguments.length===1){for(;++u<a&&((e=i=n[u])==null||e!=e);)e=i=void 0;for(;++u<a;)(r=n[u])!=null&&(e>r&&(e=r),r>i&&(i=r))}else{for(;++u<a&&((e=i=t.call(n,n[u],u))==null||e!=e);)e=void 0;for(;++u<a;)(r=t.call(n,n[u],u))!=null&&(e>r&&(e=r),r>i&&(i=r))}return[e,i]},ua.sum=function(n,t){var e,r=0,i=n.length,u=-1;if(arguments.length===1)for(;++u<i;)isNaN(e=+n[u])|
|(r+=e);else for(;++u<i;)isNaN(e=+t.call(n,n[u],u))||(r+=e);return r},ua.mean=function(t,e){var r,i=t.length,u=0,a=-1,o=0;if(arguments.length===1)for(;++a<i;)n(r=t[a])&&(u+=(r-u)/++o);else for(;++a<i;)n(r=e.call(t,t[a],a))&&(u+=(r-u)/++o);return o?u:void 0},ua.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),i=+n[r-1],u=e-r;return u?i+u*(n[r]-i):i},ua.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?ua.quantile(t.sort(ua.ascending),.5):void 0},ua.bisector=function(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n.call(t,t[u],u)<e?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;e<n.call(t,t[u],u)?i=u:r=u+1}return r}}};var sa=ua.bisector(function(n){return n});ua.bisectLeft=sa.left,ua.bisect=ua.bisectRight=sa.right,ua.shuffle=function(n){for(var t,e,r=n.length;r;)e=Math.random()*r--|0,
t=n[r],n[r]=n[e],n[e]=t;return n},ua.permute=function(n,t){for(var e=[],r=-1,i=t.length;++r<i;)e[r]=n[t[r]];return e},ua.zip=function(){if(!(i=arguments.length))return[];for(var n=-1,e=ua.min(arguments,t),r=Array(e);++n<e;)for(var i,u=-1,a=r[n]=Array(i);++u<i;)a[u]=arguments[u][n];return r},ua.transpose=function(n){return ua.zip.apply(ua,n)},ua.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ua.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ua.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ua.merge=function(n){return Array.prototype.concat.apply([],n)},ua.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw Error("infinite range");var i,u=[],a=e(Math.abs(r)),o=-1;if(n*=a,t*=a,r*=a,0>r)for(;(i=n+r*++o)>t;)u.push(i/a);else for(;(i=n+r*++o)<t;)u.push(i/a);return u},ua.map=function(n){var t=new i;for(var e in n)t.set(e,n[e]);return t},r(i,{has:function(n){return ha+n
in this},get:function(n){return this[ha+n]},set:function(n,t){return this[ha+n]=t},remove:function(n){return n=ha+n,n in this&&delete this[n]},keys:function(){var n=[];return this.forEach(function(t){n.push(t)}),n},values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},forEach:function(n){for(var t in this)t.charCodeAt(0)===ga&&n.call(this,t.substring(1),this[t])}});var ha="\0",ga=ha.charCodeAt(0);ua.nest=function(){function n(t,o,c){if(c>=a.length)return r?r.call(u,o):e?o.sort(e):o;for(var l,f,s,h,g=-1,p=o.length,d=a[c++],m=new i;++g<p;)(h=m.get(l=d(f=o[g])))?h.push(f):m.set(l,[f]);return t?(f=t(),s=function(e,r){f.set(e,n(t,r,c))}):(f={},s=function(e,r){f[e]=n(t,r,c)}),m.forEach(s),f}function t(n,e){if(e>=a.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,u={
},a=[],o=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(ua.map,e,0),0)},u.key=function(n){return a.push(n),u},u.sortKeys=function(n){return o[a.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},ua.set=function(n){var t=new u;if(n)for(var e=0;e<n.length;e++)t.add(n[e]);return t},r(u,{has:function(n){return ha+n in this
+},add:function(n){return this[ha+n]=!0,n},remove:function(n){return n=ha+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)===ga&&n.call(this,t.substring(1))}}),ua.behavior={},ua.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r<i;)n[e=arguments[r]]=a(n,t,t[e]);return n},ua.dispatch=function(){for(var n=new o,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=c(n);return n},o.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=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(arguments.length===2){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ua.event=null,ua.mouse=function(n){return g(n,f())};var pa=/WebKit/.test(oa.navigator.userAgent)?-1:0,da=d;try{da(aa.documentElement.childNodes)[0].nodeType}catch(ma){da=p}var va=[].__proto__?function(n,t){n.__proto__=t}:function(n,t
){for(var e in t)n[e]=t[e]};ua.touches=function(n,t){return arguments.length<2&&(t=f().touches),t?da(t).map(function(t){var e=g(n,t);return e.identifier=t.identifier,e}):[]},ua.behavior.drag=function(){function n(){this.on("mousedown.drag",t).on("touchstart.drag",t)}function t(){function n(){var n=a.parentNode;return null!=f?ua.touches(n).filter(function(n){return n.identifier===f})[0]:ua.mouse(n)}function t(){if(!a.parentNode)return i();var t=n(),e=t[0]-h[0],r=t[1]-h[1];g|=e|r,h=t,l(),o({type:"drag",x:t[0]+u[0],y:t[1]+u[1],dx:e,dy:r})}function i(){o({type:"dragend"}),g&&(l(),ua.event.target===c&&s(p,"click")),p.on(null!=f?"touchmove.drag-"+f:"mousemove.drag",null).on(null!=f?"touchend.drag-"+f:"mouseup.drag",null)}var u,a=this,o=e.of(a,arguments),c=ua.event.target,f=ua.event.touches?ua.event.changedTouches[0].identifier:null,h=n(),g=0,p=ua.select(oa).on(null!=f?"touchmove.drag-"+f:"mousemove.drag",t).on(null!=f?"touchend.drag-"+f:"mouseup.drag",i,!0);r?(u=r.apply(a,argument
s),u=[u.x-h[0],u.y-h[1]]):u=[0,0],null==f&&l(),o({type:"dragstart"})}var e=h(n,"drag","dragstart","dragend"),r=null;return n.origin=function(t){return arguments.length?(r=t,n):r},ua.rebind(n,e,"on")};var ya=function(n,t){return t.querySelector(n)},Ma=function(n,t){return t.querySelectorAll(n)},xa=aa.documentElement,ba=xa.matchesSelector||xa.webkitMatchesSelector||xa.mozMatchesSelector||xa.msMatchesSelector||xa.oMatchesSelector,_a=function(n,t){return ba.call(n,t)};"function"==typeof Sizzle&&(ya=function(n,t){return Sizzle(n,t)[0]||null},Ma=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},_a=Sizzle.matchesSelector),ua.selection=function(){return Na};var wa=ua.selection.prototype=[];wa.select=function(n){var t,e,r,i,u=[];"function"!=typeof n&&(n=v(n));for(var a=-1,o=this.length;++a<o;){u.push(t=[]),t.parentNode=(r=this[a]).parentNode;for(var c=-1,l=r.length;++c<l;)(i=r[c])?(t.push(e=n.call(i,i.__data__,c)),e&&"__data__"in i&&(e.__data__=i.__data__)):t.push(null)}return m(u
)},wa.selectAll=function(n){var t,e,r=[];"function"!=typeof n&&(n=y(n));for(var i=-1,u=this.length;++i<u;)for(var a=this[i],o=-1,c=a.length;++o<c;)(e=a[o])&&(r.push(t=da(n.call(e,e.__data__,o))),t.parentNode=e);return m(r)};var Sa={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/"};ua.ns={prefix:Sa,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),Sa.hasOwnProperty(e)?{space:Sa[e],local:n}:n}},wa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ua.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))},ua.requote=function(n){return n.replace(Ea,"\\$&")};var Ea=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;wa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){
var e=this.node(),r=(n=n.trim().split(/^|\s+/g)).length,i=-1;if(t=e.classList){for(;++i<r;)if(!t.contains(n[i]))return!1}else for(t=e.getAttribute("class");++i<r;)if(!b(n[i]).test(t))return!1;return!0}for(t in n)this.each(_(t,n[t]));return this}return this.each(_(n,t))},wa.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(S(e,n[e],t));return this}if(2>r)return oa.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(S(n,t,e))},wa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},wa.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},wa.html=function(n){return arguments.length?this.each("function"==typ
eof 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},wa.append=function(n){function t(){return this.appendChild(aa.createElementNS(this.namespaceURI,n))}function e(){return this.appendChild(aa.createElementNS(n.space,n.local))}return n=ua.ns.qualify(n),this.select(n.local?e:t)},wa.insert=function(n,t){function e(e,r){return this.insertBefore(aa.createElementNS(this.namespaceURI,n),t.call(this,e,r))}function r(e,r){return this.insertBefore(aa.createElementNS(n.space,n.local),t.call(this,e,r))}return n=ua.ns.qualify(n),"function"!=typeof t&&(t=v(t)),this.select(n.local?r:e)},wa.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},wa.data=function(n,t){function e(n,e){var r,u,a,o=n.length,s=e.length,h=Math.min(o,s),g=Array(s),p=Array(s),d=Array(o);if(t){var m,v=new i,y=new i,M=[];for(r=-1;++r<o;)m=t.call(u=n[r],u.__data__,r),
v.has(m)?d[r]=u:v.set(m,u),M.push(m);for(r=-1;++r<s;)m=t.call(e,a=e[r],r),(u=v.get(m))?(g[r]=u,u.__data__=a):y.has(m)||(p[r]=k(a)),y.set(m,a),v.remove(m);for(r=-1;++r<o;)v.has(M[r])&&(d[r]=n[r])}else{for(r=-1;++r<h;)u=n[r],a=e[r],u?(u.__data__=a,g[r]=u):p[r]=k(a);for(;s>r;++r)p[r]=k(e[r]);for(;o>r;++r)d[r]=n[r]}p.update=g,p.parentNode=g.parentNode=d.parentNode=n.parentNode,c.push(p),l.push(g),f.push(d)}var r,u,a=-1,o=this.length;if(!arguments.length){for(n=Array(o=(r=this[0]).length);++a<o;)(u=r[a])&&(n[a]=u.__data__);return n}var c=j([]),l=m([]),f=m([]);if("function"==typeof n)for(;++a<o;)e(r=this[a],n.call(r,r.parentNode.__data__,a));else for(;++a<o;)e(r=this[a],n);return l.enter=function(){return c},l.exit=function(){return f},l},wa.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},wa.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=A(n));for(var u=0,a=this.length;a>u;u++){i.push(t=[]),t.parentNode=(e=this[u]).paren
tNode;for(var o=0,c=e.length;c>o;o++)(r=e[o])&&n.call(r,r.__data__,o)&&t.push(r)}return m(i)},wa.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},wa.sort=function(n){n=N.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},wa.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(T(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(T(n,t,e))};var ka=ua.map({mouseenter:"mouseover",mouseleave:"mouseout"});ka.forEach(function(n){"on"+n in aa&&ka.remove(n)}),wa.each=function(n){return D(this,function(t,e,r){n.call(t,t.__data__,e,r)})},wa.call=function(n){var t=da(arguments);return n.apply(t[0]=this,t),this},wa.empty=function(){return!this.node()},wa.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,i=
e.length;i>r;r++){var u=e[r];if(u)return u}return null};var Aa=[];ua.selection.enter=j,ua.selection.enter.prototype=Aa,Aa.append=wa.append,Aa.insert=wa.insert,Aa.empty=wa.empty,Aa.node=wa.node,Aa.select=function(n){for(var t,e,r,i,u,a=[],o=-1,c=this.length;++o<c;){r=(i=this[o]).update,a.push(t=[]),t.parentNode=i.parentNode;for(var l=-1,f=i.length;++l<f;)(u=i[l])?(t.push(r[l]=e=n.call(i.parentNode,u.__data__,l)),e.__data__=u.__data__):t.push(null)}return m(a)},wa.transition=function(){var n,t,e=rc||++oc,r=[],i=Object.create(cc);i.time=Date.now();for(var u=-1,a=this.length;++u<a;){r.push(n=[]);for(var o=this[u],c=-1,l=o.length;++c<l;)(t=o[c])&&xu(t,c,e,i),n.push(t)}return vu(r,e)},ua.select=function(n){var t=["string"==typeof n?ya(n,aa):n];return t.parentNode=xa,m([t])},ua.selectAll=function(n){var t=da("string"==typeof n?Ma(n,aa):n);return t.parentNode=xa,m([t])};var Na=ua.select(xa);ua.behavior.zoom=function(){function n(){this.on("mousedown.zoom",o).on("mousemove.zoom",f).o
n(Ca+".zoom",c).on("dblclick.zoom",g).on("touchstart.zoom",p).on("touchmove.zoom",d).on("touchend.zoom",p)}function t(n){return[(n[0]-w[0])/S,(n[1]-w[1])/S]}function e(n){return[n[0]*S+w[0],n[1]*S+w[1]]}function r(n){S=Math.max(E[0],Math.min(E[1],n))}function i(n,t){t=e(t),w[0]+=n[0]-t[0],w[1]+=n[1]-t[1]}function u(){M&&M.domain(y.range().map(function(n){return(n-w[0])/S}).map(y.invert)),b&&b.domain(x.range().map(function(n){return(n-w[1])/S}).map(x.invert))}function a(n){u(),ua.event.preventDefault(),n({type:"zoom",scale:S,translate:w})}function o(){function n(){c=1,i(ua.mouse(r),h),a(u)}function e(){c&&l(),f.on("mousemove.zoom",null).on("mouseup.zoom",null),c&&ua.event.target===o&&s(f,"click.zoom")}var r=this,u=k.of(r,arguments),o=ua.event.target,c=0,f=ua.select(oa).on("mousemove.zoom",n).on("mouseup.zoom",e),h=t(ua.mouse(r));oa.focus(),l()}function c(){m||(m=t(ua.mouse(this))),r(Math.pow(2,qa()*.002)*S),i(ua.mouse(this),m),a(k.of(this,arguments))}function f(){m=null}funct
ion g(){var n=ua.mouse(this),e=t(n),u=Math.log(S)/Math.LN2;r(Math.pow(2,ua.event.shiftKey?Math.ceil(u)-1:Math.floor(u)+1)),i(n,e),a(k.of(this,arguments))}function p(){var n=ua.touches(this),e=Date.now();if(v=S,m={},n.forEach(function(n){m[n.identifier]=t(n)}),l(),n.length===1){if(500>e-_){var u=n[0],o=t(n[0]);r(2*S),i(u,o),a(k.of(this,arguments))}_=e}}function d(){var n=ua.touches(this),t=n[0],e=m[t.identifier];if(u=n[1]){var u,o=m[u.identifier];t=[(t[0]+u[0])/2,(t[1]+u[1])/2],e=[(e[0]+o[0])/2,(e[1]+o[1])/2],r(ua.event.scale*v)}i(t,e),_=null,a(k.of(this,arguments))}var m,v,y,M,x,b,_,w=[0,0],S=1,E=Ta,k=h(n,"zoom");return n.translate=function(t){return arguments.length?(w=t.map(Number),u(),n):w},n.scale=function(t){return arguments.length?(S=+t,u(),n):S},n.scaleExtent=function(t){return arguments.length?(E=null==t?Ta:t.map(Number),n):E},n.x=function(t){return arguments.length?(M=t,y=t.copy(),w=[0,0],S=1,n):M},n.y=function(t){return arguments.length?(b=t,x=t.copy(),w=[0,0],S=1,
n):b},ua.rebind(n,k,"on")};var qa,Ta=[0,1/0],Ca="onwheel"in aa?(qa=function(){return-ua.event.deltaY*(ua.event.deltaMode?120:1)},"wheel"):"onmousewheel"in aa?(qa=function(){return ua.event.wheelDelta},"mousewheel"):(qa=function(){return-ua.event.detail},"MozMousePixelScroll");L.prototype.toString=function(){return this.rgb()+""},ua.hsl=function(n,t,e){return arguments.length===1?n instanceof H?F(n.h,n.s,n.l):it(""+n,ut,F):F(+n,+t,+e)};var za=H.prototype=new L;za.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),F(this.h,this.s,this.l/n)},za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),F(this.h,this.s,n*this.l)},za.rgb=function(){return P(this.h,this.s,this.l)};var Da=Math.PI,ja=1e-6,La=Da/180,Fa=180/Da;ua.hcl=function(n,t,e){return arguments.length===1?n instanceof Z?X(n.h,n.c,n.l):n instanceof J?K(n.l,n.a,n.b):K((n=at((n=ua.rgb(n)).r,n.g,n.b)).l,n.a,n.b):X(+n,+t,+e)};var Ha=Z.prototype=new L;Ha.brighter=function(n){return X(this.h,this.c,Math.
min(100,this.l+Pa*(arguments.length?n:1)))},Ha.darker=function(n){return X(this.h,this.c,Math.max(0,this.l-Pa*(arguments.length?n:1)))},Ha.rgb=function(){return B(this.h,this.c,this.l).rgb()},ua.lab=function(n,t,e){return arguments.length===1?n instanceof J?$(n.l,n.a,n.b):n instanceof Z?B(n.l,n.c,n.h):at((n=ua.rgb(n)).r,n.g,n.b):$(+n,+t,+e)};var Pa=18,Ra=.95047,Oa=1,Ya=1.08883,Ua=J.prototype=new L;Ua.brighter=function(n){return $(Math.min(100,this.l+Pa*(arguments.length?n:1)),this.a,this.b)},Ua.darker=function(n){return $(Math.max(0,this.l-Pa*(arguments.length?n:1)),this.a,this.b)},Ua.rgb=function(){return G(this.l,this.a,this.b)},ua.rgb=function(n,t,e){return arguments.length===1?n instanceof et?tt(n.r,n.g,n.b):it(""+n,tt,P):tt(~~n,~~t,~~e)};var Ia=et.prototype=new L;Ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),tt(Math.min(255,Math.floor(t/n)),Math.min(255,Math.floor
(e/n)),Math.min(255,Math.floor(r/n)))):tt(i,i,i)},Ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),tt(Math.floor(n*this.r),Math.floor(n*this.g),Math.floor(n*this.b))},Ia.hsl=function(){return ut(this.r,this.g,this.b)},Ia.toString=function(){return"#"+rt(this.r)+rt(this.g)+rt(this.b)};var Va=ua.map({aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagre
en:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime
:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708
090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"});Va.forEach(function(n,t){Va.set(n,it(t,tt,P))}),ua.functor=lt,ua.xhr=st(ft),ua.csv=pt(",","text/csv"),ua.tsv=pt(" ","text/tab-separated-values");var Xa,Za,Ba,$a;ua.timer=function(n,t,e){if(arguments.length<3){if(arguments.length<2)t=0;else if(!isFinite(t))return;e=Date.now()}var r=e+t,i={callback:n,time:r,next:null};Za?Za.next=i:Xa=i,Za=i,Ba||($a=clearTimeout($a),Ba=1,Ja(dt))},ua.timer.flush=function(){mt(),vt()};var Ja=oa.requestAnimationFrame||oa.webkitRequestAnimationFrame||oa.mozRequestAnimationFrame||oa.oRequestAnimationFrame||oa.msRequestAnimationFrame||function(n){setTimeout(n,17)},Ga=".",Ka=",",Wa=[3,3],Qa=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"].map(yt);ua.formatPre
fix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=ua.round(n,Mt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,Math.floor((0>=e?e+1:e-1)/3)*3))),Qa[8+e/3]},ua.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)},ua.format=function(n){var t=no.exec(n),e=t[1]||" ",r=t[2]||">",i=t[3]||"",u=t[4]||"",a=t[5],o=+t[6],c=t[7],l=t[8],f=t[9],s=1,h="",g=!1;switch(l&&(l=+l.substring(1)),(a||"0"===e&&"="===r)&&(a=e="0",r="=",c&&(o-=Math.floor((o-1)/4))),f){case"n":c=!0,f="g";break;case"%":s=100,h="%",f="f";break;case"p":s=100,h="%",f="r";break;case"b":case"o":case"x":case"X":u&&(u="0"+f.toLowerCase());case"c":case"d":g=!0,l=0;break;case"s":s=-1,f="r"}"#"===u&&(u=""),"r"!=f||l||(f="g"),null!=l&&("g"==f?l=Math.max(1,Math.min(21,l)):("e"==f||"f"==f)&&(l=Math.max(0,Math.min(20,l)))),f=to.get(f)||xt;var p=a&&c;return function(n){if(g&&n%1)return"";var t=0>n||0===n&&0>1/n?(n=-n,"-"):i;if(0>s){var d=ua.formatPrefix(n,l);n=d.scale(n),
h=d.symbol}else n*=s;n=f(n,l),!a&&c&&(n=eo(n));var m=u.length+n.length+(p?0:t.length),v=o>m?Array(m=o-m+1).join(e):"";return p&&(n=eo(v+n)),Ga&&n.replace(".",Ga),t+=u,("<"===r?t+n+v:">"===r?v+t+n:"^"===r?v.substring(0,m>>=1)+t+n+v.substring(m):t+(p?n:v+n))+h}};var no=/(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,to=ua.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=ua.round(n,Mt(n,t))).toFixed(Math.max(0,Math.min(20,Mt(n*(1+1e-15),t))))}}),eo=ft;if(Wa){var ro=Wa.length;eo=function(n){for(var t=n.lastIndexOf("."),e=t>=0?"."+n.substring(t+1):(t=n.length,""),r=[],i=0,u=Wa[0];t>0&&u>0;)r.push(n.substring(t-=u,t+u)),u=Wa[i=(i+1)%ro];return r.reverse().jo
in(Ka||"")+e}}ua.geo={},ua.geo.stream=function(n,t){n&&io.hasOwnProperty(n.type)?io[n.type](n,t):bt(n,t)};var io={Feature:function(n,t){bt(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++r<i;)bt(e[r].geometry,t)}},uo={Sphere:function(n,t){t.sphere()},Point:function(n,t){var e=n.coordinates;t.point(e[0],e[1])},MultiPoint:function(n,t){for(var e,r=n.coordinates,i=-1,u=r.length;++i<u;)e=r[i],t.point(e[0],e[1])},LineString:function(n,t){_t(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)_t(e[r],t,0)},Polygon:function(n,t){wt(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)wt(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,i=e.length;++r<i;)bt(e[r],t)}};ua.geo.area=function(n){return ao=0,ua.geo.stream(n,co),ao};var ao,oo,co={sphere:function(){ao+=4*Da},point:q,lineStart:q,lineEnd:q,polygonStart:function(){oo=0,co.lineStart=St},p
olygonEnd:function(){var n=2*oo;ao+=0>n?4*Da+n:n,co.lineStart=co.lineEnd=co.point=q}};ua.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>g&&(g=t)}function t(t,e){var r=Et([t*La,e*La]);if(v){var i=At(v,r),u=[i[1],-i[0],0],a=At(u,i);Tt(a),a=Ct(a);var c=t-p,l=c>0?1:-1,d=a[0]*Fa*l,m=Math.abs(c)>180;if(m^(d>l*p&&l*t>d)){var y=a[1]*Fa;y>g&&(g=y)}else if(d=(d+360)%360-180,m^(d>l*p&&l*t>d)){var y=-a[1]*Fa;s>y&&(s=y)}else s>e&&(s=e),e>g&&(g=e);m?p>t?o(f,t)>o(f,h)&&(h=t):o(t,h)>o(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>p?o(f,t)>o(f,h)&&(h=t):o(t,h)>o(f,h)&&(f=t)}else n(t,e);v=r,p=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,v=null}function i(n,e){if(v){var r=n-p;y+=Math.abs(r)>180?r+(r>0?360:-360):r}else d=n,m=e;co.point(n,e),t(n,e)}function u(){co.lineStart()}function a(){i(d,m),co.lineEnd(),Math.abs(y)>ja&&(f=-(h=180)),x[0]=f,x[1]=h,v=null}function o(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]:n<t[0]||t[1]<n}var f,s,h,g,p,d,m,v,y,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=i,b.lineStart=u,b.lineEnd=a,y=0,co.polygonStart()},polygonEnd:function(){co.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>oo?(f=-(h=180),s=-(g=90)):y>ja?g=90:-ja>y&&(s=-90),x[0]=f,x[1]=h}};return function(n){g=h=-(f=s=1/0),M=[],ua.geo.stream(n,b),M.sort(c);for(var t,e=1,r=M.length,i=M[0],u=[i];r>e;++e)t=M[e],l(t[0],i)||l(t[1],i)?(o(i[0],t[1])>o(i[0],i[1])&&(i[1]=t[1]),o(t[0],i[1])>o(i[0],i[1])&&(i[0]=t[0])):u.push(i=t);for(var a,t,p=-1/0,r=u.length-1,e=0,i=u[r];r>=e;i=t,++e)t=u[e],(a=o(i[1],t[0]))>p&&(p=a,f=t[0],h=i[1]);return M=x=null,[[f,s],[h,g]]}}(),ua.geo.centroid=function(n){lo=fo=so=ho=go=0,ua.geo.stream(n,po);var t;return fo&&Math.abs(t=Math.sqrt(so*so+ho*ho+go*go))>ja?[Math.atan2(ho,so)*Fa,Math.asin(Math.max(-1,Math.min(1,go/t)))*Fa]:void 0};var lo,fo,so,ho,go,po={sphere:function(){2>lo&&(lo=2,fo=so=ho=go=0)},point:Dt,lineStart:Lt,lineE
nd:Ft,polygonStart:function(){2>lo&&(lo=2,fo=so=ho=go=0),po.lineStart=jt},polygonEnd:function(){po.lineStart=Lt}},mo=Ot(Ht,Xt,Bt),vo=1e9;ua.geo.projection=Qt,ua.geo.projectionMutator=ne,(ua.geo.equirectangular=function(){return Qt(ee)}).raw=ee.invert=ee,ua.geo.rotation=function(n){function t(t){return t=n(t[0]*La,t[1]*La),t[0]*=Fa,t[1]*=Fa,t}return n=re(n[0]%360*La,n[1]*La,n.length>2?n[2]*La:0),t.invert=function(t){return t=n.invert(t[0]*La,t[1]*La),t[0]*=Fa,t[1]*=Fa,t},t},ua.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=re(-n[0]*La,-n[1]*La,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Fa,n[1]*=Fa}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=oe((t=+r)*La,i*La),n):t},n.precision=function(r){return arguments.length?(e=oe(t*La,(i=+r)*La),n):i},n.angle(90)},ua.geo.distance=function(
n,t){var e,r=(t[0]-n[0])*La,i=n[1]*La,u=t[1]*La,a=Math.sin(r),o=Math.cos(r),c=Math.sin(i),l=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*a)*e+(e=l*f-c*s*o)*e),c*f+l*s*o)},ua.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ua.range(Math.ceil(u/m)*m,i,m).map(h).concat(ua.range(Math.ceil(l/v)*v,c,v).map(g)).concat(ua.range(Math.ceil(r/p)*p,e,p).filter(function(n){return Math.abs(n%m)>ja}).map(f)).concat(ua.range(Math.ceil(o/d)*d,a,d).filter(function(n){return Math.abs(n%v)>ja}).map(s))}var e,r,i,u,a,o,c,l,f,s,h,g,p=10,d=p,m=90,v=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(u).concat(g(c).slice(1),h(i).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 argum
ents.length?(u=+t[0][0],i=+t[1][0],l=+t[0][1],c=+t[1][1],u>i&&(t=u,u=i,i=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[u,l],[i,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],o=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),o>a&&(t=o,o=a,a=t),n.precision(y)):[[r,o],[e,a]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(m=+t[0],v=+t[1],n):[m,v]},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,f=le(o,a,90),s=fe(r,e,y),h=le(l,c,90),g=fe(u,i,y),n):y},n.majorExtent([[-180,-90+ja],[180,90-ja]]).minorExtent([[-180,-80-ja],[180,80+ja]])},ua.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=se,i=he;return n.distance=function(){return ua.geo.distance(t||r.apply(this,arguments),e||i.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?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ua.geo.interpolate=function(n,t){return ge(n[0]*La,n[1]*La,t[0]*La,t[1]*La)},ua.geo.length=function(n){return yo=0,ua.geo.stream(n,Mo),yo};var yo,Mo={sphere:q,point:q,lineStart:pe,lineEnd:q,polygonStart:q,polygonEnd:q};(ua.geo.conicEqualArea=function(){return de(me)}).raw=me,ua.geo.albers=function(){return ua.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ua.geo.albersUsa=function(){function n(n){var u=n[0],a=n[1];return t=null,e(u,a),t||(r(u,a),t)||i(u,a),t}var t,e,r,i,u=ua.geo.albers(),a=ua.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),o=ua.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=u.scale()
,e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?a:i>=.166&&.234>i&&r>=-.214&&-.115>r?o:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=a.stream(n),r=o.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},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?(u.precision(t),a.precision(t),o.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),a.scale(.35*t),o.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var l=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*l,s-.238*l],[f+.455
*l,s+.238*l]]).stream(c).point,r=a.translate([f-.307*l,s+.201*l]).clipExtent([[f-.425*l+ja,s+.12*l+ja],[f-.214*l-ja,s+.234*l-ja]]).stream(c).point,i=o.translate([f-.205*l,s+.212*l]).clipExtent([[f-.214*l+ja,s+.166*l+ja],[f-.115*l-ja,s+.234*l-ja]]).stream(c).point,n},n.scale(1070)};var xo,bo,_o,wo,So,Eo,ko={point:q,lineStart:q,lineEnd:q,polygonStart:function(){bo=0,ko.lineStart=ve},polygonEnd:function(){ko.lineStart=ko.lineEnd=ko.point=q,xo+=Math.abs(bo/2)}},Ao={point:ye,lineStart:q,lineEnd:q,polygonStart:q,polygonEnd:q},No={point:be,lineStart:_e,lineEnd:we,polygonStart:function(){No.lineStart=Se},polygonEnd:function(){No.point=be,No.lineStart=_e,No.lineEnd=we}};ua.geo.path=function(){function n(n){return n&&ua.geo.stream(n,r(i.pointRadius("function"==typeof u?+u.apply(this,arguments):u))),i.result()}var t,e,r,i,u=4.5;return n.area=function(n){return xo=0,ua.geo.stream(n,r(ko)),xo},n.centroid=function(n){return lo=so=ho=go=0,ua.geo.stream(n,r(No)),go?[so/go,ho/go]:void 0},n.b
ounds=function(n){return So=Eo=-(_o=wo=1/0),ua.geo.stream(n,r(Ao)),[[_o,wo],[So,Eo]]},n.projection=function(e){return arguments.length?(r=(t=e)?e.stream||ke(e):ft,n):t},n.context=function(t){return arguments.length?(i=(e=t)==null?new Me:new Ee(t),n):e},n.pointRadius=function(t){return arguments.length?(u="function"==typeof t?t:+t,n):u},n.projection(ua.geo.albersUsa()).context(null)};var qo=Ae(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ua.geo.azimuthalEqualArea=function(){return Qt(qo)}).raw=qo;var To=Ae(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},ft);(ua.geo.azimuthalEquidistant=function(){return Qt(To)}).raw=To,(ua.geo.conicConformal=function(){return de(Ne)}).raw=Ne,(ua.geo.conicEquidistant=function(){return de(qe)}).raw=qe;var Co=Ae(function(n){return 1/n},Math.atan);(ua.geo.gnomonic=function(){return Qt(Co)}).raw=Co,Te.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Da/2]},(ua.geo.mercator=function(){return Ce(Te)}).r
aw=Te;var zo=Ae(function(){return 1},Math.asin);(ua.geo.orthographic=function(){return Qt(zo)}).raw=zo;var Do=Ae(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ua.geo.stereographic=function(){return Qt(Do)}).raw=Do,ze.invert=function(n,t){return[Math.atan2(U(n),Math.cos(t)),Y(Math.sin(t)/I(n))]},(ua.geo.transverseMercator=function(){return Ce(ze)}).raw=ze,ua.geom={},ua.svg={},ua.svg.line=function(){return De(ft)};var jo=ua.map({linear:Fe,"linear-closed":He,"step-before":Pe,"step-after":Re,basis:Xe,"basis-open":Ze,"basis-closed":Be,bundle:$e,cardinal:Ue,"cardinal-open":Oe,"cardinal-closed":Ye,monotone:nr});jo.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Lo=[0,2/3,1/3,0],Fo=[0,1/3,2/3,0],Ho=[0,1/6,2/3,1/6];ua.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i,u,a,o,c,l,f,s,h,g,p,d=lt(e),m=lt(r),v=n.length,y=v-1,M=[],x=[],b=0;if(d===je&&r===Le)t=n;else for(u=0,t=[];v>u;++u)t.push([+d.call(this,i=n[u],u),+m.call(this,i,u)]);fo
r(u=1;v>u;++u)(t[u][1]<t[b][1]||t[u][1]==t[b][1]&&t[u][0]<t[b][0])&&(b=u);for(u=0;v>u;++u)u!==b&&(c=t[u][1]-t[b][1],o=t[u][0]-t[b][0],M.push({angle:Math.atan2(c,o),index:u}));for(M.sort(function(n,t){return n.angle-t.angle}),g=M[0].angle,h=M[0].index,s=0,u=1;y>u;++u){if(a=M[u].index,g==M[u].angle){if(o=t[h][0]-t[b][0],c=t[h][1]-t[b][1],l=t[a][0]-t[b][0],f=t[a][1]-t[b][1],o*o+c*c>=l*l+f*f){M[u].index=-1;continue}M[s].index=-1}g=M[u].angle,s=u,h=a}for(x.push(b),u=0,a=0;2>u;++a)M[a].index>-1&&(x.push(M[a].index),u++);for(p=x.length;y>a;++a)if(!(M[a].index<0)){for(;!tr(x[p-2],x[p-1],M[a].index,t);)--p;x[p++]=M[a].index}var _=[];for(u=p-1;u>=0;--u)_.push(n[x[u]]);return _}var e=je,r=Le;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)},ua.geom.polygon=function(n){return n.area=function(){for(var t=0,e=n.length,r=n[e-1][1]*n[0][0]-n[e-1][0]*n[0][1];++t<e;)r+=n[t-1][1]*n[t][0]-n[t-1][0]*n[t][1];ret
urn.5*r},n.centroid=function(t){var e,r,i=-1,u=n.length,a=0,o=0,c=n[u-1];for(arguments.length||(t=-1/(6*n.area()));++i<u;)e=c,c=n[i],r=e[0]*c[1]-c[0]*e[1],a+=(e[0]+c[0])*r,o+=(e[1]+c[1])*r;return[a*t,o*t]},n.clip=function(t){for(var e,r,i,u,a,o,c=-1,l=n.length,f=n[l-1];++c<l;){for(e=t.slice(),t.length=0,u=n[c],a=e[(i=e.length)-1],r=-1;++r<i;)o=e[r],er(o,f,u)?(er(a,f,u)||t.push(rr(a,o,f,u)),t.push(o)):er(a,f,u)&&t.push(rr(a,o,f,u)),a=o;f=u}return t},n},ua.geom.delaunay=function(n){var t=n.map(function(){return[]}),e=[];return ir(n,function(e){t[e.region.l.index].push(n[e.region.r.index])}),t.forEach(function(t,r){var i=n[r],u=i[0],a=i[1];t.forEach(function(n){n.angle=Math.atan2(n[0]-u,n[1]-a)}),t.sort(function(n,t){return n.angle-t.angle});for(var o=0,c=t.length-1;c>o;o++)e.push([i,t[o],t[o+1]])}),e},ua.geom.voronoi=function(n){function t(n){var t,r,a,o=n.map(function(){return[]}),c=lt(i),l=lt(u),f=n.length,s=1e6;if(c===je&&l===Le)t=n;else for(t=[],a=0;f>a;++a)t.push([+c.call
(this,r=n[a],a),+l.call(this,r,a)]);if(ir(t,function(n){var t,e,r,i,u,a;n.a===1&&n.b>=0?(t=n.ep.r,e=n.ep.l):(t=n.ep.l,e=n.ep.r),n.a===1?(u=t?t.y:-s,r=n.c-n.b*u,a=e?e.y:s,i=n.c-n.b*a):(r=t?t.x:-s,u=n.c-n.a*r,i=e?e.x:s,a=n.c-n.a*i);var c=[r,u],l=[i,a];o[n.region.l.index].push(c,l),o[n.region.r.index].push(c,l)}),o=o.map(function(n,e){var r=t[e][0],i=t[e][1],u=n.map(function(n){return Math.atan2(n[0]-r,n[1]-i)
+}),a=ua.range(n.length).sort(function(n,t){return u[n]-u[t]});return a.filter(function(n,t){return!t||u[n]-u[a[t-1]]>ja}).map(function(t){return n[t]})}),o.forEach(function(n,e){var r=n.length;if(!r)return n.push([-s,-s],[-s,s],[s,s],[s,-s]);if(!(r>2)){var i=t[e],u=n[0],a=n[1],o=i[0],c=i[1],l=u[0],f=u[1],h=a[0],g=a[1],p=Math.abs(h-l),d=g-f;if(Math.abs(d)<ja){var m=f>c?-s:s;n.push([-s,m],[s,m])}else if(ja>p){var v=l>o?-s:s;n.push([v,-s],[v,s])}else{var m=(l-o)*(g-f)>(h-l)*(f-c)?s:-s,y=Math.abs(d)-p;Math.abs(y)<ja?n.push([0>d?m:-m,m]):(y>0&&(m*=-1),n.push([-s,m],[s,m]))}}}),e)for(a=0;f>a;++a)e(o[a]);for(a=0;f>a;++a)o[a].point=n[a];return o}var e,r=null,i=je,u=Le;return arguments.length?t(n):(t.x=function(n){return arguments.length?(i=n,t):i},t.y=function(n){return arguments.length?(u=n,t):u},t.size=function(n){return arguments.length?(null==n?e=null:(r=[+n[0],+n[1]],e=ua.geom.polygon([[0,0],[0,r[1]],r,[r[0],0]]).clip),t):r},t.links=function(n){var t,e,r,a=n.map(function(){retu
rn[]}),o=[],c=lt(i),l=lt(u),f=n.length;if(c===je&&l===Le)t=n;else for(r=0;f>r;++r)t.push([+c.call(this,e=n[r],r),+l.call(this,e,r)]);return ir(t,function(t){var e=t.region.l.index,r=t.region.r.index;a[e][r]||(a[e][r]=a[r][e]=!0,o.push({source:n[e],target:n[r]}))}),o},t.triangles=function(n){if(i===je&&u===Le)return ua.geom.delaunay(n);var t,e,r,a,o,c=lt(i),l=lt(u);for(a=0,t=[],o=n.length;o>a;++a)e=[+c.call(this,r=n[a],a),+l.call(this,r,a)],e.data=r,t.push(e);return ua.geom.delaunay(t).map(function(n){return n.map(function(n){return n.data})})},t)};var Po={l:"r",r:"l"};ua.geom.quadtree=function(n,t,e,r,i){function u(n){function u(n,t,e,r,i,u,a,o){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,f=n.y;if(null!=c)if(Math.abs(c-e)+Math.abs(f-r)<.01)l(n,t,e,r,i,u,a,o);else{var s=n.point;n.x=n.y=n.point=null,l(n,s,c,f,i,u,a,o),l(n,t,e,r,i,u,a,o)}else n.x=e,n.y=r,n.point=t}else l(n,t,e,r,i,u,a,o)}function l(n,t,e,r,i,a,o,c){var l=.5*(i+o),f=.5*(a+c),s=e>=l,h=r>=f,g=(h<<1)+s;n.leaf=!1,n
=n.nodes[g]||(n.nodes[g]=or()),s?i=l:o=l,h?a=f:c=f,u(n,t,e,r,i,a,o,c)}var f,s,h,g,p,d,m,v,y,M=lt(o),x=lt(c);if(null!=t)d=t,m=e,v=r,y=i;else if(v=y=-(d=m=1/0),s=[],h=[],p=n.length,a)for(g=0;p>g;++g)f=n[g],f.x<d&&(d=f.x),f.y<m&&(m=f.y),f.x>v&&(v=f.x),f.y>y&&(y=f.y),s.push(f.x),h.push(f.y);else for(g=0;p>g;++g){var b=+M(f=n[g],g),_=+x(f,g);d>b&&(d=b),m>_&&(m=_),b>v&&(v=b),_>y&&(y=_),s.push(b),h.push(_)}var w=v-d,S=y-m;w>S?y=m+w:v=d+S;var E=or();if(E.add=function(n){u(E,n,+M(n,++g),+x(n,g),d,m,v,y)},E.visit=function(n){cr(n,E,d,m,v,y)},g=-1,null==t){for(;++g<p;)u(E,n[g],s[g],h[g],d,m,v,y);--g}else n.forEach(E.add);return s=h=n=f=null,E}var a,o=je,c=Le;return(a=arguments.length)?(o=ur,c=ar,3===a&&(i=e,r=t,e=t=0),u(n)):(u.x=function(n){return arguments.length?(o=n,u):o},u.y=function(n){return arguments.length?(c=n,u):c},u.size=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=e=0,r=+n[0],i=+n[1]),u):null==t?null:[r,i]},u)},ua.interpolateRgb=lr,ua.transform=function(n){v
ar t=aa.createElementNS(ua.ns.prefix.svg,"g");return(ua.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new fr(e?e.matrix:Ro)})(n)},fr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var Ro={a:1,b:0,c:0,d:1,e:0,f:0};ua.interpolateNumber=pr,ua.interpolateTransform=dr,ua.interpolateObject=mr,ua.interpolateString=vr;var Oo=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;ua.interpolate=yr,ua.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?lr:vr:t instanceof L?lr:"object"===e?Array.isArray(t)?xr:mr:pr)(n,t)}],ua.interpolateArray=xr;var Yo=function(){return ft},Uo=ua.map({linear:Yo,poly:Ar,quad:function(){return Sr},cubic:function(){return Er},sin:function(){return Nr},exp:function(){return qr},circle:function(){return Tr},elastic:Cr,back:zr,bounce:function(){return Dr}}),Io=ua.map({"
in":ft,out:_r,"in-out":wr,"out-in":function(n){return wr(_r(n))}});ua.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=Uo.get(e)||Yo,r=Io.get(r)||ft,br(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},ua.interpolateHcl=jr,ua.interpolateHsl=Lr,ua.interpolateLab=Fr,ua.interpolateRound=Hr,ua.layout={},ua.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Or(n[e]));return t}},ua.layout.chord=function(){function n(){var n,l,s,h,g,p={},d=[],m=ua.range(u),v=[];for(e=[],r=[],n=0,h=-1;++h<u;){for(l=0,g=-1;++g<u;)l+=i[h][g];d.push(l),v.push(ua.range(u)),n+=l}for(a&&m.sort(function(n,t){return a(d[n],d[t])}),o&&v.forEach(function(n,t){n.sort(function(n,e){return o(i[t][n],i[t][e])})}),n=(2*Da-f*u)/n,l=0,h=-1;++h<u;){for(s=l,g=-1;++g<u;){var y=m[h],M=v[y][g],x=i[y][M],b=l,_=l+=x*n;p[y+"-"+M]={index:y,subindex:M,startAngle:b,endAngle:_,value:x}}r[y]={index:y,startAngle:s,endAngle:l,value:(l
-s)/n},l+=f}for(h=-1;++h<u;)for(g=h-1;++g<u;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,i,u,a,o,c,l={},f=0;return l.matrix=function(n){return arguments.length?(u=(i=n)&&i.length,e=r=null,l):i},l.padding=function(n){return arguments.length?(f=n,e=r=null,l):f},l.sortGroups=function(n){return arguments.length?(a=n,e=r=null,l):a},l.sortSubgroups=function(n){return arguments.length?(o=n,e=null,l):o},l.sortChords=function(n){return arguments.length?(c=n,e&&t(),l):c},l.chords=function(){return e||n(),e},l.groups=function(){return r||n(),r},l},ua.layout.force=function(){function n(n){return function(t,e,r,i){if(t.point!==n){var u=t.cx-n.x,a=t.cy-n.y,o=1/Math.sqrt(u*u+a*a);if(d>(i-e)*o){var c=t.charge*o*o;return n.px-=u*c,n.py-=a*c,!0}if(t.point&&isFinite(o)){var c=t.pointCharge*o*o;n.p
x-=u*c,n.py-=a*c}}return!t.charge}}function t(n){n.px=ua.event.x,n.py=ua.event.y,o.resume()}var e,r,i,u,a,o={},c=ua.dispatch("start","tick","end"),l=[1,1],f=.9,s=Vo,h=Xo,g=-30,p=.1,d=.8,m=[],v=[];return o.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,o,s,h,d,y,M,x,b=m.length,_=v.length;for(e=0;_>e;++e)o=v[e],s=o.source,h=o.target,M=h.x-s.x,x=h.y-s.y,(d=M*M+x*x)&&(d=r*u[e]*((d=Math.sqrt(d))-i[e])/d,M*=d,x*=d,h.x-=M*(y=s.weight/(h.weight+s.weight)),h.y-=x*y,s.x+=M*(y=1-y),s.y+=x*y);if((y=r*p)&&(M=l[0]/2,x=l[1]/2,e=-1,y))for(;++e<b;)o=m[e],o.x+=(M-o.x)*y,o.y+=(x-o.y)*y;if(g)for(Br(t=ua.geom.quadtree(m),r,a),e=-1;++e<b;)(o=m[e]).fixed||t.visit(n(o));for(e=-1;++e<b;)o=m[e],o.fixed?(o.x=o.px,o.y=o.py):(o.x-=(o.px-(o.px=o.x))*f,o.y-=(o.py-(o.py=o.y))*f);c.tick({type:"tick",alpha:r})},o.nodes=function(n){return arguments.length?(m=n,o):m},o.links=function(n){return arguments.length?(v=n,o):v},o.size=function(n){return arguments.length?(l=n,o):l},o.
linkDistance=function(n){return arguments.length?(s="function"==typeof n?n:+n,o):s},o.distance=o.linkDistance,o.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,o):h},o.friction=function(n){return arguments.length?(f=+n,o):f},o.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,o):g},o.gravity=function(n){return arguments.length?(p=+n,o):p},o.theta=function(n){return arguments.length?(d=+n,o):d},o.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),ua.timer(o.tick)),o):r},o.start=function(){function n(n,r){for(var i,u=t(e),a=-1,o=u.length;++a<o;)if(!isNaN(i=u[a][n]))return i;return Math.random()*r}function t(){if(!c){for(c=[],r=0;p>r;++r)c[r]=[];for(r=0;d>r;++r){var n=v[r];c[n.source.index].push(n.target),c[n.target.index].push(n.source)}}return c[e]}var e,r,c,f,p=m.length,d=v.length,y=l[0],M=l[1];for(e=0;p>e;++e)(f=m[e]).index=e,f.weight=0;for(e=0;d>e;++e)f=v[e],typeof f.source
=="number"&&(f.source=m[f.source]),typeof f.target=="number"&&(f.target=m[f.target]),++f.source.weight,++f.target.weight;for(e=0;p>e;++e)f=m[e],isNaN(f.x)&&(f.x=n("x",y)),isNaN(f.y)&&(f.y=n("y",M)),isNaN(f.px)&&(f.px=f.x),isNaN(f.py)&&(f.py=f.y);if(i=[],"function"==typeof s)for(e=0;d>e;++e)i[e]=+s.call(this,v[e],e);else for(e=0;d>e;++e)i[e]=s;if(u=[],"function"==typeof h)for(e=0;d>e;++e)u[e]=+h.call(this,v[e],e);else for(e=0;d>e;++e)u[e]=h;if(a=[],"function"==typeof g)for(e=0;p>e;++e)a[e]=+g.call(this,m[e],e);else for(e=0;p>e;++e)a[e]=g;return o.resume()},o.resume=function(){return o.alpha(.1)},o.stop=function(){return o.alpha(0)},o.drag=function(){return e||(e=ua.behavior.drag().origin(ft).on("dragstart.force",Ir).on("drag.force",t).on("dragend.force",Vr)),arguments.length?(this.on("mouseover.force",Xr).on("mouseout.force",Zr).call(e),void 0):e},ua.rebind(o,c,"on")};var Vo=20,Xo=1;ua.layout.hierarchy=function(){function n(t,a,o){var c=i.call(e,t,a);if(t.depth=a,o.push(t),c&
&(l=c.length)){for(var l,f,s=-1,h=t.children=[],g=0,p=a+1;++s<l;)f=n(c[s],p,o),f.parent=t,h.push(f),g+=f.value;r&&h.sort(r),u&&(t.value=g)}else u&&(t.value=+u.call(e,t,a)||0);return t}function t(n,r){var i=n.children,a=0;if(i&&(o=i.length))for(var o,c=-1,l=r+1;++c<o;)a+=t(i[c],l);else u&&(a=+u.call(e,n,r)||0);return u&&(n.value=a),a}function e(t){var e=[];return n(t,0,e),e}var r=Kr,i=Jr,u=Gr;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(i=n,e):i},e.value=function(n){return arguments.length?(u=n,e):u},e.revalue=function(n){return t(n,0),n},e},ua.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(a=u.length)){var a,o,c,l=-1;for(r=t.value?r/t.value:0;++l<a;)n(o=u[l],e,c=o.value*r,i),e+=c}}function t(n){var e=n.children,r=0;if(e&&(i=e.length))for(var i,u=-1;++u<i;)r=Math.max(r,t(e[u]));return 1+r}function e(e,u){var a=r.call(this,e,u);return n(a[0],0,i[0],i[1]/t(
a[0])),a}var r=ua.layout.hierarchy(),i=[1,1];return e.size=function(n){return arguments.length?(i=n,e):i},$r(e,r)},ua.layout.pie=function(){function n(u){var a=u.map(function(e,r){return+t.call(n,e,r)}),o=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof i?i.apply(this,arguments):i)-o)/ua.sum(a),l=ua.range(u.length);null!=e&&l.sort(e===Zo?function(n,t){return a[t]-a[n]}:function(n,t){return e(u[n],u[t])});var f=[];return l.forEach(function(n){var t;f[n]={data:u[n],value:t=a[n],startAngle:o,endAngle:o+=t*c}}),f}var t=Number,e=Zo,r=0,i=2*Da;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n};var Zo={};ua.layout.stack=function(){function n(o,c){var l=o.map(function(e,r){return t.call(n,e,r)}),f=l.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),a.call(n,t,e)]
})}),s=e.call(n,f,c);l=ua.permute(l,s),f=ua.permute(f,s);var h,g,p,d=r.call(n,f,c),m=l.length,v=l[0].length;for(g=0;v>g;++g)for(i.call(n,l[0][g],p=d[g],f[0][g][1]),h=1;m>h;++h)i.call(n,l[h][g],p+=f[h-1][g][1],f[h][g][1]);return o}var t=ft,e=ei,r=ri,i=ti,u=Qr,a=ni;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:Bo.get(t)||ei,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:$o.get(t)||ri,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(a=t,n):a},n.out=function(t){return arguments.length?(i=t,n):i},n};var Bo=ua.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(ii),u=n.map(ui),a=ua.range(r).sort(function(n,t){return i[n]-i[t]}),o=0,c=0,l=[],f=[];for(t=0;r>t;++t)e=a[t],c>o?(o+=u[e],l.push(e)):(c+=u[e],f.push(e));return f.reverse().concat(l)},reverse:function(n){return ua.range(n.length).reverse()},"default":ei}),$
o=ua.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,a=[],o=0,c=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>o&&(o=r),a.push(r)}for(e=0;u>e;++e)c[e]=(o-a[e])/2;return c},wiggle:function(n){var t,e,r,i,u,a,o,c,l,f=n.length,s=n[0],h=s.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,o=s[e][0]-s[e-1][0];f>t;++t){for(r=0,a=(n[t][e][1]-n[t][e-1][1])/(2*o);t>r;++r)a+=(n[r][e][1]-n[r][e-1][1])/o;u+=a*n[t][e][1]}g[e]=c-=i?u/i*o:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,i=n.length,u=n[0].length,a=1/i,o=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=a}for(e=0;u>e;++e)o[e]=0;return o},zero:ri});ua.layout.histogram=function(){function n(n,u){for(var a,o,c=[],l=n.map(e,this),f=r.call(this,l,u),s=i.call(this,f,l,u),u=-1,h=l.length,g=s.length-1,p=t?1:1/h;++u<g;)a=c[u]=[],a.dx=s[u+1]-(a.x=s[u]),a.y=0;if(g>0)for(u=-1;++u<h;
)o=l[u],o>=f[0]&&o<=f[1]&&(a=c[ua.bisect(s,o,1,g)-1],a.y+=p,a.push(n[u]));return c}var t=!0,e=Number,r=li,i=oi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=lt(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return ci(n,t)}:lt(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ua.layout.tree=function(){function n(n,i){function u(n,t){var r=n.children,i=n._tree;if(r&&(a=r.length)){for(var a,c,l,f=r[0],s=f,h=-1;++h<a;)l=r[h],u(l,c),s=o(l,c,s),c=l;yi(n);var g=.5*(f._tree.prelim+l._tree.prelim);t?(i.prelim=t._tree.prelim+e(n,t),i.mod=i.prelim-g):i.prelim=g}else t&&(i.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,i=-1;for(t+=n._tree.mod;++i<r;)a(e[i],t)}}function o(n,t,r){if(t){for(var i,u=n,a=n,o=t,c=n.parent.children[0],l=u._tree.mod,f=a._tree.mod,s=o._tree.mod,h=c._tree.mod;o=hi(o),u=si(u),o&&
u;)c=si(c),a=hi(a),a._tree.ancestor=n,i=o._tree.prelim+s-u._tree.prelim-l+e(o,u),i>0&&(Mi(xi(o,n,r),n,i),l+=i,f+=i),s+=o._tree.mod,l+=u._tree.mod,h+=c._tree.mod,f+=a._tree.mod;o&&!hi(a)&&(a._tree.thread=o,a._tree.mod+=s-f),u&&!si(c)&&(c._tree.thread=u,c._tree.mod+=l-h,r=n)}return r}var c=t.call(this,n,i),l=c[0];vi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),u(l),a(l,-l._tree.prelim);var f=gi(l,di),s=gi(l,pi),h=gi(l,mi),g=f.x-e(f,s)/2,p=s.x+e(s,f)/2,d=h.depth||1;return vi(l,function(n){n.x=(n.x-g)/(p-g)*r[0],n.y=n.depth/d*r[1],delete n._tree}),c}var t=ua.layout.hierarchy().sort(null).value(null),e=fi,r=[1,1];return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(r=t,n):r},$r(n,t)},ua.layout.pack=function(){function n(n,i){var u=t.call(this,n,i),a=u[0];a.x=0,a.y=0,vi(a,function(n){n.r=Math.sqrt(n.value)}),vi(a,Ei);var o=r[0],c=r[1],l=Math.max(2*a.r/o,2*a.r/c);if(e>0){
var f=e*l/2;vi(a,function(n){n.r+=f}),vi(a,Ei),vi(a,function(n){n.r-=f}),l=Math.max(2*a.r/o,2*a.r/c)}return Ni(a,o/2,c/2,1/l),u}var t=ua.layout.hierarchy().sort(bi),e=0,r=[1,1];return n.size=function(t){return arguments.length?(r=t,n):r},n.padding=function(t){return arguments.length?(e=+t,n):e},$r(n,t)},ua.layout.cluster=function(){function n(n,i){var u,a=t.call(this,n,i),o=a[0],c=0;vi(o,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ti(t)):(n.x=u?c+=e(n,u):0,n.y=0,u=n)});var l=zi(o),f=Di(o),s=l.x-e(l,f)/2,h=f.x+e(f,l)/2;return vi(o,function(n){n.x=(n.x-s)/(h-s)*r[0],n.y=(1-(o.y?n.y/o.y:1))*r[1]}),a}var t=ua.layout.hierarchy().sort(null).value(null),e=fi,r=[1,1];return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(r=t,n):r},$r(n,t)},ua.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++i<u;)r=(e=n[i]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length)
{var a,o,c,l=s(e),f=[],h=u.slice(),p=1/0,d="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?e.depth&1?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),f.area=0;(c=h.length)>0;)f.push(a=h[c-1]),f.area+=a.area,"squarify"!==g||(o=r(f,d))<=p?(h.pop(),p=o):(f.area-=f.pop().area,i(f,d,l,!1),d=Math.min(l.dx,l.dy),f.length=f.area=0,p=1/0);f.length&&(i(f,d,l,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,a=s(t),o=r.slice(),c=[];for(n(o,a.dx*a.dy/t.value),c.area=0;u=o.pop();)c.push(u),c.area+=u.area,u.z!=null&&(i(c,u.z?a.dx:a.dy,a,!o.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,a=-1,o=n.length;++a<o;)(e=n[a].area)&&(u>e&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*p/r,r/(t*u*p)):1/0}function i(n,t,e,r){var i,u=-1,a=n.length,o=e.x,l=e.y,f=t?c(n.area/t):0;if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++u<a;)i=n[u],i.x=o,i.y=l,i.dy=f,o+=i.dx=Math.min(e.x+e.dx-o,f?c(i.area/f):0);i.z=!0,i.dx+=e.x+e.d
x-o,e.y+=f,e.dy-=f}else{for((r||f>e.dx)&&(f=e.dx);++u<a;)i=n[u],i.x=o,i.y=l,i.dx=f,l+=i.dy=Math.min(e.y+e.dy-l,f?c(i.area/f):0);i.z=!1,i.dy+=e.y+e.dy-l,e.x+=f,e.dx-=f}}function u(r){var i=a||o(r),u=i[0];return u.x=0,u.y=0,u.dx=l[0],u.dy=l[1],a&&o.revalue(u),n([u],u.dx*u.dy/u.value),(a?e:t)(u),h&&(a=i),i}var a,o=ua.layout.hierarchy(),c=Math.round,l=[1,1],f=null,s=ji,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return u.size=function(n){return arguments.length?(l=n,u):l},u.padding=function(n){function t(t){var e=n.call(u,t,t.depth);return null==e?ji(t):Li(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Li(t,n)}if(!arguments.length)return f;var r;return s=(f=n)==null?ji:(r=typeof n)=="function"?t:"number"===r?(n=[n,n,n,n],e):e,u},u.round=function(n){return arguments.length?(c=n?Math.round:Number,u):c!=Number},u.sticky=function(n){return arguments.length?(h=n,a=null,u):h},u.ratio=function(n){return arguments.length?(p=n,u):p},u.mode=function(n){return arguments.length?(g=n+"",
u):g},$r(u,o)},ua.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=Math.random()*2-1,r=Math.random()*2-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ua.random.normal.apply(ua,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}}},ua.scale={},ua.scale.linear=function(){return Yi([0,1],[0,1],yr,!1)},ua.scale.log=function(){return Bi(ua.scale.linear().domain([0,Math.LN10]),10,$i,Ji,[1,10])};var Jo=ua.format(".0e");ua.scale.pow=function(){return Wi(ua.scale.linear(),1,[0,1])},ua.scale.sqrt=function(){return ua.scale.pow().exponent(.5)},ua.scale.ordinal=function(){return nu([],{t:"range",a:[[]]})},ua.scale.category10=function(){return ua.scale.ordinal().range(Go)},ua.scale.category20=function(){return ua.scale.ordinal().range(Ko)},ua.scale.category20b=function(){return ua.scale.ordi
nal().range(Wo)},ua.scale.category20c=function(){return ua.scale.ordinal().range(Qo)};var Go=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],Ko=["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"],Wo=["#393b79","#5254a3","#6b6ecf","#9c9ede","#637939","#8ca252","#b5cf6b","#cedb9c","#8c6d31","#bd9e39","#e7ba52","#e7cb94","#843c39","#ad494a","#d6616b","#e7969c","#7b4173","#a55194","#ce6dbd","#de9ed6"],Qo=["#3182bd","#6baed6","#9ecae1","#c6dbef","#e6550d","#fd8d3c","#fdae6b","#fdd0a2","#31a354","#74c476","#a1d99b","#c7e9c0","#756bb1","#9e9ac8","#bcbddc","#dadaeb","#636363","#969696","#bdbdbd","#d9d9d9"];ua.scale.quantile=function(){return tu([],[])},ua.scale.quantize=function(){return eu(0,1,[0,1])},ua.scale.threshold=function(){return ru([.5],[0,1])},ua.scale.identity=function()
{return iu([0,1])},ua.svg.arc=function(){function n(){var n=t.apply(this,arguments),u=e.apply(this,arguments),a=r.apply(this,arguments)+nc,o=i.apply(this,arguments)+nc,c=(a>o&&(c=a,a=o,o=c),o-a),l=Da>c?"0":"1",f=Math.cos(a),s=Math.sin(a),h=Math.cos(o),g=Math.sin(o);return c>=tc?n?"M0,"+u+"A"+u+","+u+" 0 1,1 0,"+-u+"A"+u+","+u+" 0 1,1 0,"+u+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+u+"A"+u+","+u+" 0 1,1 0,"+-u+"A"+u+","+u+" 0 1,1 0,"+u+"Z":n?"M"+u*f+","+u*s+"A"+u+","+u+" 0 "+l+",1 "+u*h+","+u*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+l+",0 "+n*f+","+n*s+"Z":"M"+u*f+","+u*s+"A"+u+","+u+" 0 "+l+",1 "+u*h+","+u*g+"L0,0"+"Z"}var t=uu,e=au,r=ou,i=cu;return n.innerRadius=function(e){return arguments.length?(t=lt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=lt(t),n):e},n.startAngle=function(t){return arguments.length?(r=lt(t),n):r},n.endAngle=function(t){return arguments.length?(i=lt(t),n):i},n.centroid=function(){var n=(t.apply(this,arguments
)+e.apply(this,arguments))/2,u=(r.apply(this,arguments)+i.apply(this,arguments))/2+nc;return[Math.cos(u)*n,Math.sin(u)*n]},n};var nc=-Da/2,tc=2*Da-1e-6;ua.svg.line.radial=function(){var n=De(lu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},Pe.reverse=Re,Re.reverse=Pe,ua.svg.area=function(){return fu(ft)},ua.svg.area.radial=function(){var n=fu(lu);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},ua.svg.chord=function(){function n(n,o){var c=t(this,u,n,o),l=t(this,a,n,o);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?i(c.r,c.p1,c.r,c.p0):i(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+i(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=o.call(n,i,r),a=c.call(n,i,r)+nc,f=l.call(n,i,r)+nc;return{r:u,a0:a,a1:f,p0:[u*Math.cos(a),u*Math.sin(a)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n
,t,e){return"A"+n+","+n+" 0 "+ +(e>Da)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=se,a=he,o=su,c=ou,l=cu;return n.radius=function(t){return arguments.length?(o=lt(t),n):o},n.source=function(t){return arguments.length?(u=lt(t),n):u},n.target=function(t){return arguments.length?(a=lt(t),n):a},n.startAngle=function(t){return arguments.length?(c=lt(t),n):c},n.endAngle=function(t){return arguments.length?(l=lt(t),n):l},n},ua.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),a=e.call(this,n,i),o=(u.y+a.y)/2,c=[u,{x:u.x,y:o},{x:a.x,y:o},a];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=se,e=he,r=hu;return n.source=function(e){return arguments.length?(t=lt(e),n):t},n.target=function(t){return arguments.length?(e=lt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ua.svg.diagonal.radial=function(){var n=ua.svg.diagonal(),t=hu,e=n.projection;return n.projection=function(n){return arguments.length?e(gu(t=n)):t},n},ua.svg.symbol=f
unction(){function n(n,r){return(ec.get(t.call(this,n,r))||mu)(e.call(this,n,r))}var t=du,e=pu;return n.type=function(e){return arguments.length?(t=lt(e),n):t},n.size=function(t){return arguments.length?(e=lt(t),n):e},n};var ec=ua.map({circle:mu,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*uc)),e=t*uc;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/ic),e=t*ic/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/ic),e=t*ic/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ua.svg.symbolTypes=ec.keys();var rc,ic=Math.sqrt(3),uc=Math.tan(30*La),ac=[],oc=0,cc={ease:kr,delay:0,duration:250};ac.call=wa.call,ac.empty=wa.empty,ac.node=wa.node,ua.transition=
function(n){return arguments.length?rc?n.transition():n:Na.transition()},ua.transition.prototype=ac,ac.select=function(n){var t,e,r,i=this.id,u=[];"function"!=typeof n&&(n=v(n));for(var a=-1,o=this.length;++a<o;){u.push(t=[]);for(var c=this[a],l=-1,f=c.length;++l<f;)(r=c[l])&&(e=n.call(r,r.__data__,l))?("__data__"in r&&(e.__data__=r.__data__),xu(e,l,i,r.__transition__[i]),t.push(e)):t.push(null)}return vu(u,i)},ac.selectAll=function(n){var t,e,r,i,u,a=this.id,o=[];"function"!=typeof n&&(n=y(n));for(var c=-1,l=this.length;++c<l;)for(var f=this[c],s=-1,h=f.length;++s<h;)if(r=f[s]){u=r.__transition__[a],e=n.call(r,r.__data__,s),o.push(t=[]);for(var g=-1,p=e.length;++g<p;)xu(i=e[g],g,a,u),t.push(i)}return vu(o,a)},ac.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=A(n));for(var u=0,a=this.length;a>u;u++){i.push(t=[]);for(var e=this[u],o=0,c=e.length;c>o;o++)(r=e[o])&&n.call(r,r.__data__,o)&&t.push(r)}return vu(i,this.id,this.time).ease(this.ease())},ac.tween=function(
n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):D(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},ac.attr=function(n,t){function e(){this.removeAttribute(o)}function r(){this.removeAttributeNS(o.space,o.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(o);return e!==n&&(t=a(e,n),function(n){this.setAttribute(o,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(o.space,o.local);return e!==n&&(t=a(e,n),function(n){this.setAttributeNS(o.space,o.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var a=Mr(n),o=ua.ns.qualify(n);return yu(this,"attr."+n,t,o.local?u:i)},ac.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return
r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ua.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},ac.style=function(n,t,e){function r(){this.style.removeProperty(n)}function i(t){return null==t?r:(t+="",function(){var r,i=oa.getComputedStyle(this,null).getPropertyValue(n);return i!==t&&(r=a(i,t),function(t){this.style.setProperty(n,r(t),e)})})}var u=arguments.length;if(3>u){if("string"!=typeof n){2>u&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}var a=Mr(n);return yu(this,"style."+n,t,i)},ac.styleTween=function(n,t,e){function r(r,i){var u=t.call(this,r,i,oa.getComputedStyle(this,null).getPropertyValue(n));return u&&function(t){this.style.setProperty(n,u(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},ac.text=function(n){return yu(this,"text",n,Mu)},ac.remove=function(){return this.each("end.transition",function(){var n;!this.__transition__&&(n=this.parentNode)&&n.removeChild(this)})},ac.ease=function(n){var t=this.id;re
turn arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=ua.ease.apply(ua,arguments)),D(this,function(e){e.__transition__[t].ease=n}))},ac.delay=function(n){var t=this.id;return D(this,"function"==typeof n?function(e,r,i){e.__transition__[t].delay=n.call(e,e.__data__,r,i)|0}:(n|=0,function(e){e.__transition__[t].delay=n}))},ac.duration=function(n){var t=this.id;return D(this,"function"==typeof n?function(e,r,i){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,i)|0)}:(n=Math.max(1,0|n),function(e){e.__transition__[t].duration=n}))},ac.each=function(n,t){var e=this.id;if(arguments.length<2){var r=cc,i=rc;rc=e,D(this,function(t,r,i){cc=t.__transition__[e],n.call(t,t.__data__,r,i)}),cc=r,rc=i}else D(this,function(r){r.__transition__[e].event.on(n,t)});return this},ac.transition=function(){for(var n,t,e,r,i=this.id,u=++oc,a=[],o=0,c=this.length;c>o;o++){a.push(n=[]);for(var t=this[o],l=0,f=t.length;f>l;l++)(e=t[l])&&(r=Object.create(e.__tr
ansition__[i]),r.delay+=r.duration,xu(e,l,u,r)),n.push(e)}return vu(a,u)},ua.svg.axis=function(){function n(n){n.each(function(){var n,s=ua.select(this),h=null==l?e.ticks?e.ticks.apply(e,c):e.domain():l,g=null==t?e.tickFormat?e.tickFormat.apply(e,c):String:t,p=wu(e,h,f),d=s.selectAll(".tick.minor").data(p,String),m=d.enter().insert("line",".tick").attr("class","tick minor").style("opacity",1e-6),v=ua.transition(d.exit()).style("opacity",1e-6).remove(),y=ua.transition(d).style("opacity",1),M=s.selectAll(".tick.major").data(h,String),x=M.enter().insert("g","path").attr("class","tick major").style("opacity",1e-6),b=ua.transition(M.exit()).style("opacity",1e-6).remove(),_=ua.transition(M).style("opacity",1),w=Hi(e),S=s.selectAll(".domain").data([0]),E=(S.enter().append("path").attr("class","domain"),ua.transition(S)),k=e.copy(),A=this.__chart__||k;this.__chart__=k,x.append("line"),x.append("text");var N=x.select("line"),q=_.select("line"),T=M.select("text").text(g),C=x.select("t
ext"),z=_.select("text");switch(r){case"bottom":n=bu,m.attr("y2",u),y.attr("x2",0).attr("y2",u),N.attr("y2",i),C.attr("y",Math.max(i,0)+o),q.attr("x2",0).attr("y2",i),z.attr("x",0).attr("y",Math.max(i,0)+o),T.attr("dy",".71em").style("text-anchor","middle"),E.attr("d","M"+w[0]+","+a+"V0H"+w[1]+"V"+a);break;case"top":n=bu,m.attr("y2",-u),y.attr("x2",0).attr("y2",-u),N.attr("y2",-i),C.attr("y",-(Math.max(i,0)+o)),q.attr("x2",0).attr("y2",-i),z.attr("x",0).attr("y",-(Math.max(i,0)+o)),T.attr("dy","0em").style("text-anchor","middle"),E.attr("d","M"+w[0]+","+-a+"V0H"+w[1]+"V"+-a);break;case"left":n=_u,m.attr("x2",-u),y.attr("x2",-u).attr("y2",0),N.attr("x2",-i),C.attr("x",-(Math.max(i,0)+o)),q.attr("x2",-i).attr("y2",0),z.attr("x",-(Math.max(i,0)+o)).attr("y",0),T.attr("dy",".32em").style("text-anchor","end"),E.attr("d","M"+-a+","+w[0]+"H0V"+w[1]+"H"+-a);break;case"right":n=_u,m.attr("x2",u),y.attr("x2",u).attr("y2",0),N.attr("x2",i),C.attr("x",Math.max(i,0)+o),q.attr("x2",i).att
r("y2",0),z.attr("x",Math.max(i,0)+o).attr("y",0),T.attr("dy",".32em").style("text-anchor","start"),E.attr("d","M"+a+","+w[0]+"H0V"+w[1]+"H"+a)}if(e.ticks)x.call(n,A),_.call(n,k),b.call(n,k),m.call(n,A),y.call(n,k),v.call(n,k);else{var D=k.rangeBand()/2,j=function(n){return k(n)+D};x.call(n,j),_.call(n,j)}})}var t,e=ua.scale.linear(),r=lc,i=6,u=6,a=6,o=3,c=[10],l=null,f=0;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in fc?t+"":lc,n):r},n.ticks=function(){return arguments.length?(c=arguments,n):c},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t,e){if(!arguments.length)return i;var r=arguments.length-1;return i=+t,u=r>1?+e:i,a=r>0?+arguments[r]:i,n},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(t){return arguments.length?(f=+t,n):f},n};var lc="bottom",fc={top:1,right:1,bottom:1,
left:1};ua.svg.brush=function(){function n(u){u.each(function(){var u,a=ua.select(this),l=a.selectAll(".background").data([0]),s=a.selectAll(".extent").data([0]),h=a.selectAll(".resize").data(f,String);a.style("pointer-events","all").on("mousedown.brush",i).on("touchstart.brush",i),l.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),s.enter().append("rect").attr("class","extent").style("cursor","move"),h.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return sc[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"),h.style("display",n.empty()?"none":null),h.exit().remove(),o&&(u=Hi(o),l.attr("x",u[0]).attr("width",u[1]-u[0]),e(a)),c&&(u=Hi(c),l.attr("y",u[0]).attr("height",u[1]-u[0]),r(a)),t(a)})}function t(n){n.selectAll(".resize").attr("transf
orm",function(n){return"translate("+s[+/e$/.test(n)][0]+","+s[+/^s/.test(n)][1]+")"})}function e(n){n.select(".extent").attr("x",s[0][0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1][0]-s[0][0])}function r(n){n.select(".extent").attr("y",s[0][1]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",s[1][1]-s[0][1])}function i(){function i(){var n=ua.event.changedTouches;
+return n?ua.touches(y,n)[0]:ua.mouse(y)}function f(){ua.event.keyCode==32&&(E||(m=null,k[0]-=s[1][0],k[1]-=s[1][1],E=2),l())}function h(){ua.event.keyCode==32&&2==E&&(k[0]+=s[1][0],k[1]+=s[1][1],E=0,l())}function g(){var n=i(),u=!1;v&&(n[0]+=v[0],n[1]+=v[1]),E||(ua.event.altKey?(m||(m=[(s[0][0]+s[1][0])/2,(s[0][1]+s[1][1])/2]),k[0]=s[+(n[0]<m[0])][0],k[1]=s[+(n[1]<m[1])][1]):m=null),w&&p(n,o,0)&&(e(b),u=!0),S&&p(n,c,1)&&(r(b),u=!0),u&&(t(b),x({type:"brush",mode:E?"move":"resize"}))}function p(n,t,e){var r,i,a=Hi(t),o=a[0],c=a[1],l=k[e],f=s[1][e]-s[0][e];return E&&(o-=l,c-=f+l),r=Math.max(o,Math.min(c,n[e])),E?i=(r+=l)+f:(m&&(l=Math.max(o,Math.min(c,2*m[e]-r))),r>l?(i=r,r=l):i=l),s[0][e]!==r||s[1][e]!==i?(u=null,s[0][e]=r,s[1][e]=i,!0):void 0}function d(){g(),b.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ua.select("body").style("cursor",null),A.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touc
hend.brush",null).on("keydown.brush",null).on("keyup.brush",null),x({type:"brushend"}),l()}var m,v,y=this,M=ua.select(ua.event.target),x=a.of(y,arguments),b=ua.select(y),_=M.datum(),w=!/^(n|s)$/.test(_)&&o,S=!/^(e|w)$/.test(_)&&c,E=M.classed("extent"),k=i(),A=ua.select(oa).on("mousemove.brush",g).on("mouseup.brush",d).on("touchmove.brush",g).on("touchend.brush",d).on("keydown.brush",f).on("keyup.brush",h);if(E)k[0]=s[0][0]-k[0],k[1]=s[0][1]-k[1];else if(_){var N=+/w$/.test(_),q=+/^n/.test(_);v=[s[1-N][0]-k[0],s[1-q][1]-k[1]],k[0]=s[N][0],k[1]=s[q][1]}else ua.event.altKey&&(m=k.slice());b.style("pointer-events","none").selectAll(".resize").style("display",null),ua.select("body").style("cursor",M.style("cursor")),x({type:"brushstart"}),g(),l()}var u,a=h(n,"brushstart","brush","brushend"),o=null,c=null,f=hc[0],s=[[0,0],[0,0]];return n.x=function(t){return arguments.length?(o=t,f=hc[!o<<1|!c],n):o},n.y=function(t){return arguments.length?(c=t,f=hc[!o<<1|!c],n):c},n.extent=functi
on(t){var e,r,i,a,l;return arguments.length?(u=[[0,0],[0,0]],o&&(e=t[0],r=t[1],c&&(e=e[0],r=r[0]),u[0][0]=e,u[1][0]=r,o.invert&&(e=o(e),r=o(r)),e>r&&(l=e,e=r,r=l),s[0][0]=0|e,s[1][0]=0|r),c&&(i=t[0],a=t[1],o&&(i=i[1],a=a[1]),u[0][1]=i,u[1][1]=a,c.invert&&(i=c(i),a=c(a)),i>a&&(l=i,i=a,a=l),s[0][1]=0|i,s[1][1]=0|a),n):(t=u||s,o&&(e=t[0][0],r=t[1][0],u||(e=s[0][0],r=s[1][0],o.invert&&(e=o.invert(e),r=o.invert(r)),e>r&&(l=e,e=r,r=l))),c&&(i=t[0][1],a=t[1][1],u||(i=s[0][1],a=s[1][1],c.invert&&(i=c.invert(i),a=c.invert(a)),i>a&&(l=i,i=a,a=l))),o&&c?[[e,i],[r,a]]:o?[e,r]:c&&[i,a])},n.clear=function(){return u=null,s[0][0]=s[0][1]=s[1][0]=s[1][1]=0,n},n.empty=function(){return o&&s[0][0]===s[1][0]||c&&s[0][1]===s[1][1]},ua.rebind(n,a,"on")};var sc={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},hc=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]];ua.time={};var gc=Date,pc=["Sunday","Monday","T
uesday","Wednesday","Thursday","Friday","Saturday"];Su.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(){dc.setUTCDate.apply(this._,arguments)},setDay:function(){dc.setUTCDay.apply(this._,arguments)},setFullYear:function(){dc.setUTCFullYear.apply(this._,arguments)},setHours:function(){dc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){dc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){dc.setUTCMinutes.apply(this._,arguments)},setM
onth:function(){dc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){dc.setUTCSeconds.apply(this._,arguments)},setTime:function(){dc.setTime.apply(this._,arguments)}};var dc=Date.prototype,mc="%a %b %e %X %Y",vc="%m/%d/%Y",yc="%H:%M:%S",Mc=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],xc=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],bc=["January","February","March","April","May","June","July","August","September","October","November","December"],_c=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];ua.time.year=Eu(function(n){return n=ua.time.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ua.time.years=ua.time.year.range,ua.time.years.utc=ua.time.year.utc.range,ua.time.day=Eu(function(n){var t=new gc(1970,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}),ua.time.d
ays=ua.time.day.range,ua.time.days.utc=ua.time.day.utc.range,ua.time.dayOfYear=function(n){var t=ua.time.year(n);return Math.floor((n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5)},pc.forEach(function(n,t){n=n.toLowerCase(),t=7-t;var e=ua.time[n]=Eu(function(n){return(n=ua.time.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+Math.floor(t)*7)},function(n){var e=ua.time.year(n).getDay();return Math.floor((ua.time.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ua.time[n+"s"]=e.range,ua.time[n+"s"].utc=e.utc.range,ua.time[n+"OfYear"]=function(n){var e=ua.time.year(n).getDay();return Math.floor((ua.time.dayOfYear(n)+(e+t)%7)/7)}}),ua.time.week=ua.time.sunday,ua.time.weeks=ua.time.sunday.range,ua.time.weeks.utc=ua.time.sunday.utc.range,ua.time.weekOfYear=ua.time.sundayOfYear,ua.time.format=function(n){function t(t){for(var r,i,u,a=[],o=-1,c=0;++o<e;)n.charCodeAt(o)===37&&(a.push(n.substring(c,o)),(i=qc[r=n.charAt(++o)])!=null&&(r=n.charAt(++o
)),(u=Tc[r])&&(r=u(t,null==i?"e"===r?" ":"0":i)),a.push(r),c=o+1);return a.push(n.substring(c,o)),a.join("")}var e=n.length;return t.parse=function(t){var e={y:1900,m:0,d:1,H:0,M:0,S:0,L:0},r=Au(e,n,t,0);if(r!=t.length)return null;"p"in e&&(e.H=e.H%12+e.p*12);var i=new gc;return i.setFullYear(e.y,e.m,e.d),i.setHours(e.H,e.M,e.S,e.L),i},t.toString=function(){return n},t};var wc=Nu(Mc),Sc=Nu(xc),Ec=Nu(bc),kc=qu(bc),Ac=Nu(_c),Nc=qu(_c),qc={"-":"",_:" ",0:"0"},Tc={a:function(n){return xc[n.getDay()]},A:function(n){return Mc[n.getDay()]},b:function(n){return _c[n.getMonth()]},B:function(n){return bc[n.getMonth()]},c:ua.time.format(mc),d:function(n,t){return Tu(n.getDate(),t,2)},e:function(n,t){return Tu(n.getDate(),t,2)},H:function(n,t){return Tu(n.getHours(),t,2)},I:function(n,t){return Tu(n.getHours()%12||12,t,2)},j:function(n,t){return Tu(1+ua.time.dayOfYear(n),t,3)},L:function(n,t){return Tu(n.getMilliseconds(),t,3)},m:function(n,t){return Tu(n.getMonth()+1,t,2)},M:function(n
,t){return Tu(n.getMinutes(),t,2)},p:function(n){return n.getHours()>=12?"PM":"AM"},S:function(n,t){return Tu(n.getSeconds(),t,2)},U:function(n,t){return Tu(ua.time.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Tu(ua.time.mondayOfYear(n),t,2)},x:ua.time.format(vc),X:ua.time.format(yc),y:function(n,t){return Tu(n.getFullYear()%100,t,2)},Y:function(n,t){return Tu(n.getFullYear()%1e4,t,4)},Z:$u,"%":function(){return"%"}},Cc={a:Cu,A:zu,b:Du,B:ju,c:Lu,d:Uu,e:Uu,H:Iu,I:Iu,L:Zu,m:Yu,M:Vu,p:Bu,S:Xu,x:Fu,X:Hu,y:Ru,Y:Pu},zc=/^\s*\d+/,Dc=ua.map({am:0,pm:1});ua.time.format.utc=function(n){function t(n){try{gc=Su;var t=new gc;return t._=n,e(t)}finally{gc=Date}}var e=ua.time.format(n);return t.parse=function(n){try{gc=Su;var t=e.parse(n);return t&&t._}finally{gc=Date}},t.toString=e.toString,t};var jc=ua.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");ua.time.format.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Ju:jc,Ju.parse=function(n){var
t=new Date(n);return isNaN(t)?null:t},Ju.toString=jc.toString,ua.time.second=Eu(function(n){return new gc(Math.floor(n/1e3)*1e3)},function(n,t){n.setTime(n.getTime()+Math.floor(t)*1e3)},function(n){return n.getSeconds()}),ua.time.seconds=ua.time.second.range,ua.time.seconds.utc=ua.time.second.utc.range,ua.time.minute=Eu(function(n){return new gc(Math.floor(n/6e4)*6e4)},function(n,t){n.setTime(n.getTime()+Math.floor(t)*6e4)},function(n){return n.getMinutes()}),ua.time.minutes=ua.time.minute.range,ua.time.minutes.utc=ua.time.minute.utc.range,ua.time.hour=Eu(function(n){var t=n.getTimezoneOffset()/60;return new gc((Math.floor(n/36e5-t)+t)*36e5)},function(n,t){n.setTime(n.getTime()+Math.floor(t)*36e5)},function(n){return n.getHours()}),ua.time.hours=ua.time.hour.range,ua.time.hours.utc=ua.time.hour.utc.range,ua.time.month=Eu(function(n){return n=ua.time.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ua.time.months=ua.time.mont
h.range,ua.time.months.utc=ua.time.month.utc.range;var Lc=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Fc=[[ua.time.second,1],[ua.time.second,5],[ua.time.second,15],[ua.time.second,30],[ua.time.minute,1],[ua.time.minute,5],[ua.time.minute,15],[ua.time.minute,30],[ua.time.hour,1],[ua.time.hour,3],[ua.time.hour,6],[ua.time.hour,12],[ua.time.day,1],[ua.time.day,2],[ua.time.week,1],[ua.time.month,1],[ua.time.month,3],[ua.time.year,1]],Hc=[[ua.time.format("%Y"),Ht],[ua.time.format("%B"),function(n){return n.getMonth()}],[ua.time.format("%b %d"),function(n){return n.getDate()!=1}],[ua.time.format("%a %d"),function(n){return n.getDay()&&n.getDate()!=1}],[ua.time.format("%I %p"),function(n){return n.getHours()}],[ua.time.format("%I:%M"),function(n){return n.getMinutes()}],[ua.time.format(":%S"),function(n){return n.getSeconds()}],[ua.time.format(".%L"),function(n){return n.getMilliseconds()}]],Pc=ua.scale.linear(),Rc=Wu(Hc);Fc.
year=function(n,t){return Pc.domain(n.map(na)).ticks(t).map(Qu)},ua.time.scale=function(){return Gu(ua.scale.linear(),Fc,Rc)};var Oc=Fc.map(function(n){return[n[0].utc,n[1]]}),Yc=[[ua.time.format.utc("%Y"),Ht],[ua.time.format.utc("%B"),function(n){return n.getUTCMonth()}],[ua.time.format.utc("%b %d"),function(n){return n.getUTCDate()!=1}],[ua.time.format.utc("%a %d"),function(n){return n.getUTCDay()&&n.getUTCDate()!=1}],[ua.time.format.utc("%I %p"),function(n){return n.getUTCHours()}],[ua.time.format.utc("%I:%M"),function(n){return n.getUTCMinutes()}],[ua.time.format.utc(":%S"),function(n){return n.getUTCSeconds()}],[ua.time.format.utc(".%L"),function(n){return n.getUTCMilliseconds()}]],Uc=Wu(Yc);return Oc.year=function(n,t){return Pc.domain(n.map(ea)).ticks(t).map(ta)},ua.time.scale.utc=function(){return Gu(ua.scale.linear(),Oc,Uc)},ua.text=st(function(n){return n.responseText}),ua.json=function(n,t){return ht(n,"application/json",ra,t)},ua.html=function(n,t){return ht(n,"t
ext/html",ia,t)},ua.xml=st(function(n){return n.responseXML}),ua}();
\ No newline at end of file
commit 40067107470e7402e599ed2e81f03ae8a1d21fac
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 09:55:15 2013 -0700
Fix chart size on detail summary graphs as new chart is a bit larger with new date nav controls.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
index b876c74..31b1667 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
@@ -634,7 +634,7 @@ public abstract class AbstractActivityView extends EnhancedVLayout implements Re
setIsModal(true);
setShowModalMask(true);
setWidth(950);
- setHeight(370);
+ setHeight(390);
setShowResizer(true);
setCanDragResize(true);
centerInPage();
commit 971dc50de43a893aa7424a3a17dbfb5d53f2d721
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 09:53:32 2013 -0700
d3 Brush handle modification to represent a physical handle.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 364e1d8..21e4774 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -540,9 +540,23 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
}
function createBrush(){
-
- // here is all the brush related stuff
- var brush = $wnd.d3.svg.brush()
+ // slightly modified but originally from crossfilter (http://square.github.com/crossfilter/)
+ var resizePath = function (d) {
+ var e1 = +(d === "e"),
+ e = e1 ? 1 : 0 ,
+ x = e ? 1 : -1,
+ y = height / 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);
+ },
+ brush = $wnd.d3.svg.brush()
.x(timeScale)
.extent($wnd.d3.extent(chartData, function (d) {
return d.x;
@@ -555,13 +569,10 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
.call(brush);
brushg.selectAll(".resize").append("path")
- .attr("transform", "translate(0," + height / 2 + ")")
- .attr("opacity", ".3")
- .attr("fill", "#49F9FE")
.attr("d", resizePath);
brushg.selectAll("rect")
- .attr("height", 135);
+ .attr("height", height);
brushstart();
brushmove();
@@ -572,7 +583,6 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
function brushmove() {
var s = brush.extent();
- //circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
}
@@ -588,21 +598,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
$wnd.jQuery('#dateRange').text(formattedDateRange);
}
- // Taken from crossfilter (http://square.github.com/crossfilter/)
- function resizePath(d) {
- var e = +(d == 'e'),
- x = e ? 1 : -1,
- y = height / 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 formatHovers(chartContext, d) {
commit aa0c43d4eddfaee9c9db7570f202e9fbd98d47d0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 29 14:23:29 2013 -0700
Bug fixes on d3 graph brushes.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index 0e2db67..6a3c4a5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -27,7 +27,6 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.DateSliderGraphType;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
@@ -42,7 +41,6 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
private MeasurementUserPreferences measurementUserPreferences;
private AbstractD3GraphListView d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
- //private DateSliderGraphType dateSliderGraphType;
private Long startDateTime;
private Long endDateTime;
@@ -59,7 +57,6 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
List<Long> beginEndTimes = prefs.getBeginEndTimes();
startDateTime = beginEndTimes.get(0);
endDateTime = beginEndTimes.get(1);
- // this.dateSliderGraphType = new DateSliderGraphType(beginEndTimes.get(0), beginEndTimes.get(1));
}
/**
@@ -74,8 +71,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
// append the bootstrap buttongroup since smartGWT doesn't have one
- StringBuilder divAndSvgDefs = new StringBuilder();
- divAndSvgDefs.append("<div id=\"graphDateTimeRangeEditor\">" +
+ StringBuilder buttonBarDiv = new StringBuilder();
+ buttonBarDiv.append("<div id=\"graphDateTimeRangeEditor\">" +
"<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
" <div class=\"accordion-group\">" +
" <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
@@ -97,10 +94,10 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
" </div>" +
" </div>" +
" </div>");
- HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
- graph.setWidth100();
- graph.setHeight(50);
- addMember(graph);
+ HTMLFlow buttonBarDivFlow = new HTMLFlow(buttonBarDiv.toString());
+ buttonBarDivFlow.setWidth100();
+ buttonBarDivFlow.setHeight(50);
+ addMember(buttonBarDivFlow);
new Timer(){
@Override
public void run() {
@@ -203,9 +200,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
});
- // initially populate
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- //$wnd.jQuery("#radioHour").click();
+ // initially populate with default click
+ $wnd.jQuery("#radio12h").click();
}-*/;
@@ -238,7 +234,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
public void parentResized() {
super.parentResized();
removeMembers(getMembers());
- //createDateSliderMarker();
+ createDateSliderMarker();
//drawJsniChart();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index a4e0332..364e1d8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -558,7 +558,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
.attr("transform", "translate(0," + height / 2 + ")")
.attr("opacity", ".3")
.attr("fill", "#49F9FE")
- .attr("d", resizePath());
+ .attr("d", resizePath);
brushg.selectAll("rect")
.attr("height", 135);
@@ -585,7 +585,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
function updateDateRangeDisplay(startDate, endDate ) {
//@todo: i18n the date format
var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- $wnd.jQuery('#dateRange').val(formattedDateRange);
+ $wnd.jQuery('#dateRange').text(formattedDateRange);
}
// Taken from crossfilter (http://square.github.com/crossfilter/)
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
index 95f02a1..2dbd79b 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
@@ -46,7 +46,7 @@
/* Brush related css rules */
.brush rect.extent {
fill: #0757ff;
- fill-opacity: .09;
+ fill-opacity: .15;
shape-rendering: crispEdges;
}
commit 95829908b86a7481304ab0a1d590a00af9631522
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 29 13:41:38 2013 -0700
Graph d3 brush slider is now on Graph and date button bar resembles that of logstash (logstalgia) style operation.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index 6ab312e..0e2db67 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -80,7 +80,6 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
" <div class=\"accordion-group\">" +
" <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
" <div class=\"accordion-inner\">" +
- "<div>"+
" <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
" <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
" <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
@@ -90,17 +89,17 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
" <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
" <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
" <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
+ " <button id=\"radioCustom\" type=\"button\" class=\"btn btn-mini\">Custom...</button>" +
" </span>" +
- " <input id=\"dateRange\" style=\"margin-left:30px;margin-top:5px;width:280px;\" type=\"text\" readonly=\"readonly\" />" +
- "</div>"+
- " <button id=\"buttonCustom\" type=\"button\" class=\"btn btn-mini btn-link\">Custom...</button>" +
+ " <span id=\"dateRange\" class=\"\" style=\"margin-left:30px;margin-top:7px;width:270px;\" /></span>" +
+ " <button id=\"buttonReset\" type=\"button\" style=\"float:right;margin-right:10px;\" class=\"btn btn-mini\">Reset Manual Zoom</button>" +
" </div>" +
" </div>" +
" </div>" +
" </div>");
HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
graph.setWidth100();
- graph.setHeight(65);
+ graph.setHeight(50);
addMember(graph);
new Timer(){
@Override
@@ -109,7 +108,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
//drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
attachGraphDateRangeEditorButtonGroupHandlers();
}
- }.schedule(400);
+ }.schedule(200);
}
public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
@@ -117,8 +116,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
var global = this;
function updateDateDisplay(startDate, endDate ) {
- var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- $wnd.jQuery('#dateRange').val(formattedDateRange);
+ var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ $wnd.jQuery('#dateRange').text(formattedDateRange);
}
function saveDateRange(startDate, endDate){
@@ -130,57 +129,79 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
- $wnd.jQuery("#radioMin").bind('click', function (event) {
- console.log("Minute selected");
- graphDateContext.startDate = $wnd.moment().startOf('hour');
+ $wnd.jQuery("#radio1h").bind('click', function (event) {
+ console.log("1h selected");
+ graphDateContext.startDate = $wnd.moment().subtract(1, 'hours');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
//this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
- $wnd.jQuery("#radioHour").bind('click', function (event) {
- console.log("Hour selected");
- graphDateContext.startDate = $wnd.moment().startOf('day');
+ $wnd.jQuery("#radio6h").bind('click', function (event) {
+ console.log(" 6h selected");
+ graphDateContext.startDate = $wnd.moment().subtract(6, 'hours');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
//this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
- $wnd.jQuery("#radioDay").bind('click', function (event) {
- console.log("Day selected");
- graphDateContext.startDate = $wnd.moment().startOf('week');
+ $wnd.jQuery("#radio12h").bind('click', function (event) {
+ console.log("12h selected");
+ graphDateContext.startDate = $wnd.moment().subtract(12, 'hours');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
//this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
- $wnd.jQuery("#radioMonth").bind('click', function (event) {
- console.log("month selected");
- graphDateContext.startDate = $wnd.moment().startOf('month');
+ $wnd.jQuery("#radio1d").bind('click', function (event) {
+ console.log("1d selected");
+ graphDateContext.startDate = $wnd.moment().subtract(24, 'hours');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
//this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
- $wnd.jQuery("#radioYear").bind('click', function (event) {
- console.log("year selected");
- graphDateContext.startDate = $wnd.moment().startOf('year');
+ $wnd.jQuery("#radio5d").bind('click', function (event) {
+ console.log("5d selected");
+ graphDateContext.startDate = $wnd.moment().subtract(5, 'days');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
//this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
- $wnd.jQuery("#expandCollapseButton").bind('click', function (event) {
- console.log("expand/collapse selected");
- //$wnd.jQuery("#timeRange").toggle();
- var buttonBarVisibility = $wnd.jQuery("#timeRangeButtons").attr("visibility");
- if(buttonBarVisibility === 'none'){
- $wnd.jQuery("#timeRangeButtons").attr("visibility","visible");
- }else {
- $wnd.jQuery("#timeRangeButtons").attr("visibility","none");
- }
-
+ $wnd.jQuery("#radio1m").bind('click', function (event) {
+ console.log("1m selected");
+ graphDateContext.startDate = $wnd.moment().subtract(1, 'months');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radio3m").bind('click', function (event) {
+ console.log("3m selected");
+ graphDateContext.startDate = $wnd.moment().subtract(3, 'months');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
+ $wnd.jQuery("#radio1y").bind('click', function (event) {
+ console.log("1y selected");
+ graphDateContext.startDate = $wnd.moment().subtract(1, 'years');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioCustom").bind('click', function (event) {
+ console.log("Custom Range selected");
+ graphDateContext.startDate = $wnd.moment().subtract(2, 'years');
+ graphDateContext.endDate = $wnd.moment();
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ });
+
// initially populate
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
index bbba479..10a2635 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
@@ -123,7 +123,7 @@ public class DateSliderGraphType {
}
function updateDateRangeDisplay(startDate, endDate ) {
- var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
$wnd.jQuery('#dateRange').val(formattedDateRange);
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index aca67b9..a4e0332 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -97,16 +97,6 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
chart,
svg;
- function isIEBrowserGreaterThanOrEqualTo(targetIEVersion){
- var myUserAgent = $wnd.navigator.userAgent;
- if (/MSIE (\d+\.\d+);/.test(myUserAgent)){ //test for MSIE x.x;
- var ieVersion=new Number(RegExp.$1); // capture x.x portion and store as a number
- if (ieVersion>=targetIEVersion){
- return true;
- }
- }
- return false;
- }
function getChartWidth() {
return $wnd.jQuery("#" + chartContext.chartHandle).width();
@@ -490,7 +480,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
return yScale(d.y);
}
else {
- return yScale(0);
+ return NaN;
}
});
@@ -549,6 +539,72 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
}
+ function createBrush(){
+
+ // here is all the brush related stuff
+ var brush = $wnd.d3.svg.brush()
+ .x(timeScale)
+ .extent($wnd.d3.extent(chartData, function (d) {
+ return d.x;
+ }))
+ .on("brushstart", brushstart)
+ .on("brush", brushmove)
+ .on("brushend", brushend),
+ brushg = svg.append("g")
+ .attr("class", "brush")
+ .call(brush);
+
+ brushg.selectAll(".resize").append("path")
+ .attr("transform", "translate(0," + height / 2 + ")")
+ .attr("opacity", ".3")
+ .attr("fill", "#49F9FE")
+ .attr("d", resizePath());
+
+ brushg.selectAll("rect")
+ .attr("height", 135);
+
+ brushstart();
+ brushmove();
+
+ function brushstart() {
+ svg.classed("selecting", true);
+ }
+
+ function brushmove() {
+ var s = brush.extent();
+ //circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ }
+
+ function brushend() {
+ var s = brush.extent();
+ svg.classed("selecting", !$wnd.d3.event.target.empty());
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ }
+
+ function updateDateRangeDisplay(startDate, endDate ) {
+ //@todo: i18n the date format
+ var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ $wnd.jQuery('#dateRange').val(formattedDateRange);
+ }
+
+ // Taken from crossfilter (http://square.github.com/crossfilter/)
+ function resizePath(d) {
+ var e = +(d == 'e'),
+ x = e ? 1 : -1,
+ y = height / 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 formatHovers(chartContext, d) {
var hoverString,
xValue = (d.x == undefined) ? 0 : +d.x,
@@ -624,6 +680,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
createOOBLines();
}
createHovers(chartContext);
+ createBrush();
}
}
}; // end public closure
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
index 1b83532..95f02a1 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
@@ -44,28 +44,19 @@
stroke: #50505a;
}
/* Brush related css rules */
-.brush .extent {
- stroke: #fff;
- fill-opacity: .125;
+.brush rect.extent {
+ fill: #0757ff;
+ fill-opacity: .09;
shape-rendering: crispEdges;
}
-.selecting circle {
- fill-opacity: .2;
-}
-
-.selecting circle.selected {
- stroke: #f00;
-}
-.resize path {
+.brush .resize path {
fill: #666;
fill-opacity: .8;
stroke: #000;
stroke-width: 1.5px;
}
-
-
.minLabel, .avgLabel, .highLabel {
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
commit 894f0bee57579b1b370868d39ca36b743374e244
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 24 14:54:40 2013 -0700
Pull d3 Date slider and place into actual graph instead. Decision was made in UXD meeting today.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index e7f17e3..6ab312e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -42,7 +42,9 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
private MeasurementUserPreferences measurementUserPreferences;
private AbstractD3GraphListView d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
- private DateSliderGraphType dateSliderGraphType;
+ //private DateSliderGraphType dateSliderGraphType;
+ private Long startDateTime;
+ private Long endDateTime;
public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
@@ -55,7 +57,9 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
// initialize with saved begin/end times
List<Long> beginEndTimes = prefs.getBeginEndTimes();
- this.dateSliderGraphType = new DateSliderGraphType(beginEndTimes.get(0), beginEndTimes.get(1));
+ startDateTime = beginEndTimes.get(0);
+ endDateTime = beginEndTimes.get(1);
+ // this.dateSliderGraphType = new DateSliderGraphType(beginEndTimes.get(0), beginEndTimes.get(1));
}
/**
@@ -72,24 +76,26 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
// append the bootstrap buttongroup since smartGWT doesn't have one
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs.append("<div id=\"graphDateTimeRangeEditor\">" +
- "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:895px;\">" +
+ "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:758px;\">" +
" <div class=\"accordion-group\">" +
" <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
" <div class=\"accordion-inner\">" +
+ "<div>"+
" <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
- " <button id=\"radioMin\" type=\"button\" class=\"btn btn-mini\" >"+MSG.chart_slider_button_bar_minute()+"</button>" +
- " <button id=\"radioHour\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_hour()+"</button>" +
- " <button id=\"radioDay\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_day()+"</button>" +
- " <button id=\"radioMonth\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_month()+"</button>" +
- " <button id=\"radioYear\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_year()+"</button>" +
+ " <button id=\"radio1h\" type=\"button\" class=\"btn btn-mini\" >1h</button>" +
+ " <button id=\"radio6h\" type=\"button\" class=\"btn btn-mini\">6h</button>" +
+ " <button id=\"radio12h\" type=\"button\" class=\"btn btn-mini\">12h</button>" +
+ " <button id=\"radio1d\" type=\"button\" class=\"btn btn-mini\">1d</button>" +
+ " <button id=\"radio5d\" type=\"button\" class=\"btn btn-mini\">5d</button>" +
+ " <button id=\"radio1m\" type=\"button\" class=\"btn btn-mini\">1m</button>" +
+ " <button id=\"radio3m\" type=\"button\" class=\"btn btn-mini\">3m</button>" +
+ " <button id=\"radio1y\" type=\"button\" class=\"btn btn-mini\">1y</button>" +
" </span>" +
" <input id=\"dateRange\" style=\"margin-left:30px;margin-top:5px;width:280px;\" type=\"text\" readonly=\"readonly\" />" +
- " <button id=\"expandCollapseButton\" style=\"float:right;\" type=\"button\" class=\"btn btn-mini\">+/-</button>" +
+ "</div>"+
+ " <button id=\"buttonCustom\" type=\"button\" class=\"btn btn-mini btn-link\">Custom...</button>" +
" </div>" +
" </div>" +
- " <div id=\"dateSlider\">" +
- " <svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\"></svg></div>"+
- " </div>" +
" </div>" +
" </div>");
HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
@@ -99,8 +105,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
new Timer(){
@Override
public void run() {
- changeDateRange(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
- dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
+ changeDateRange(getStartTime(), getEndTime());
+ //drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
attachGraphDateRangeEditorButtonGroupHandlers();
}
}.schedule(400);
@@ -130,7 +136,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioHour").bind('click', function (event) {
console.log("Hour selected");
@@ -138,7 +144,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioDay").bind('click', function (event) {
console.log("Day selected");
@@ -146,7 +152,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioMonth").bind('click', function (event) {
console.log("month selected");
@@ -154,7 +160,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioYear").bind('click', function (event) {
console.log("year selected");
@@ -162,7 +168,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
- this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
+ //this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#expandCollapseButton").bind('click', function (event) {
console.log("expand/collapse selected");
@@ -188,13 +194,13 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
}-*/;
- public void drawJsniDateSlider(){
- dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
- }
-
- public void drawJsniDateSlider(Long startTime, Long endTime){
- dateSliderGraphType.drawJsniChart(startTime, endTime);
- }
+// public void drawJsniDateSlider(){
+// dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
+// }
+//
+// public void drawJsniDateSlider(Long startTime, Long endTime){
+// dateSliderGraphType.drawJsniChart(startTime, endTime);
+// }
public void redrawGraphs(){
d3GraphListView.redrawGraphs();
@@ -231,8 +237,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
*/
public void changeDateRange(double startTime, double endTime){
- this.dateSliderGraphType.setStartDateTime((long)startTime);
- this.dateSliderGraphType.setEndDateTime((long)endTime);
+ startDateTime = (long)startTime;
+ endDateTime = (long)endTime;
//@todo: uncomment when ready
// final boolean advanced = true;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
index df69e36..015a528 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
@@ -38,6 +38,7 @@ import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
*
* @author Mike Thompson
*/
+@Deprecated
public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGraphType {
private static Messages MSG = CoreGUI.getMessages();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
index e543f86..bbba479 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
@@ -26,6 +26,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
*
* @author Mike Thompson
*/
+@Deprecated
public class DateSliderGraphType {
private Long startDateTime;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 1345c4c..451d9a3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -45,7 +45,7 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
@@ -132,7 +132,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
graphDateTimeRangeEditor.createDateSliderMarker();
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphWithSliderType>(new AvailabilityOverUnderGraphWithSliderType(resource.getId()));
+ availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resource.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
@@ -154,7 +154,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
public void redrawGraphs() {
this.onDraw();
availabilityGraph.drawJsniChart();
- graphDateTimeRangeEditor.drawJsniDateSlider();
+ //graphDateTimeRangeEditor.drawJsniDateSlider();
}
@Override
commit fdc5aff4f8286b2f7598ea316eaef0fdebc0f093
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 24 10:50:03 2013 -0700
Replace brushable availability graph with pure date slider - DateSliderGraphType
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index d64f3f6..e7f17e3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -130,6 +130,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioHour").bind('click', function (event) {
console.log("Hour selected");
@@ -137,6 +138,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioDay").bind('click', function (event) {
console.log("Day selected");
@@ -144,6 +146,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioMonth").bind('click', function (event) {
console.log("month selected");
@@ -151,6 +154,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioYear").bind('click', function (event) {
console.log("year selected");
@@ -158,6 +162,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
+ this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::drawJsniDateSlider(Ljava/lang/Long;Ljava/lang/Long;)(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#expandCollapseButton").bind('click', function (event) {
console.log("expand/collapse selected");
@@ -187,6 +192,10 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
}
+ public void drawJsniDateSlider(Long startTime, Long endTime){
+ dateSliderGraphType.drawJsniChart(startTime, endTime);
+ }
+
public void redrawGraphs(){
d3GraphListView.redrawGraphs();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/JQueryDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/JQueryDateTimeRangeEditor.java
deleted file mode 100644
index 5266e7f..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/JQueryDateTimeRangeEditor.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
-
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-
-/**
- * An implementation using JQuery UI components because smartGWT doesn't contain buttonsets or dual range sliders.
- *
- * @author Mike Thompson
- */
-@Deprecated
-public class JQueryDateTimeRangeEditor {
- private static Messages MSG = CoreGUI.getMessages();
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart() /*-{
- console.log("Draw GraphDateTimeRangeEditor");
-
- var global = this,
- // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
- // NOTE: rhq.js has the javascript object constructors in it.
- availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
- );
-
-
- var availabilityGraph = function () {
- "use strict";
- // privates
-
- var margin = {top: 5, right: 5, bottom: 5, left: 40},
- barOffset = 10,
- width = 750 - margin.left - margin.right + barOffset,
- height = 40 - margin.top - margin.bottom,
- svg;
-
-
- function drawBars(availChartContext) {
- var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
- return +d.availStart;
- }),
- xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
- return +d.availEnd;
- }),
-
- timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain([xAxisMin, xAxisMax]),
-
- yScale = $wnd.d3.scale.linear()
- .clamp(true)
- .rangeRound([height, 0])
- .domain([0, 4]),
-
- xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(8)
- .tickSize(13, 0, 0)
- .orient("bottom"),
-
- calcBarY = function (d) {
- var ABOVE = -10,
- BELOW = 0,
- STRADDLE = -5,
- offset;
-
- if (d.availType === 'DOWN') {
- offset = BELOW;
- }
- else if (d.availType === 'DISABLED') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UNKNOWN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UP') {
- offset = ABOVE;
- }
- else if (d.availType === 'WARN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'EMPTY') {
- offset = STRADDLE;
- }
- return yScale(0) + offset;
-
- },
-
- calcBarFill = function (d) {
- if (d.availType === 'DOWN') {
- return "#FF1919"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "url(#diagonalHatchFill)"; // grey diagonal hatches
- }
- else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
- }
- else if (d.availType === 'UP') {
- return "#198C19"; // green
- }
- else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.log("AvailabilityType not valid.");
- return "#000"; //black
- }
- },
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-
- svg.selectAll("rect.availBars")
- .data(availChartContext.data)
- .enter().append("rect")
- .attr("class", "availBars")
- .attr("x", function (d) {
- return timeScale(+d.availStart);
- })
- .attr("y", function (d) {
- return calcBarY(d);
- })
- .attr("height", function (d) {
- return 10;
- })
- .attr("width", function (d) {
- return timeScale(+d.availEnd) - timeScale(+d.availStart);
- })
- .attr("opacity", ".9")
- .attr("fill", function (d) {
- return calcBarFill(d);
- });
-
- // create x-axis
- svg.append("g")
- .attr("class", "x axis")
- .attr("fill", "#50505a")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
-
- svg.append("text")
- .attr("class", "availabilityLabel")
- .attr("x", -40)
- .attr("y", 10)
- .style("font-size", "12px")
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-weight", "bold")
- .attr("fill", "#003168")
- .text(availChartContext.chartTitle);
-
- svg.append("text")
- .attr("class", "upLabel")
- .attr("x", -5)
- .attr("y", 28)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartUpLabel);
-
- svg.append("text")
- .attr("class", "downLabel")
- .attr("x", -5)
- .attr("y", 39)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartDownLabel);
-
- }
-
- function createHovers() {
- $wnd.jQuery('svg rect.availBars').tipsy({
- gravity: 's',
- html: true,
- trigger: 'hover',
- title: function () {
- var d = this.__data__;
- return formatHovers(d);
- },
- show: function (e, el) {
- el.css({ 'z-index': '990000'})
- }
- });
- }
-
- function formatHovers(d) {
- var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
- dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart);
-
- return '<div class="chartHoverEnclosingDiv">' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
- '</div>';
-
- }
-
- return {
- // Public API
- draw: function (availChartContext) {
- "use strict";
- console.log("AvailabilityChart");
- drawBars(availChartContext);
- createHovers();
- }
- }; // end public closure
-
-
- }();
-
- if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
- availabilityGraph.draw(availChartContext);
- }
-
- }-*/;
-
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
index 58920ff..e543f86 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
@@ -100,7 +100,7 @@ public class DateSliderGraphType {
.attr("d", resizePath);
brushg.selectAll("rect")
- .attr("height", 20);
+ .attr("height", 29);
brushstart();
brushmove();
commit 8aa31b54ef3b4db63de41b88cfaad943f670c8d7
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 23 12:38:25 2013 -0700
Replace brushable availability graph with pure date slider - DateSliderGraphType
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index b1e2ade..d64f3f6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -18,6 +18,8 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+import java.util.List;
+
import com.google.gwt.user.client.Timer;
import com.smartgwt.client.widgets.HTMLFlow;
@@ -25,9 +27,9 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.DateSliderGraphType;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
/**
@@ -37,16 +39,23 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPre
*/
public class GraphDateTimeRangeEditor extends EnhancedVLayout {
- private JQueryDateTimeRangeEditor graphDateTimeRangeEditor;
private MeasurementUserPreferences measurementUserPreferences;
private AbstractD3GraphListView d3GraphListView;
private static final Messages MSG = CoreGUI.getMessages();
+ private DateSliderGraphType dateSliderGraphType;
- public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,AbstractD3GraphListView d3GraphListView) {
+ public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,
+ AbstractD3GraphListView d3GraphListView) {
this.measurementUserPreferences = measurementUserPrefs;
this.d3GraphListView = d3GraphListView;
- this.graphDateTimeRangeEditor = new JQueryDateTimeRangeEditor();
+
+
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+
+ // initialize with saved begin/end times
+ List<Long> beginEndTimes = prefs.getBeginEndTimes();
+ this.dateSliderGraphType = new DateSliderGraphType(beginEndTimes.get(0), beginEndTimes.get(1));
}
/**
@@ -57,32 +66,32 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
* NOTE: auxiliary javascript functions in rhq.js
*
*/
- public void createGraphMarker() {
+ public void createDateSliderMarker() {
Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
// append the bootstrap buttongroup since smartGWT doesn't have one
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs.append("<div id=\"graphDateTimeRangeEditor\">" +
- "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:895px;\">\n" +
- " <div class=\"accordion-group\">\n" +
- " \n" +
- " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">\n" +
- " <div class=\"accordion-inner\">\n" +
- " <span id=\"timeRange\" class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
- " <button id=\"radioMin\" type=\"button\" class=\"btn btn-mini\" >"+MSG.chart_slider_button_bar_minute()+"</button>\n" +
- " <button id=\"radioHour\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_hour()+"</button>\n" +
- " <button id=\"radioDay\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_day()+"</button>\n" +
- " <button id=\"radioMonth\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_month()+"</button>\n" +
- " <button id=\"radioYear\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_year()+"</button>\n" +
- " </span>\n" +
- " <input id=\"dateRange\" style=\"margin-left:30px;margin-top:5px;width:280px;\" type=\"text\" readonly=\"readonly\" />\n" +
- " <button id=\"expandCollapseButton\" style=\"margin-left:202px;\" type=\"button\" class=\"btn btn-mini\">+/-</button>\n" +
- " </div>\n" +
- " </div>\n" +
- " </div>\n" +
- " </div>\n"+
- "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
- divAndSvgDefs.append("</svg></div>");
+ "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:895px;\">" +
+ " <div class=\"accordion-group\">" +
+ " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">" +
+ " <div class=\"accordion-inner\">" +
+ " <span id=\"timeRangeButtons\" class=\"btn-group\" data-toggle=\"buttons-radio\">" +
+ " <button id=\"radioMin\" type=\"button\" class=\"btn btn-mini\" >"+MSG.chart_slider_button_bar_minute()+"</button>" +
+ " <button id=\"radioHour\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_hour()+"</button>" +
+ " <button id=\"radioDay\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_day()+"</button>" +
+ " <button id=\"radioMonth\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_month()+"</button>" +
+ " <button id=\"radioYear\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_year()+"</button>" +
+ " </span>" +
+ " <input id=\"dateRange\" style=\"margin-left:30px;margin-top:5px;width:280px;\" type=\"text\" readonly=\"readonly\" />" +
+ " <button id=\"expandCollapseButton\" style=\"float:right;\" type=\"button\" class=\"btn btn-mini\">+/-</button>" +
+ " </div>" +
+ " </div>" +
+ " <div id=\"dateSlider\">" +
+ " <svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\"></svg></div>"+
+ " </div>" +
+ " </div>" +
+ " </div>");
HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
graph.setWidth100();
graph.setHeight(65);
@@ -90,6 +99,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
new Timer(){
@Override
public void run() {
+ changeDateRange(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
+ dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
attachGraphDateRangeEditorButtonGroupHandlers();
}
}.schedule(400);
@@ -100,14 +111,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
var global = this;
function updateDateDisplay(startDate, endDate ) {
- var formattedDateRange;
-
- if (isSameDay(startDate, endDate) && isSameMonth(startDate, endDate) && isSameYear(startDate, endDate)) {
- // no need to display date only time
- formattedDateRange = startDate.format('ddd') + ': ' + startDate.format('h:mm a') + ' - ' + endDate.format('h:mm a');
- } else {
- formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- }
+ var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
$wnd.jQuery('#dateRange').val(formattedDateRange);
}
@@ -115,17 +119,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
var start = startDate | 0, end = endDate | 0;
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::changeDateRange(DD)(start,end);
//@todo: fixme
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
- }
-
- function isSameDay(startDate, endDate) {
- return (startDate.date() === endDate.date());
- }
- function isSameMonth(startDate, endDate) {
- return (startDate.month() === endDate.month());
- }
- function isSameYear(startDate, endDate) {
- return (startDate.year() === endDate.year());
+ //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
}
var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
@@ -167,7 +161,13 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
});
$wnd.jQuery("#expandCollapseButton").bind('click', function (event) {
console.log("expand/collapse selected");
- $wnd.jQuery("#timeRange").toggle();
+ //$wnd.jQuery("#timeRange").toggle();
+ var buttonBarVisibility = $wnd.jQuery("#timeRangeButtons").attr("visibility");
+ if(buttonBarVisibility === 'none'){
+ $wnd.jQuery("#timeRangeButtons").attr("visibility","visible");
+ }else {
+ $wnd.jQuery("#timeRangeButtons").attr("visibility","none");
+ }
});
@@ -183,6 +183,10 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
}-*/;
+ public void drawJsniDateSlider(){
+ dateSliderGraphType.drawJsniChart(dateSliderGraphType.getStartTime(), dateSliderGraphType.getEndTime());
+ }
+
public void redrawGraphs(){
d3GraphListView.redrawGraphs();
}
@@ -191,24 +195,15 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
protected void onDraw() {
super.onDraw();
removeMembers(getMembers());
- createGraphMarker();
+ createDateSliderMarker();
}
@Override
public void parentResized() {
super.parentResized();
removeMembers(getMembers());
- createGraphMarker();
- drawJsniChart();
- }
-
-
- /**
- * Delegate the call to rendering the JSNI chart.
- * This way the chart type can be swapped out at any time.
- */
- public void drawJsniChart() {
- graphDateTimeRangeEditor.drawJsniChart();
+ //createDateSliderMarker();
+ //drawJsniChart();
}
@@ -216,23 +211,34 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
return measurementUserPreferences.getMetricRangePreferences().begin;
}
+ public Long getEndTime() {
+ return measurementUserPreferences.getMetricRangePreferences().end;
+ }
+ /**
+ * Whenever we make a change to the date range save it here so it gets propogated to
+ * the correct places.
+ * @param startTime double because JSNI doesnt support long
+ * @param endTime double because JSNI doesnt support long
+ */
public void changeDateRange(double startTime, double endTime){
- final boolean advanced = true;
- AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
- prefs.explicitBeginEnd = advanced;
- prefs.begin = new Long(String.valueOf(startTime));
- prefs.end = new Long(String.valueOf(endTime));
- if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
- CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
- } else {
- measurementUserPreferences.setMetricRangePreferences(prefs);
- }
+ this.dateSliderGraphType.setStartDateTime((long)startTime);
+ this.dateSliderGraphType.setEndDateTime((long)endTime);
+
+ //@todo: uncomment when ready
+// final boolean advanced = true;
+// AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+// prefs.explicitBeginEnd = advanced;
+// prefs.begin = (long) startTime;
+// prefs.end = (long) endTime;
+// if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
+// CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
+// } else {
+// measurementUserPreferences.setMetricRangePreferences(prefs);
+// }
}
- public Long getEndTime() {
- return measurementUserPreferences.getMetricRangePreferences().end;
- }
+
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
new file mode 100644
index 0000000..58920ff
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/DateSliderGraphType.java
@@ -0,0 +1,181 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+
+/**
+ * The simplest of a all graph types as this d3 graph does not even require data, just x axis range so we can plot an
+ * x-axis. No y data values needed. The purpose of this graph is to provide an x axis and a way to drag a
+ * range over it (via d3 brushes).
+ *
+ * @author Mike Thompson
+ */
+public class DateSliderGraphType {
+
+ private Long startDateTime;
+ private Long endDateTime;
+
+ public DateSliderGraphType(Long startTime, Long endTime) {
+ this.startDateTime = startTime;
+ this.endDateTime = endTime;
+ }
+
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart(double start, double end) /*-{
+ console.log("Draw Date Range graph");
+
+ var dateSliderGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ svg;
+
+
+ function drawBars(startTime, endTime) {
+
+ var timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([startTime, endTime]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(8)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ svg = $wnd.d3.select("#dateSlider svg").append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("fill", "#b0b0b0")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+
+ // here is all the brush related stuff
+ var brush = $wnd.d3.svg.brush()
+ .x(timeScale)
+ .extent([startTime, endTime])
+ .on("brushstart", brushstart)
+ .on("brush", brushmove)
+ .on("brushend", brushend);
+
+
+ var brushg = svg.append("g")
+ .attr("class", "brush")
+ .call(brush);
+
+ brushg.selectAll(".resize").append("path")
+ .attr("transform", "translate(0," + height / 2 + ")")
+ .attr("d", resizePath);
+
+ brushg.selectAll("rect")
+ .attr("height", 20);
+
+ brushstart();
+ brushmove();
+
+ function brushstart() {
+ svg.classed("selecting", true);
+ }
+
+ function brushmove() {
+ var s = brush.extent();
+ //circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ }
+
+ function brushend() {
+ var s = brush.extent();
+ svg.classed("selecting", !$wnd.d3.event.target.empty());
+ updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
+ }
+
+ function updateDateRangeDisplay(startDate, endDate ) {
+ var formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ $wnd.jQuery('#dateRange').val(formattedDateRange);
+ }
+
+ // Taken from crossfilter (http://square.github.com/crossfilter/)
+ function resizePath(d) {
+ var e = +(d == 'e'),
+ x = e ? 1 : -1,
+ y = height / 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);
+ }
+ }
+
+ return {
+ // Public API
+ draw: function (startTime, endTime) {
+ "use strict";
+ console.log("DateSliderChart");
+ drawBars(startTime, endTime);
+ }
+ }; // end public closure
+
+
+ }();
+
+ dateSliderGraph.draw(this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.DateSliderGraphType::getStartTime()(), this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.DateSliderGraphType::getEndTime()());
+
+ }-*/;
+
+ public Long getStartTime() {
+ return startDateTime;
+ }
+
+ public void setStartDateTime(Long startDateTime) {
+ this.startDateTime = startDateTime;
+ }
+
+
+ public Long getEndTime() {
+ return endDateTime;
+ }
+
+
+ public void setEndDateTime(Long endDateTime) {
+ this.endDateTime = endDateTime;
+ }
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index d5e77d0..1345c4c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -129,6 +129,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
destroyMembers();
addMember(graphDateTimeRangeEditor);
+ graphDateTimeRangeEditor.createDateSliderMarker();
if (showAvailabilityGraph) {
availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphWithSliderType>(new AvailabilityOverUnderGraphWithSliderType(resource.getId()));
@@ -153,6 +154,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
public void redrawGraphs() {
this.onDraw();
availabilityGraph.drawJsniChart();
+ graphDateTimeRangeEditor.drawJsniDateSlider();
}
@Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
index 92bc69e..3fc0192 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
@@ -97,8 +97,10 @@ public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends En
*/
private static String getSvgDefs() {
return " <defs>"+
- "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" width=\"4\" height=\"4\"> <path d=\"M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2\" /> </pattern>"
- + "</defs>";
+ "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" width=\"4\" height=\"4\">" +
+ "<path d=\"M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2\" />" +
+ "</pattern>" +
+ "</defs>";
}
@Override
commit fffbbfdd54914d2ebf3e73a830c63db22ce4c0ec
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 22 11:41:28 2013 -0700
Look and Feel Tweaks.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index 5535e78..b1e2ade 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -23,9 +23,11 @@ import com.smartgwt.client.widgets.HTMLFlow;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
/**
@@ -61,19 +63,20 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
// append the bootstrap buttongroup since smartGWT doesn't have one
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs.append("<div id=\"graphDateTimeRangeEditor\">" +
- "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:875px;>\n" +
+ "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:895px;\">\n" +
" <div class=\"accordion-group\">\n" +
" \n" +
" <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">\n" +
" <div class=\"accordion-inner\">\n" +
- " <span class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
- " <button id=\"radioMin\" type=\"button\" class=\"btn \" >"+MSG.chart_slider_button_bar_minute()+"</button>\n" +
- " <button id=\"radioHour\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_hour()+"</button>\n" +
- " <button id=\"radioDay\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_day()+"</button>\n" +
- " <button id=\"radioMonth\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_month()+"</button>\n" +
- " <button id=\"radioYear\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_year()+"</button>\n" +
+ " <span id=\"timeRange\" class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
+ " <button id=\"radioMin\" type=\"button\" class=\"btn btn-mini\" >"+MSG.chart_slider_button_bar_minute()+"</button>\n" +
+ " <button id=\"radioHour\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_hour()+"</button>\n" +
+ " <button id=\"radioDay\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_day()+"</button>\n" +
+ " <button id=\"radioMonth\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_month()+"</button>\n" +
+ " <button id=\"radioYear\" type=\"button\" class=\"btn btn-mini\">"+MSG.chart_slider_button_bar_year()+"</button>\n" +
" </span>\n" +
- " <input id=\"dateRange\" style=\"margin-left:30px;width:280px;\" type=\"text\" readonly=\"readonly\" />\n" +
+ " <input id=\"dateRange\" style=\"margin-left:30px;margin-top:5px;width:280px;\" type=\"text\" readonly=\"readonly\" />\n" +
+ " <button id=\"expandCollapseButton\" style=\"margin-left:202px;\" type=\"button\" class=\"btn btn-mini\">+/-</button>\n" +
" </div>\n" +
" </div>\n" +
" </div>\n" +
@@ -130,13 +133,13 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
$wnd.jQuery("#radioMin").bind('click', function (event) {
console.log("Minute selected");
graphDateContext.startDate = $wnd.moment().startOf('hour');
- graphDateContext.endDate = $wnd.moment().unix();
+ graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioHour").bind('click', function (event) {
console.log("Hour selected");
- graphDateContext.startDate = $wnd.moment().startOf('hour');
+ graphDateContext.startDate = $wnd.moment().startOf('day');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
@@ -162,6 +165,11 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
});
+ $wnd.jQuery("#expandCollapseButton").bind('click', function (event) {
+ console.log("expand/collapse selected");
+ $wnd.jQuery("#timeRange").toggle();
+
+ });
// initially populate
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
@@ -170,7 +178,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
}-*/;
public native void refreshGraphs() /*-{
- console.log(" ** Calling GraphDateTimeRangeEditor.refreshGraphs");
+ console.log("Calling GraphDateTimeRangeEditor.refreshGraphs");
this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::redrawGraphs()();
}-*/;
@@ -210,8 +218,16 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
public void changeDateRange(double startTime, double endTime){
- measurementUserPreferences.getMetricRangePreferences().begin = new Long(String.valueOf(startTime));
- measurementUserPreferences.getMetricRangePreferences().end = new Long(String.valueOf(endTime));
+ final boolean advanced = true;
+ AbstractMeasurementRangeEditor.MetricRangePreferences prefs = measurementUserPreferences.getMetricRangePreferences();
+ prefs.explicitBeginEnd = advanced;
+ prefs.begin = new Long(String.valueOf(startTime));
+ prefs.end = new Long(String.valueOf(endTime));
+ if (null != prefs.begin && null != prefs.end && prefs.begin > prefs.end) {
+ CoreGUI.getMessageCenter().notify(new Message(MSG.view_measureTable_startBeforeEnd()));
+ } else {
+ measurementUserPreferences.setMetricRangePreferences(prefs);
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/preferences/MeasurementUserPreferences.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/preferences/MeasurementUserPreferences.java
index 015cbf9..4a853c7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/preferences/MeasurementUserPreferences.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/preferences/MeasurementUserPreferences.java
@@ -134,18 +134,18 @@ public class MeasurementUserPreferences {
return prefs;
}
- public void setMetricViews(MetricViewsPreferences prefs, String key) {
- StringBuilder builder = new StringBuilder();
- int index = 0;
- for (String viewName : prefs.views) {
- if (index != 0) {
- builder.append(UserPreferences.PREF_LIST_DELIM);
- }
- builder.append(viewName);
- index++;
- }
- userPrefs.setPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + key, builder.toString());
- }
+// public void setMetricViews(MetricViewsPreferences prefs, String key) {
+// StringBuilder builder = new StringBuilder();
+// int index = 0;
+// for (String viewName : prefs.views) {
+// if (index != 0) {
+// builder.append(UserPreferences.PREF_LIST_DELIM);
+// }
+// builder.append(viewName);
+// index++;
+// }
+// userPrefs.setPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + key, builder.toString());
+// }
public String getSelectedView(String key) {
String value = userPrefs.getPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + "selected." + key,
@@ -153,49 +153,49 @@ public class MeasurementUserPreferences {
return value;
}
- public void setSelectedView(String key, String viewName) {
- userPrefs.setPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + "selected." + key, viewName);
- }
-
- public static class MetricViewData {
- public List<String> charts;
- }
-
- public MetricViewData getMetricViewData(String context, String viewName) {
- //TODO: jmarques - externalize default view name
- // instead of PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME
- // lookup PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT from the bundle
- if (viewName == null || "".equals(viewName)) {
- viewName = PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME;
- }
- MetricViewData chartPreferences = new MetricViewData();
- // important to let IllegalArgumentException bubble out of here, so the caller can persist the default set
- String data = userPrefs.getPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + context + "." + viewName);
- chartPreferences.charts = StringUtility.explode(data, UserPreferences.PREF_LIST_DELIM);
- return chartPreferences;
- }
-
- public void setMetricViewData(String context, String viewName, MetricViewData prefs) {
- //TODO: jmarques - externalize default view name
- // instead of PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME
- // lookup PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT from the bundle
- if (viewName == null || "".equals(viewName)) {
- viewName = PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME;
- }
- StringBuilder builder = new StringBuilder();
- int index = 0;
- for (String chart : prefs.charts) {
- if (index != 0) {
- builder.append(UserPreferences.PREF_LIST_DELIM);
- }
- builder.append(chart);
- index++;
- }
- userPrefs.setPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + context + "." + viewName, builder.toString());
- }
-
- public void deleteMetricViewData(String context, String viewName) {
- userPrefs.unsetPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + context + "." + viewName);
- }
+// public void setSelectedView(String key, String viewName) {
+// userPrefs.setPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + "selected." + key, viewName);
+// }
+//
+// public static class MetricViewData {
+// public List<String> charts;
+// }
+
+// public MetricViewData getMetricViewData(String context, String viewName) {
+// //TODO: jmarques - externalize default view name
+// // instead of PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME
+// // lookup PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT from the bundle
+// if (viewName == null || "".equals(viewName)) {
+// viewName = PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME;
+// }
+// MetricViewData chartPreferences = new MetricViewData();
+// // important to let IllegalArgumentException bubble out of here, so the caller can persist the default set
+// String data = userPrefs.getPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + context + "." + viewName);
+// chartPreferences.charts = StringUtility.explode(data, UserPreferences.PREF_LIST_DELIM);
+// return chartPreferences;
+// }
+//
+// public void setMetricViewData(String context, String viewName, MetricViewData prefs) {
+// //TODO: jmarques - externalize default view name
+// // instead of PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME
+// // lookup PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT from the bundle
+// if (viewName == null || "".equals(viewName)) {
+// viewName = PREF_MEASUREMENT_INDICATOR_VIEW_DEFAULT_NAME;
+// }
+// StringBuilder builder = new StringBuilder();
+// int index = 0;
+// for (String chart : prefs.charts) {
+// if (index != 0) {
+// builder.append(UserPreferences.PREF_LIST_DELIM);
+// }
+// builder.append(chart);
+// index++;
+// }
+// userPrefs.setPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + context + "." + viewName, builder.toString());
+// }
+//
+// public void deleteMetricViewData(String context, String viewName) {
+// userPrefs.unsetPreference(PREF_MEASUREMENT_INDICATOR_VIEW_PREFIX + context + "." + viewName);
+// }
}
commit 72efda3b93360c6679747bf0d0876cb5f18dd3ea
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 18:56:04 2013 -0700
Fix various behaviours between d3 slider and graphs.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index be99b9d..5535e78 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -112,7 +112,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
var start = startDate | 0, end = endDate | 0;
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::changeDateRange(DD)(start,end);
//@todo: fixme
- //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
}
function isSameDay(startDate, endDate) {
@@ -132,7 +132,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.startDate = $wnd.moment().startOf('hour');
graphDateContext.endDate = $wnd.moment().unix();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- saveDateRange(graphDateContext.startDate.unix(), graphDateContext.endDate.unix());
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioHour").bind('click', function (event) {
console.log("Hour selected");
@@ -165,11 +165,12 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
// initially populate
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- $wnd.jQuery("#radioHour").click();
+ //$wnd.jQuery("#radioHour").click();
}-*/;
public native void refreshGraphs() /*-{
+ console.log(" ** Calling GraphDateTimeRangeEditor.refreshGraphs");
this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::redrawGraphs()();
}-*/;
@@ -208,8 +209,9 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
}
public void changeDateRange(double startTime, double endTime){
- //measurementUserPreferences.getMetricRangePreferences().begin = new Long(startTime);
- //measurementUserPreferences.getMetricRangePreferences().end = new Long(String.valueOf(endTime));
+
+ measurementUserPreferences.getMetricRangePreferences().begin = new Long(String.valueOf(startTime));
+ measurementUserPreferences.getMetricRangePreferences().end = new Long(String.valueOf(endTime));
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
index 9be12b1..df69e36 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
@@ -174,9 +174,9 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
.orient("bottom"),
calcBarY = function (d) {
- var ABOVE = -10,
+ var ABOVE = -6,
BELOW = 0,
- STRADDLE = -5,
+ STRADDLE = -3,
offset;
if (d.availType === 'DOWN'){
@@ -203,19 +203,19 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
calcBarFill = function (d) {
if (d.availType === 'DOWN') {
- return "#FF1919"; // red
+ return "#c5888b"; // red
}
else if (d.availType === 'DISABLED') {
return "url(#diagonalHatchFill)"; // grey diagonal hatches
}
else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
+ return "#d8d8d8"; // gray
}
else if (d.availType === 'UP') {
- return "#198C19"; // green
+ return "#8cbe89"; // green
}
else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
+ return "#e1b36b"; // orange
}
else if (d.availType === 'EMPTY') {
return "#CCC"; // gray
@@ -243,12 +243,12 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
return calcBarY(d);
})
.attr("height", function (d) {
- return 10;
+ return 6;
})
.attr("width", function (d) {
return timeScale(+d.availEnd) - timeScale(+d.availStart);
})
- .attr("opacity", ".9")
+ .attr("opacity", ".75")
.attr("fill", function (d) {
return calcBarFill(d);
});
@@ -256,7 +256,7 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
// create x-axis
svg.append("g")
.attr("class", "x axis")
- .attr("fill", "#50505a")
+ .attr("fill", "#b0b0b0")
.attr("stroke-width", "0.5")
.attr("transform", "translate(0," + height + ")")
.attr("letter-spacing", "3")
@@ -270,7 +270,7 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
.style("font-size", "12px")
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-weight", "bold")
- .attr("fill", "#003168")
+ .attr("fill", "#545454")
.text(availChartContext.chartTitle);
svg.append("text")
@@ -279,7 +279,7 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
.attr("y", 28)
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-size", "9px")
- .attr("fill", "#50505a")
+ .attr("fill", "#545454")
.style("text-anchor", "end")
.text(availChartContext.chartUpLabel);
@@ -289,10 +289,12 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
.attr("y", 39)
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-size", "9px")
- .attr("fill", "#50505a")
+ .attr("fill", "#545454")
.style("text-anchor", "end")
.text(availChartContext.chartDownLabel);
+
+ // here is all the brush related stuff
var brush = $wnd.d3.svg.brush()
.x(timeScale)
.extent([1369033200, 1369084807])
@@ -300,10 +302,10 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
.on("brush", brushmove)
.on("brushend", brushend);
- var arc = $wnd.d3.svg.arc()
- .outerRadius(30 / 2)
- .startAngle(0)
- .endAngle(function(d, i) { return i ? -Math.PI : Math.PI; });
+// var arc = $wnd.d3.svg.arc()
+// .outerRadius(30 / 2)
+// .startAngle(0)
+// .endAngle(function(d, i) { return i ? -Math.PI : Math.PI; });
var brushg = svg.append("g")
.attr("class", "brush")
@@ -311,10 +313,10 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
brushg.selectAll(".resize").append("path")
.attr("transform", "translate(0," + height / 2 + ")")
- .attr("d", arc);
+ .attr("d", resizePath);
brushg.selectAll("rect")
- .attr("height", height);
+ .attr("height", 30);
brushstart();
brushmove();
@@ -334,6 +336,22 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
svg.classed("selecting", !d3.event.target.empty());
console.log("End start: "+s[0] + "End End: "+ s[1]);
}
+ // Taken from crossfilter (http://square.github.com/crossfilter/)
+ function resizePath(d) {
+ var e = +(d == 'e'),
+ x = e ? 1 : -1,
+ y = height / 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);
+ }
+
}
commit 33dd256a7b3009e526f88dad85d7afb512c5a88f
Merge: 08d93a3 e5d22ca
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 13:23:26 2013 -0700
Merge branch 'master' into mtho11/dual-slider-chart-control
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java
index d7528db,0000000..b086e0b
mode 100644,000000..100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java
@@@ -1,384 -1,0 +1,384 @@@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import java.util.Date;
+import java.util.List;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AvailabilityGraphType;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+/**
+ * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
+ * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
+ * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityOverUnderGraphType implements AvailabilityGraphType {
+
+ private static Messages MSG = CoreGUI.getMessages();
+ private List<Availability> availabilityList;
+ private List<ResourceGroupAvailability> groupAvailabilityList;
+ private Integer entityId;
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public AvailabilityOverUnderGraphType(Integer entityId) {
+ this.entityId = entityId;
+ }
+
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ this.availabilityList = availabilityList;
+ }
+
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ this.groupAvailabilityList = groupAvailabilityList;
+ }
+
+ public String getAvailabilityJson() {
+ StringBuilder sb = new StringBuilder("[");
+ if (null != availabilityList) {
+ // loop through the avail intervals
+ for (Availability availability : availabilityList) {
+ sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - availability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+
+ } else if (null != groupAvailabilityList) {
+ // loop through the group avail down intervals
+ for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
+ // allows substitution for situations like WARN=MIXED for easier terminology
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
+ .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
+ .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+
+ sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
+ sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
+ .getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - groupAvailability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+ }
+
+ sb.append("]");
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw Enhanced Availability chart");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(8)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
- var ABOVE = -10,
++ var ABOVE = -6,
+ BELOW = 0,
- STRADDLE = -5,
++ STRADDLE = -3,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
- return "#FF1919"; // red
++ return "#c5888b"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
++ return "#d8d8d8"; // gray
+ }
+ else if (d.availType === 'UP') {
- return "#198C19"; // green
++ return "#8cbe89"; // green
+ }
+ else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
++ return "#e1b36b"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.log("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+ })
+ .attr("height", function (d) {
- return 10;
++ return 6;
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
- .attr("opacity", ".9")
++ .attr("opacity", ".75")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
- .attr("fill", "#50505a")
++ .attr("fill", "#b0b0b0")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
- .attr("fill", "#003168")
++ .attr("fill", "#545454")
+ .text(availChartContext.chartTitle);
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
- .attr("fill", "#50505a")
++ .attr("fill", "#545454")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartUpLabel);
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
- .attr("fill", "#50505a")
++ .attr("fill", "#545454")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartDownLabel);
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart);
+
+ return '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+
+ }
+
+ return {
+ // Public API
+ draw: function (availChartContext) {
+ "use strict";
+ console.log("AvailabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+ public String getChartId() {
+ return String.valueOf(entityId);
+ }
+
+ public String getChartTimeLabel() {
+ return MSG.chart_time_label();
+ }
+
+ public String getChartDateLabel() {
+ return MSG.chart_date_label();
+ }
+
+ public String getChartHoverAvailabilityLabel() {
+ return MSG.chart_hover_availability_label();
+ }
+
+ public String getChartHoverStartLabel() {
+ return MSG.chart_hover_start_label();
+ }
+
+ public String getAvailChartDownLabel() {
+ return MSG.avail_chart_down_label();
+ }
+
+ public String getAvailChartUpLabel() {
+ return MSG.avail_chart_up_label();
+ }
+
+ public String getAvailChartTitleLabel() {
+ return MSG.avail_chart_title_label();
+ }
+
+ public String getChartHoverBarLabel() {
+ return MSG.chart_hover_bar_label();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return MSG.chart_hover_time_format();
+ }
+
+ public String getChartHoverDateFormat() {
+ return MSG.chart_hover_date_format();
+ }
+}
commit 08d93a34720c2b5ff23670e8b227738088eb6b31
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 12:31:26 2013 -0700
i18n the Button bar.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index 2126558..be99b9d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -21,7 +21,8 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
import com.google.gwt.user.client.Timer;
import com.smartgwt.client.widgets.HTMLFlow;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -37,6 +38,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
private JQueryDateTimeRangeEditor graphDateTimeRangeEditor;
private MeasurementUserPreferences measurementUserPreferences;
private AbstractD3GraphListView d3GraphListView;
+ private static final Messages MSG = CoreGUI.getMessages();
public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,AbstractD3GraphListView d3GraphListView) {
@@ -65,11 +67,11 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
" <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">\n" +
" <div class=\"accordion-inner\">\n" +
" <span class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
- " <button id=\"radioMin\" type=\"button\" class=\"btn \" >Min</button>\n" +
- " <button id=\"radioHour\" type=\"button\" class=\"btn \">Hour</button>\n" +
- " <button id=\"radioDay\" type=\"button\" class=\"btn \">Day</button>\n" +
- " <button id=\"radioMonth\" type=\"button\" class=\"btn \">Month</button>\n" +
- " <button id=\"radioYear\" type=\"button\" class=\"btn \">Year</button>\n" +
+ " <button id=\"radioMin\" type=\"button\" class=\"btn \" >"+MSG.chart_slider_button_bar_minute()+"</button>\n" +
+ " <button id=\"radioHour\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_hour()+"</button>\n" +
+ " <button id=\"radioDay\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_day()+"</button>\n" +
+ " <button id=\"radioMonth\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_month()+"</button>\n" +
+ " <button id=\"radioYear\" type=\"button\" class=\"btn \">"+MSG.chart_slider_button_bar_year()+"</button>\n" +
" </span>\n" +
" <input id=\"dateRange\" style=\"margin-left:30px;width:280px;\" type=\"text\" readonly=\"readonly\" />\n" +
" </div>\n" +
@@ -107,7 +109,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
}
function saveDateRange(startDate, endDate){
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::changeDateRange(Ljava/lang/Double;Ljava/lang/Double;)(D,D)(new Double(startDate.toString(), new Double(endDate.toString() )));
+ var start = startDate | 0, end = endDate | 0;
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::changeDateRange(DD)(start,end);
//@todo: fixme
//global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
}
@@ -127,32 +130,37 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
$wnd.jQuery("#radioMin").bind('click', function (event) {
console.log("Minute selected");
graphDateContext.startDate = $wnd.moment().startOf('hour');
- graphDateContext.endDate = $wnd.moment();
+ graphDateContext.endDate = $wnd.moment().unix();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate.unix(), graphDateContext.endDate.unix());
});
$wnd.jQuery("#radioHour").bind('click', function (event) {
console.log("Hour selected");
graphDateContext.startDate = $wnd.moment().startOf('hour');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioDay").bind('click', function (event) {
console.log("Day selected");
graphDateContext.startDate = $wnd.moment().startOf('week');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioMonth").bind('click', function (event) {
console.log("month selected");
graphDateContext.startDate = $wnd.moment().startOf('month');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioYear").bind('click', function (event) {
console.log("year selected");
graphDateContext.startDate = $wnd.moment().startOf('year');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ saveDateRange(graphDateContext.startDate, graphDateContext.endDate);
});
// initially populate
@@ -199,9 +207,9 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
return measurementUserPreferences.getMetricRangePreferences().begin;
}
- public void changeDateRange(Double startTime, Double endTime){
- measurementUserPreferences.getMetricRangePreferences().begin = new Long(String.valueOf(startTime));
- measurementUserPreferences.getMetricRangePreferences().end = new Long(String.valueOf(endTime));
+ public void changeDateRange(double startTime, double endTime){
+ //measurementUserPreferences.getMetricRangePreferences().begin = new Long(startTime);
+ //measurementUserPreferences.getMetricRangePreferences().end = new Long(String.valueOf(endTime));
}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 00a68ef..cf55365 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -21,6 +21,11 @@ chart_hover_start_label = Start
chart_hover_time_format = %I:%M:%S %p
chart_ie_not_supported = Charting is not available for this browser.
chart_no_data_label = No Data
+chart_slider_button_bar_minute = Min
+chart_slider_button_bar_hour = Hour
+chart_slider_button_bar_day = Day
+chart_slider_button_bar_month = Month
+chart_slider_button_bar_year = Year
chart_time_label = Start
chart_title_avg_label = Avg
chart_title_min_label = Min
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index a27fb3c..bc8a4cc 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -36,7 +36,6 @@
##chart_down_label = Down
##chart_time_label = Start
##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
##chart_title_avg_label = Avg
##chart_title_min_label = Min
##chart_title_peak_label = Max
@@ -45,6 +44,12 @@
##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
##chart_hover_start_label = Start
##chart_hover_end_label = End
##chart_hover_period_label = Period
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 5415ed0..7d8fdb0 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -16,7 +16,6 @@
##chart_down_label = Down
##chart_time_label = Start
##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
##chart_title_avg_label = Avg
##chart_title_min_label = Min
##chart_title_peak_label = Max
@@ -25,6 +24,12 @@
##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
##chart_hover_start_label = Start
##chart_hover_end_label = End
##chart_hover_period_label = Period
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 8f47413..e4daaad 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -16,7 +16,6 @@
##chart_down_label = Down
##chart_time_label = Start
##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
##chart_title_avg_label = Avg
##chart_title_min_label = Min
##chart_title_peak_label = Max
@@ -25,6 +24,12 @@
##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
##chart_hover_start_label = Start
##chart_hover_end_label = End
##chart_hover_period_label = Period
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 5d19d06..9d03a51 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -14,7 +14,6 @@
##chart_down_label = Down
##chart_time_label = Start
##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
##chart_title_avg_label = Avg
##chart_title_min_label = Min
##chart_title_peak_label = Max
@@ -23,6 +22,12 @@
##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
##chart_hover_start_label = Start
##chart_hover_end_label = End
##chart_hover_period_label = Period
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 743c4b5..da3fe9f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -13,7 +13,6 @@
##chart_down_label = Down
##chart_time_label = Start
##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
##chart_title_avg_label = Avg
##chart_title_min_label = Min
##chart_title_peak_label = Max
@@ -22,6 +21,12 @@
##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
##chart_hover_start_label = Start
##chart_hover_end_label = End
##chart_hover_period_label = Period
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 772c4e4..85837d6 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -13,7 +13,6 @@
##chart_down_label = Down
##chart_time_label = Start
##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
##chart_title_avg_label = Avg
##chart_title_min_label = Min
##chart_title_peak_label = Max
@@ -22,6 +21,12 @@
##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
##chart_hover_start_label = Start
##chart_hover_end_label = End
##chart_hover_period_label = Period
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 03dfa4e..f13c8d7 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -13,7 +13,6 @@
##chart_down_label = Down
##chart_time_label = Start
##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
##chart_title_avg_label = Avg
##chart_title_min_label = Min
##chart_title_peak_label = Max
@@ -22,6 +21,12 @@
##chart_hover_date_format = %m/%d/%y
##chart_hover_time_format = %I:%M:%S %p
##chart_ie_not_supported = Charting is not available for this browser.
+##chart_no_data_label = No Data
+##chart_slider_button_bar_minute = Min
+##chart_slider_button_bar_hour = Hour
+##chart_slider_button_bar_day = Day
+##chart_slider_button_bar_month = Month
+##chart_slider_button_bar_year = Year
##chart_hover_start_label = Start
##chart_hover_end_label = End
##chart_hover_period_label = Period
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
index 1021893..9105328 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
@@ -111,8 +111,8 @@ AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverSta
/**
* GraphDateContext object constructor.
- * @param startDate
- * @param endDate
+ * @param startDate moment object representing startDate range
+ * @param endDate moment object representing endDate range
* @constructor
*/
GraphDateContext = function (startDate, endDate){
commit 0377aa5396cff78cdb91bb4a05bc12f153805d9e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 10:23:58 2013 -0700
Fix some of button behavior for d3 slider implementation.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index 83fd973..2126558 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -67,7 +67,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
" <span class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
" <button id=\"radioMin\" type=\"button\" class=\"btn \" >Min</button>\n" +
" <button id=\"radioHour\" type=\"button\" class=\"btn \">Hour</button>\n" +
- " <button id=\"radioWeek\" type=\"button\" class=\"btn \">Week</button>\n" +
+ " <button id=\"radioDay\" type=\"button\" class=\"btn \">Day</button>\n" +
" <button id=\"radioMonth\" type=\"button\" class=\"btn \">Month</button>\n" +
" <button id=\"radioYear\" type=\"button\" class=\"btn \">Year</button>\n" +
" </span>\n" +
@@ -104,7 +104,9 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
}
$wnd.jQuery('#dateRange').val(formattedDateRange);
+ }
+ function saveDateRange(startDate, endDate){
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::changeDateRange(Ljava/lang/Double;Ljava/lang/Double;)(D,D)(new Double(startDate.toString(), new Double(endDate.toString() )));
//@todo: fixme
//global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
@@ -126,7 +128,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
console.log("Minute selected");
graphDateContext.startDate = $wnd.moment().startOf('hour');
graphDateContext.endDate = $wnd.moment();
- updateDateDisplay(graphDateContext);
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioHour").bind('click', function (event) {
console.log("Hour selected");
@@ -134,8 +136,8 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
});
- $wnd.jQuery("#radioWeek").bind('click', function (event) {
- console.log("Week selected");
+ $wnd.jQuery("#radioDay").bind('click', function (event) {
+ console.log("Day selected");
graphDateContext.startDate = $wnd.moment().startOf('week');
graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
@@ -155,8 +157,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
// initially populate
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- //@todo: fixme
- //$wnd.jQuery("#radioHour").click();
+ $wnd.jQuery("#radioHour").click();
}-*/;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
index 6f9ef81..9be12b1 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
@@ -179,7 +179,7 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
STRADDLE = -5,
offset;
- if (d.availType === 'DOWN') {
+ if (d.availType === 'DOWN'){
offset = BELOW;
}
else if (d.availType === 'DISABLED') {
@@ -293,6 +293,48 @@ public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGra
.style("text-anchor", "end")
.text(availChartContext.chartDownLabel);
+ var brush = $wnd.d3.svg.brush()
+ .x(timeScale)
+ .extent([1369033200, 1369084807])
+ .on("brushstart", brushstart)
+ .on("brush", brushmove)
+ .on("brushend", brushend);
+
+ var arc = $wnd.d3.svg.arc()
+ .outerRadius(30 / 2)
+ .startAngle(0)
+ .endAngle(function(d, i) { return i ? -Math.PI : Math.PI; });
+
+ var brushg = svg.append("g")
+ .attr("class", "brush")
+ .call(brush);
+
+ brushg.selectAll(".resize").append("path")
+ .attr("transform", "translate(0," + height / 2 + ")")
+ .attr("d", arc);
+
+ brushg.selectAll("rect")
+ .attr("height", height);
+
+ brushstart();
+ brushmove();
+
+ function brushstart() {
+ svg.classed("selecting", true);
+ }
+
+ function brushmove() {
+ var s = brush.extent();
+ //circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
+ console.log("Move start: "+s[0] + "Move End: "+ s[1]);
+ }
+
+ function brushend() {
+ var s = brush.extent();
+ svg.classed("selecting", !d3.event.target.empty());
+ console.log("End start: "+s[0] + "End End: "+ s[1]);
+ }
+
}
function createHovers() {
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
index 631b405..1b83532 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
@@ -43,12 +43,28 @@
.y.axis path {
stroke: #50505a;
}
-
+ /* Brush related css rules */
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
+.selecting circle {
+ fill-opacity: .2;
+}
+
+.selecting circle.selected {
+ stroke: #f00;
+}
+
+.resize path {
+ fill: #666;
+ fill-opacity: .8;
+ stroke: #000;
+ stroke-width: 1.5px;
+}
+
+
.minLabel, .avgLabel, .highLabel {
font-family: Arial, Verdana, sans-serif;
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
index 161ebcb..1021893 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
@@ -124,9 +124,4 @@ GraphDateContext = function (startDate, endDate){
this.endDate = endDate;
};
-function brushed() {
- x.domain(brush.empty() ? x2.domain() : brush.extent());
- focus.select("path").attr("d", area);
- focus.select(".x.axis").call(xAxis);
-}
commit 8597564b99aec88785c8f1bc637b0da386408ad1
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Sun May 19 13:50:59 2013 -0700
Refresh charts using new javascript date slider.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index c5d87b7..049be45 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -54,7 +54,7 @@ public abstract class AbstractD3GraphListView extends EnhancedVLayout implements
public AbstractD3GraphListView() {
super();
measurementUserPrefs = new MeasurementUserPreferences(UserSessionManager.getUserPreferences());
- graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs);
+ graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs,this);
startRefreshCycle();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
index 17dd595..83fd973 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -21,6 +21,8 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
import com.google.gwt.user.client.Timer;
import com.smartgwt.client.widgets.HTMLFlow;
+import org.rhq.enterprise.gui.coregui.client.components.measurement.AbstractMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
@@ -34,10 +36,12 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
private JQueryDateTimeRangeEditor graphDateTimeRangeEditor;
private MeasurementUserPreferences measurementUserPreferences;
+ private AbstractD3GraphListView d3GraphListView;
- public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs) {
+ public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs,AbstractD3GraphListView d3GraphListView) {
this.measurementUserPreferences = measurementUserPrefs;
+ this.d3GraphListView = d3GraphListView;
this.graphDateTimeRangeEditor = new JQueryDateTimeRangeEditor();
}
@@ -88,6 +92,7 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
console.log("Draw GraphDateTimeRangeEditor");
+ var global = this;
function updateDateDisplay(startDate, endDate ) {
var formattedDateRange;
@@ -99,6 +104,10 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
}
$wnd.jQuery('#dateRange').val(formattedDateRange);
+
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::changeDateRange(Ljava/lang/Double;Ljava/lang/Double;)(D,D)(new Double(startDate.toString(), new Double(endDate.toString() )));
+ //@todo: fixme
+ //global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::refreshGraphs()();
}
function isSameDay(startDate, endDate) {
@@ -113,43 +122,53 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
-
$wnd.jQuery("#radioMin").bind('click', function (event) {
- console.log("minute selected");
+ console.log("Minute selected");
graphDateContext.startDate = $wnd.moment().startOf('hour');
+ graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext);
});
$wnd.jQuery("#radioHour").bind('click', function (event) {
console.log("Hour selected");
graphDateContext.startDate = $wnd.moment().startOf('hour');
+ graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioWeek").bind('click', function (event) {
console.log("Week selected");
graphDateContext.startDate = $wnd.moment().startOf('week');
+ graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioMonth").bind('click', function (event) {
console.log("month selected");
graphDateContext.startDate = $wnd.moment().startOf('month');
+ graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
});
$wnd.jQuery("#radioYear").bind('click', function (event) {
console.log("year selected");
graphDateContext.startDate = $wnd.moment().startOf('year');
+ graphDateContext.endDate = $wnd.moment();
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
});
// initially populate
updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- $wnd.jQuery("#radioHour").click();
+ //@todo: fixme
+ //$wnd.jQuery("#radioHour").click();
}-*/;
public native void refreshGraphs() /*-{
-
+ this.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor::redrawGraphs()();
}-*/;
+
+ public void redrawGraphs(){
+ d3GraphListView.redrawGraphs();
+ }
+
@Override
protected void onDraw() {
super.onDraw();
@@ -179,15 +198,14 @@ public class GraphDateTimeRangeEditor extends EnhancedVLayout {
return measurementUserPreferences.getMetricRangePreferences().begin;
}
-// public void setStartTime(Long startTime) {
-// this.startTime = startTime;
-// }
+ public void changeDateRange(Double startTime, Double endTime){
+ measurementUserPreferences.getMetricRangePreferences().begin = new Long(String.valueOf(startTime));
+ measurementUserPreferences.getMetricRangePreferences().end = new Long(String.valueOf(endTime));
+
+ }
public Long getEndTime() {
return measurementUserPreferences.getMetricRangePreferences().end;
}
-// public void setEndTime(Long endTime) {
-// this.endTime = endTime;
-// }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 38a5544..d5e77d0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -112,7 +112,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
}
private void commonConstructorSettings() {
- graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs);
+ graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs,this);
setOverflow(Overflow.HIDDEN);
}
commit d107481bd1bbe076cb0301e949fd401132c44e03
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 17 17:06:29 2013 -0700
Change charttype package to graph and also graphtype sub package.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
index 1416b9d..d741ddd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
@@ -60,8 +60,8 @@ import org.rhq.enterprise.gui.coregui.client.dashboard.PortletViewFactory;
import org.rhq.enterprise.gui.coregui.client.dashboard.PortletWindow;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.selection.SingleResourceGroupSelector;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
index 0d6bcfd..bb1bf24 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
@@ -55,8 +55,8 @@ import org.rhq.enterprise.gui.coregui.client.dashboard.PortletViewFactory;
import org.rhq.enterprise.gui.coregui.client.dashboard.PortletWindow;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index e358774..c5d87b7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -29,7 +29,7 @@ import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.AutoRefreshUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.GraphDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AbstractGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AbstractGraph.java
deleted file mode 100644
index 27a6c02..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AbstractGraph.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-
-/**
- * Common Graph capability used across multiple graphs.
- * The MetricGraphData delegate is wrapped for JSNI access via d3 charts.
- * Also, by delegating and directly extending MetricGraphData we have more
- * control over the visibility of what we want graphs to 'see'.
- *
- * @see MetricGraphData
- *
- * @author Mike Thompson
- */
-public abstract class AbstractGraph extends VLayout implements HasD3MetricJsniChart {
-
- private MetricGraphData metricGraphData;
-
- public MetricGraphData getMetricGraphData() {
- return metricGraphData;
- }
-
- public void setMetricGraphData(MetricGraphData metricGraphData) {
- this.metricGraphData = metricGraphData;
- }
-
- public int getEntityId() {
- return metricGraphData.getEntityId();
- }
-
- @Override
- public void setEntityId(int entityId) {
- metricGraphData.setEntityId(entityId);
- }
-
-
- @Override
- public void setEntityName(String entityName) {
- metricGraphData.setEntityName(entityName);
- }
-
- public int getDefinitionId() {
- return metricGraphData.getDefinitionId();
- }
-
- public MeasurementDefinition getDefinition() {
- return metricGraphData.getDefinition();
- }
-
- @Override
- public void setDefinition(MeasurementDefinition definition) {
- metricGraphData.setDefinition(definition);
- }
-
- public String getChartId() {
- return metricGraphData.getChartId();
- }
-
- public boolean showBarAvgTrendLine(){
- return metricGraphData.showBarAvgTrendLine();
- }
-
- public String getChartTitleMinLabel() {
- return metricGraphData.getChartTitleMinLabel();
- }
-
- public String getChartTitleAvgLabel() {
- return metricGraphData.getChartTitleAvgLabel();
- }
-
- public String getChartTitlePeakLabel() {
- return metricGraphData.getChartTitlePeakLabel();
- }
-
- public String getChartDateLabel() {
- return metricGraphData.getChartDateLabel();
- }
-
- public String getChartDownLabel() {
- return metricGraphData.getChartDownLabel();
- }
-
- public String getChartTimeLabel() {
- return metricGraphData.getChartTimeLabel();
- }
-
- public String getChartUnknownLabel() {
- return metricGraphData.getChartUnknownLabel();
- }
-
- public String getChartNoDataLabel() {
- return metricGraphData.getChartNoDataLabel();
- }
-
- public String getChartHoverStartLabel() {
- return metricGraphData.getChartHoverStartLabel();
- }
-
- public String getChartHoverEndLabel() {
- return metricGraphData.getChartHoverEndLabel();
- }
-
- public String getChartHoverPeriodLabel() {
- return metricGraphData.getChartHoverPeriodLabel();
- }
-
- public String getChartHoverBarLabel() {
- return metricGraphData.getChartHoverBarLabel();
- }
-
- public String getChartHoverTimeFormat() {
- return metricGraphData.getChartHoverTimeFormat();
- }
-
- public String getChartHoverDateFormat() {
- return metricGraphData.getChartHoverDateFormat();
- }
-
-
- public int getChartHeight() {
- return metricGraphData.getChartHeight();
- }
-
- public void setChartHeight(Integer chartHeight) {
- metricGraphData.setChartHeight(chartHeight);
- }
-
- public String getChartTitle() {
- return metricGraphData != null ? metricGraphData.getChartTitle() : "";
- }
- public boolean isPortalGraph(){
- return metricGraphData.isPortalGraph();
- }
-
-
- public String getYAxisUnits() {
- return metricGraphData.getYAxisUnits();
- }
-
- public String getXAxisTitle() {
- return metricGraphData.getXAxisTitle();
- }
-
- public String getJsonMetrics() {
- return metricGraphData.getJsonMetrics();
- }
-
- public int getPortalId() {
- return metricGraphData.getPortalId();
- }
-
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java
deleted file mode 100644
index 36d0807..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-/**
- * Interface for AvailabilityGraphs. Implementations of this interface
- * always need to define the capability of creating a graph marker
- * - some kind of div with an id that d3 can bind to and able to
- * drawJsniChart to actually draw(render) the d3 graph.
- *
- * @author Mike Thompson
- */
-@Deprecated
-public interface AvailabilityGraph {
-
- /**
- * Step 1 create the graph marker to allow d3 to bind.
- */
- void createGraphMarker();
-
- /**
- * Step 2 bind to the above div#id and render the chart.
- */
- void drawJsniChart();
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraphType.java
deleted file mode 100644
index f390c6e..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraphType.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import java.util.List;
-
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-
-/**
- * Contract for an Availability Graph Implementation. This gives the abilility for
- * Availability graphs to swap implementations giving different chart types.
- *
- * @author Mike Thompson
- */
-public interface AvailabilityGraphType {
-
- void setAvailabilityList(List<Availability> availabilityList);
-
- void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList);
-
- String getAvailabilityJson();
-
- String getChartId();
-
- void drawJsniChart();
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java
deleted file mode 100644
index 1b14f8c..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import java.util.Date;
-import java.util.List;
-
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
- * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
- * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
- *
- * @author Mike Thompson
- */
-public class AvailabilityLineGraphType implements AvailabilityGraphType {
-
- private static Messages MSG = CoreGUI.getMessages();
- private List<Availability> availabilityList;
- private List<ResourceGroupAvailability> groupAvailabilityList;
- private Integer entityId;
-
- /**
- * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
- * for all cases but the dashboard portlet).
- */
- public AvailabilityLineGraphType(Integer entityId) {
- this.entityId = entityId;
- }
-
- public void setAvailabilityList(List<Availability> availabilityList) {
- this.availabilityList = availabilityList;
- }
-
- public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
- this.groupAvailabilityList = groupAvailabilityList;
- }
-
- public String getAvailabilityJson() {
- StringBuilder sb = new StringBuilder("[");
- if (null != availabilityList) {
- // loop through the avail intervals
- for (Availability availability : availabilityList) {
- sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType()+ "\", ");
- sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
- // last record will be null
- long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - availability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
-
- } else if (null != groupAvailabilityList) {
- // loop through the group avail down intervals
- for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
- // allows substitution for situations like WARN=MIXED for easier terminology
- String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType().equals(ResourceGroupComposite.GroupAvailabilityType.WARN))
- ? MSG.chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
-
- sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
- sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
- // last record will be null
- long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
- .getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - groupAvailability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
- }
-
- sb.append("]");
- Log.debug(sb.toString());
- return sb.toString();
- }
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart() /*-{
- console.log("Draw Availability chart");
-
- var global = this,
- // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
- // NOTE: rhq.js has the javascript object constructors in it.
- availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getAvailabilityJson()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartHoverEndLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartHoverAvailabilityLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType::getChartHoverDateFormat()()
- );
-
-
- var availabilityGraph = function () {
- "use strict";
- // privates
-
- var margin = {top: 5, right: 5, bottom: 5, left: 40},
- barOffset = 10,
- width = 750 - margin.left - margin.right + barOffset,
- height = 20 - margin.top - margin.bottom,
- pixelsOffHeight = 0,
- svg;
-
-
- function drawBars(availChartContext) {
- var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
- return +d.availStart;
- }),
- xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
- return +d.availEnd;
- }),
-
- timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain([xAxisMin, xAxisMax]),
-
- yScale = $wnd.d3.scale.linear()
- .clamp(true)
- .rangeRound([height, 0])
- .domain([0, 4]),
-
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-
- // The gray bars at the bottom leading up
- svg.selectAll("rect.availBars")
- .data(availChartContext.data)
- .enter().append("rect")
- .attr("class", "availBars")
- .attr("x", function (d) {
- return timeScale(+d.availStart);
- })
- .attr("y", function (d) {
- return yScale(0);
- })
- .attr("height", function (d) {
- return height - yScale(4) - pixelsOffHeight;
- })
- .attr("width", function (d) {
- return timeScale(+d.availEnd) - timeScale(+d.availStart);
- })
-
- .attr("opacity", ".9")
- .attr("fill", function (d) {
- if (d.availType === 'DOWN') {
- return "#FF1919"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "#FF9933"; // orange
- }
- else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
- }
- else if (d.availType === 'UP') {
- return "#198C19"; // green
- }
- else if (d.availType === 'WARN') {
- return "#FFFF00"; // yellow
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.warn("AvailabilityType not valid.");
- return "#000"; //black
- }
- });
- }
-
- function createHovers() {
- $wnd.jQuery('svg rect.availBars').tipsy({
- gravity: 'n',
- html: true,
- trigger: 'hover',
- title: function () {
- var d = this.__data__;
- return formatHovers(d);
- },
- show: function (e, el) {
- el.css({ 'z-index': '990000'})
- }
- });
- }
-
- function formatHovers(d) {
- var hoverString,
- timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
- dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart),
- availEnd = new Date(+d.availEnd);
-
- hoverString =
- '<div class="chartHoverEnclosingDiv">' +
- '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverStartLabel + ': </span><span style="width:50px;">' + timeFormatter(availStart) + '</span></div>' +
- '<div class="chartHoverAlignRight"><span >' + ' </span><span style="width:50px;">' + dateFormatter(availStart) + '</span></div>' +
- '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverEndLabel + ': </span><span style="width:50px;">' + timeFormatter(availEnd) + '</span></div>' +
- '<div class="chartHoverAlignRight"><span >' + ' </span><span style="width:50px;">' + dateFormatter(availEnd) + '</span></div>' +
- '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
- '</div>';
- return hoverString;
-
- }
-
- return {
- // Public API
- draw: function (chartContext) {
- "use strict";
- console.info("AvailabilityChart");
- //console.time("availabilityChart");
-
- drawBars(availChartContext);
- createHovers();
- //console.timeEnd("availabilityChart");
- }
- }; // end public closure
-
-
- }();
-
- if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
- availabilityGraph.draw(availChartContext);
- }
-
- }-*/;
-
- public String getChartId() {
- return String.valueOf(entityId);
- }
-
- public String getChartTimeLabel() {
- return MSG.chart_time_label();
- }
-
- public String getChartDateLabel() {
- return MSG.chart_date_label();
- }
-
- public String getChartHoverAvailabilityLabel() {
- return MSG.chart_hover_availability_label();
- }
-
- public String getChartHoverStartLabel() {
- return MSG.chart_hover_start_label();
- }
-
- public String getChartHoverEndLabel() {
- return MSG.chart_hover_end_label();
- }
-
- public String getChartHoverBarLabel() {
- return MSG.chart_hover_bar_label();
- }
-
- public String getChartHoverTimeFormat() {
- return MSG.chart_hover_time_format();
- }
-
- public String getChartHoverDateFormat() {
- return MSG.chart_hover_date_format();
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
deleted file mode 100644
index 29d5742..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import java.util.Date;
-import java.util.List;
-
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
- * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
- * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
- *
- * @author Mike Thompson
- */
-public class AvailabilityOverUnderGraphType implements AvailabilityGraphType{
-
- private static Messages MSG = CoreGUI.getMessages();
- private List<Availability> availabilityList;
- private List<ResourceGroupAvailability> groupAvailabilityList;
- private Integer entityId;
-
- /**
- * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
- * for all cases but the dashboard portlet).
- */
- public AvailabilityOverUnderGraphType(Integer entityId) {
- this.entityId = entityId;
- }
-
- public void setAvailabilityList(List<Availability> availabilityList) {
- this.availabilityList = availabilityList;
- }
-
- public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
- this.groupAvailabilityList = groupAvailabilityList;
- }
-
- public String getAvailabilityJson() {
- StringBuilder sb = new StringBuilder("[");
- if (null != availabilityList) {
- // loop through the avail intervals
- for (Availability availability : availabilityList) {
- sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
- // last record will be null
- long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - availability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
-
- } else if (null != groupAvailabilityList) {
- // loop through the group avail down intervals
- for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
- // allows substitution for situations like WARN=MIXED for easier terminology
- String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
- .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
- .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
-
- sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
- sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
- // last record will be null
- long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
- .getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - groupAvailability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
- }
-
- sb.append("]");
- Log.debug(sb.toString());
- return sb.toString();
- }
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart() /*-{
- console.log("Draw Enhanced Availability chart");
-
- var global = this,
- // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
- // NOTE: rhq.js has the javascript object constructors in it.
- availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
- );
-
-
- var availabilityGraph = function () {
- "use strict";
- // privates
-
- var margin = {top: 5, right: 5, bottom: 5, left: 40},
- barOffset = 10,
- width = 750 - margin.left - margin.right + barOffset,
- height = 40 - margin.top - margin.bottom,
- svg;
-
-
- function drawBars(availChartContext) {
- var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
- return +d.availStart;
- }),
- xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
- return +d.availEnd;
- }),
-
- timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain([xAxisMin, xAxisMax]),
-
- yScale = $wnd.d3.scale.linear()
- .clamp(true)
- .rangeRound([height, 0])
- .domain([0, 4]),
-
- xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(8)
- .tickSize(13, 0, 0)
- .orient("bottom"),
-
- calcBarY = function (d) {
- var ABOVE = -10,
- BELOW = 0,
- STRADDLE = -5,
- offset;
-
- if (d.availType === 'DOWN') {
- offset = BELOW;
- }
- else if (d.availType === 'DISABLED') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UNKNOWN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UP') {
- offset = ABOVE;
- }
- else if (d.availType === 'WARN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'EMPTY') {
- offset = STRADDLE;
- }
- return yScale(0) + offset;
-
- },
-
- calcBarFill = function (d) {
- if (d.availType === 'DOWN') {
- return "#FF1919"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "url(#diagonalHatchFill)"; // grey diagonal hatches
- }
- else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
- }
- else if (d.availType === 'UP') {
- return "#198C19"; // green
- }
- else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.log("AvailabilityType not valid.");
- return "#000"; //black
- }
- },
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-
- svg.selectAll("rect.availBars")
- .data(availChartContext.data)
- .enter().append("rect")
- .attr("class", "availBars")
- .attr("x", function (d) {
- return timeScale(+d.availStart);
- })
- .attr("y", function (d) {
- return calcBarY(d);
- })
- .attr("height", function (d) {
- return 10;
- })
- .attr("width", function (d) {
- return timeScale(+d.availEnd) - timeScale(+d.availStart);
- })
- .attr("opacity", ".9")
- .attr("fill", function (d) {
- return calcBarFill(d);
- });
-
- // create x-axis
- svg.append("g")
- .attr("class", "x axis")
- .attr("fill", "#50505a")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
-
- svg.append("text")
- .attr("class", "availabilityLabel")
- .attr("x", -40)
- .attr("y", 10)
- .style("font-size", "12px")
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-weight", "bold")
- .attr("fill", "#003168")
- .text(availChartContext.chartTitle);
-
- svg.append("text")
- .attr("class", "upLabel")
- .attr("x", -5)
- .attr("y", 28)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartUpLabel);
-
- svg.append("text")
- .attr("class", "downLabel")
- .attr("x", -5)
- .attr("y", 39)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartDownLabel);
-
- }
-
- function createHovers() {
- $wnd.jQuery('svg rect.availBars').tipsy({
- gravity: 's',
- html: true,
- trigger: 'hover',
- title: function () {
- var d = this.__data__;
- return formatHovers(d);
- },
- show: function (e, el) {
- el.css({ 'z-index': '990000'})
- }
- });
- }
-
- function formatHovers(d) {
- var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
- dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart);
-
- return '<div class="chartHoverEnclosingDiv">' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
- '</div>';
-
- }
-
- return {
- // Public API
- draw: function (availChartContext) {
- "use strict";
- console.log("AvailabilityChart");
- drawBars(availChartContext);
- createHovers();
- }
- }; // end public closure
-
-
- }();
-
- if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
- availabilityGraph.draw(availChartContext);
- }
-
- }-*/;
-
- public String getChartId() {
- return String.valueOf(entityId);
- }
-
- public String getChartTimeLabel() {
- return MSG.chart_time_label();
- }
-
- public String getChartDateLabel() {
- return MSG.chart_date_label();
- }
-
- public String getChartHoverAvailabilityLabel() {
- return MSG.chart_hover_availability_label();
- }
-
- public String getChartHoverStartLabel() {
- return MSG.chart_hover_start_label();
- }
-
- public String getAvailChartDownLabel() {
- return MSG.avail_chart_down_label();
- }
-
- public String getAvailChartUpLabel() {
- return MSG.avail_chart_up_label();
- }
-
- public String getAvailChartTitleLabel() {
- return MSG.avail_chart_title_label();
- }
-
- public String getChartHoverBarLabel() {
- return MSG.chart_hover_bar_label();
- }
-
- public String getChartHoverTimeFormat() {
- return MSG.chart_hover_time_format();
- }
-
- public String getChartHoverDateFormat() {
- return MSG.chart_hover_date_format();
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphWithSliderType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphWithSliderType.java
deleted file mode 100644
index 24c3ae1..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphWithSliderType.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import java.util.Date;
-import java.util.List;
-
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
- * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
- * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
- *
- * @author Mike Thompson
- */
-public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGraphType {
-
- private static Messages MSG = CoreGUI.getMessages();
- private List<Availability> availabilityList;
- private List<ResourceGroupAvailability> groupAvailabilityList;
- private Integer entityId;
-
- /**
- * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
- * for all cases but the dashboard portlet).
- */
- public AvailabilityOverUnderGraphWithSliderType(Integer entityId) {
- this.entityId = entityId;
- }
-
- @Override
- public void setAvailabilityList(List<Availability> availabilityList) {
- this.availabilityList = availabilityList;
- }
-
- @Override
- public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
- this.groupAvailabilityList = groupAvailabilityList;
- }
-
- @Override
- public String getAvailabilityJson() {
- StringBuilder sb = new StringBuilder("[");
- if (null != availabilityList) {
- // loop through the avail intervals
- for (Availability availability : availabilityList) {
- sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
- // last record will be null
- long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - availability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
-
- } else if (null != groupAvailabilityList) {
- // loop through the group avail down intervals
- for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
- // allows substitution for situations like WARN=MIXED for easier terminology
- String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
- .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
- .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
-
- sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
- sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
- // last record will be null
- long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
- .getTime();
- sb.append(" \"availEnd\":" + endTime + ", ");
-
- long availDuration = endTime - groupAvailability.getStartTime();
- String availDurationString = MeasurementConverterClient.format((double) availDuration,
- MeasurementUnits.MILLISECONDS, true);
- sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
-
- }
- sb.setLength(sb.length() - 1);
- }
-
- sb.append("]");
- Log.debug(sb.toString());
- return sb.toString();
- }
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- @Override
- public native void drawJsniChart() /*-{
- console.log("Draw Enhanced Availability chart");
-
- var global = this,
- // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
- // NOTE: rhq.js has the javascript object constructors in it.
- availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailabilityJson()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverAvailabilityLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverDateFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailChartTitleLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailChartUpLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailChartDownLabel()()
- );
-
-
- var availabilityGraph = function () {
- "use strict";
- // privates
-
- var margin = {top: 5, right: 5, bottom: 5, left: 40},
- barOffset = 10,
- width = 750 - margin.left - margin.right + barOffset,
- height = 40 - margin.top - margin.bottom,
- svg;
-
-
- function drawBars(availChartContext) {
- var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
- return +d.availStart;
- }),
- xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
- return +d.availEnd;
- }),
-
- timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain([xAxisMin, xAxisMax]),
-
- yScale = $wnd.d3.scale.linear()
- .clamp(true)
- .rangeRound([height, 0])
- .domain([0, 4]),
-
- xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(8)
- .tickSize(13, 0, 0)
- .orient("bottom"),
-
- calcBarY = function (d) {
- var ABOVE = -10,
- BELOW = 0,
- STRADDLE = -5,
- offset;
-
- if (d.availType === 'DOWN') {
- offset = BELOW;
- }
- else if (d.availType === 'DISABLED') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UNKNOWN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UP') {
- offset = ABOVE;
- }
- else if (d.availType === 'WARN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'EMPTY') {
- offset = STRADDLE;
- }
- return yScale(0) + offset;
-
- },
-
- calcBarFill = function (d) {
- if (d.availType === 'DOWN') {
- return "#FF1919"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "url(#diagonalHatchFill)"; // grey diagonal hatches
- }
- else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
- }
- else if (d.availType === 'UP') {
- return "#198C19"; // green
- }
- else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.log("AvailabilityType not valid.");
- return "#000"; //black
- }
- },
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-
- svg.selectAll("rect.availBars")
- .data(availChartContext.data)
- .enter().append("rect")
- .attr("class", "availBars")
- .attr("x", function (d) {
- return timeScale(+d.availStart);
- })
- .attr("y", function (d) {
- return calcBarY(d);
- })
- .attr("height", function (d) {
- return 10;
- })
- .attr("width", function (d) {
- return timeScale(+d.availEnd) - timeScale(+d.availStart);
- })
- .attr("opacity", ".9")
- .attr("fill", function (d) {
- return calcBarFill(d);
- });
-
- // create x-axis
- svg.append("g")
- .attr("class", "x axis")
- .attr("fill", "#50505a")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
-
- svg.append("text")
- .attr("class", "availabilityLabel")
- .attr("x", -40)
- .attr("y", 10)
- .style("font-size", "12px")
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-weight", "bold")
- .attr("fill", "#003168")
- .text(availChartContext.chartTitle);
-
- svg.append("text")
- .attr("class", "upLabel")
- .attr("x", -5)
- .attr("y", 28)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartUpLabel);
-
- svg.append("text")
- .attr("class", "downLabel")
- .attr("x", -5)
- .attr("y", 39)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartDownLabel);
-
- }
-
- function createHovers() {
- $wnd.jQuery('svg rect.availBars').tipsy({
- gravity: 's',
- html: true,
- trigger: 'hover',
- title: function () {
- var d = this.__data__;
- return formatHovers(d);
- },
- show: function (e, el) {
- el.css({ 'z-index': '990000'})
- }
- });
- }
-
- function formatHovers(d) {
- var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
- dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart);
-
- return '<div class="chartHoverEnclosingDiv">' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
- '</div>';
-
- }
-
- return {
- // Public API
- draw: function (availChartContext) {
- "use strict";
- console.log("AvailabilityChart");
- drawBars(availChartContext);
- createHovers();
- }
- }; // end public closure
-
-
- }();
-
- if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
- availabilityGraph.draw(availChartContext);
- }
-
- }-*/;
-
- public String getChartId() {
- return String.valueOf(entityId);
- }
-
- public String getChartTimeLabel() {
- return MSG.chart_time_label();
- }
-
- public String getChartDateLabel() {
- return MSG.chart_date_label();
- }
-
- public String getChartHoverAvailabilityLabel() {
- return MSG.chart_hover_availability_label();
- }
-
- public String getChartHoverStartLabel() {
- return MSG.chart_hover_start_label();
- }
-
- public String getAvailChartDownLabel() {
- return MSG.avail_chart_down_label();
- }
-
- public String getAvailChartUpLabel() {
- return MSG.avail_chart_up_label();
- }
-
- public String getAvailChartTitleLabel() {
- return MSG.avail_chart_title_label();
- }
-
- public String getChartHoverBarLabel() {
- return MSG.chart_hover_bar_label();
- }
-
- public String getChartHoverTimeFormat() {
- return MSG.chart_hover_time_format();
- }
-
- public String getChartHoverDateFormat() {
- return MSG.chart_hover_date_format();
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/GraphDateTimeRangeEditor.java
deleted file mode 100644
index 9dd7b4a..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/GraphDateTimeRangeEditor.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import com.google.gwt.user.client.Timer;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
-
-/**
- * Component to allow selection of Date/Time range for graphs.
- *
- * @author Mike Thompson
- */
-public class GraphDateTimeRangeEditor extends EnhancedVLayout {
-
- private JQueryDateTimeRangeEditor graphDateTimeRangeEditor;
- private MeasurementUserPreferences measurementUserPreferences;
-
-
- public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs) {
- this.measurementUserPreferences = measurementUserPrefs;
- this.graphDateTimeRangeEditor = new JQueryDateTimeRangeEditor();
- }
-
- /**
- * Setup the page elements especially the div and svg elements that serve as
- * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
- * Later the drawJsniGraph() is called to actually fill in the div/svg element
- * created here with the actual svg element.
- * NOTE: auxiliary javascript functions in rhq.js
- *
- */
- public void createGraphMarker() {
- Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
-
- // append the bootstrap buttongroup since smartGWT doesn't have one
- StringBuilder divAndSvgDefs = new StringBuilder();
- divAndSvgDefs.append("<div id=\"graphDateTimeRangeEditor\">" +
- "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:875px;>\n" +
- " <div class=\"accordion-group\">\n" +
- " \n" +
- " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">\n" +
- " <div class=\"accordion-inner\">\n" +
- " <span class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
- " <button id=\"radioMin\" type=\"button\" class=\"btn \" >Min</button>\n" +
- " <button id=\"radioHour\" type=\"button\" class=\"btn \">Hour</button>\n" +
- " <button id=\"radioWeek\" type=\"button\" class=\"btn \">Week</button>\n" +
- " <button id=\"radioMonth\" type=\"button\" class=\"btn \">Month</button>\n" +
- " <button id=\"radioYear\" type=\"button\" class=\"btn \">Year</button>\n" +
- " </span>\n" +
- " <input id=\"dateRange\" style=\"margin-left:30px;width:280px;\" type=\"text\"/>\n" +
- " </div>\n" +
- " </div>\n" +
- " </div>\n" +
- " </div>\n"+
- "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
- divAndSvgDefs.append("</svg></div>");
- HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
- graph.setWidth100();
- graph.setHeight(65);
- addMember(graph);
- new Timer(){
- @Override
- public void run() {
- attachGraphDateRangeEditorButtonGroupHandlers();
- }
- }.schedule(400);
- }
-
- public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
- console.log("Draw GraphDateTimeRangeEditor");
- console.warn("Registering Handlers");
-
- function updateDateDisplay(startDate, endDate ) {
- var formattedDateRange;
-
- if (isSameDay(startDate, endDate) && isSameMonth(startDate, endDate) && isSameYear(startDate, endDate)) {
- // no need to display date only time
- formattedDateRange = startDate.format('ddd') + ': ' + startDate.format('h:mm a') + ' - ' + endDate.format('h:mm a');
- } else {
- formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
- }
- $wnd.jQuery('#dateRange').val(formattedDateRange);
- }
-
- function isSameDay(startDate, endDate) {
- return (startDate.date() === endDate.date());
- }
- function isSameMonth(startDate, endDate) {
- return (startDate.month() === endDate.month());
- }
- function isSameYear(startDate, endDate) {
- return (startDate.year() === endDate.year());
- }
-
- var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
-
-
- $wnd.jQuery("#radioMin").bind('click', function (event) {
- console.warn("minute selected");
- graphDateContext.startDate = $wnd.moment().startOf('hour');
- updateDateDisplay(graphDateContext);
- });
- $wnd.jQuery("#radioHour").bind('click', function (event) {
- console.log("Hour selected");
- graphDateContext.startDate = $wnd.moment().startOf('hour');
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radioWeek").bind('click', function (event) {
- console.log("Week selected");
- graphDateContext.startDate = $wnd.moment().startOf('week');
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radioMonth").bind('click', function (event) {
- console.log("month selected");
- graphDateContext.startDate = $wnd.moment().startOf('month');
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- });
- $wnd.jQuery("#radioYear").bind('click', function (event) {
- console.log("year selected");
- graphDateContext.startDate = $wnd.moment().startOf('year');
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- });
-
- // initially populate
- updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
- $wnd.jQuery("#radioHour").click();
-
- }-*/;
-
- @Override
- protected void onDraw() {
- super.onDraw();
- removeMembers(getMembers());
- createGraphMarker();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- createGraphMarker();
- drawJsniChart();
- }
-
-
- /**
- * Delegate the call to rendering the JSNI chart.
- * This way the chart type can be swapped out at any time.
- */
- public void drawJsniChart() {
- graphDateTimeRangeEditor.drawJsniChart();
- }
-
-
- public Long getStartTime() {
- return measurementUserPreferences.getMetricRangePreferences().begin;
- }
-
-// public void setStartTime(Long startTime) {
-// this.startTime = startTime;
-// }
-
- public Long getEndTime() {
- return measurementUserPreferences.getMetricRangePreferences().end;
- }
-
-// public void setEndTime(Long endTime) {
-// this.endTime = endTime;
-// }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/HasD3MetricJsniChart.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/HasD3MetricJsniChart.java
deleted file mode 100644
index e315ff2..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/HasD3MetricJsniChart.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-
-/**
- * Defines GWT JSNI charting capability. Indicator of a class producing
- * d3 (javascript) charts. Allows us to quickly find, in a standard
- * way JSNI charts like d3. Finding implementations of this class
- * will reveal all the d3 charting implementations.
- *
- * @author Mike Thompson
- */
-public interface HasD3MetricJsniChart
-{
- void drawJsniChart();
- void setEntityId(int entityId) ;
- void setEntityName(String entityName) ;
- void setDefinition(MeasurementDefinition measurementDefinition) ;
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/JQueryDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/JQueryDateTimeRangeEditor.java
deleted file mode 100644
index 656e47a..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/JQueryDateTimeRangeEditor.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-
-/**
- * An implementation using JQuery UI components because smartGWT doesn't contain buttonsets or dual range sliders.
- *
- * @author Mike Thompson
- */
-public class JQueryDateTimeRangeEditor {
- private static Messages MSG = CoreGUI.getMessages();
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart() /*-{
- console.log("Draw GraphDateTimeRangeEditor");
-
- var global = this,
- // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
- // NOTE: rhq.js has the javascript object constructors in it.
- availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
- );
-
-
- var availabilityGraph = function () {
- "use strict";
- // privates
-
- var margin = {top: 5, right: 5, bottom: 5, left: 40},
- barOffset = 10,
- width = 750 - margin.left - margin.right + barOffset,
- height = 40 - margin.top - margin.bottom,
- svg;
-
-
- function drawBars(availChartContext) {
- var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
- return +d.availStart;
- }),
- xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
- return +d.availEnd;
- }),
-
- timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain([xAxisMin, xAxisMax]),
-
- yScale = $wnd.d3.scale.linear()
- .clamp(true)
- .rangeRound([height, 0])
- .domain([0, 4]),
-
- xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(8)
- .tickSize(13, 0, 0)
- .orient("bottom"),
-
- calcBarY = function (d) {
- var ABOVE = -10,
- BELOW = 0,
- STRADDLE = -5,
- offset;
-
- if (d.availType === 'DOWN') {
- offset = BELOW;
- }
- else if (d.availType === 'DISABLED') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UNKNOWN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UP') {
- offset = ABOVE;
- }
- else if (d.availType === 'WARN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'EMPTY') {
- offset = STRADDLE;
- }
- return yScale(0) + offset;
-
- },
-
- calcBarFill = function (d) {
- if (d.availType === 'DOWN') {
- return "#FF1919"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "url(#diagonalHatchFill)"; // grey diagonal hatches
- }
- else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
- }
- else if (d.availType === 'UP') {
- return "#198C19"; // green
- }
- else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.log("AvailabilityType not valid.");
- return "#000"; //black
- }
- },
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-
- svg.selectAll("rect.availBars")
- .data(availChartContext.data)
- .enter().append("rect")
- .attr("class", "availBars")
- .attr("x", function (d) {
- return timeScale(+d.availStart);
- })
- .attr("y", function (d) {
- return calcBarY(d);
- })
- .attr("height", function (d) {
- return 10;
- })
- .attr("width", function (d) {
- return timeScale(+d.availEnd) - timeScale(+d.availStart);
- })
- .attr("opacity", ".9")
- .attr("fill", function (d) {
- return calcBarFill(d);
- });
-
- // create x-axis
- svg.append("g")
- .attr("class", "x axis")
- .attr("fill", "#50505a")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
-
- svg.append("text")
- .attr("class", "availabilityLabel")
- .attr("x", -40)
- .attr("y", 10)
- .style("font-size", "12px")
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-weight", "bold")
- .attr("fill", "#003168")
- .text(availChartContext.chartTitle);
-
- svg.append("text")
- .attr("class", "upLabel")
- .attr("x", -5)
- .attr("y", 28)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartUpLabel);
-
- svg.append("text")
- .attr("class", "downLabel")
- .attr("x", -5)
- .attr("y", 39)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text(availChartContext.chartDownLabel);
-
- }
-
- function createHovers() {
- $wnd.jQuery('svg rect.availBars').tipsy({
- gravity: 's',
- html: true,
- trigger: 'hover',
- title: function () {
- var d = this.__data__;
- return formatHovers(d);
- },
- show: function (e, el) {
- el.css({ 'z-index': '990000'})
- }
- });
- }
-
- function formatHovers(d) {
- var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
- dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart);
-
- return '<div class="chartHoverEnclosingDiv">' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
- '</div>';
-
- }
-
- return {
- // Public API
- draw: function (availChartContext) {
- "use strict";
- console.log("AvailabilityChart");
- drawBars(availChartContext);
- createHovers();
- }
- }; // end public closure
-
-
- }();
-
- if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
- availabilityGraph.draw(availChartContext);
- }
-
- }-*/;
-
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/LineMetricGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/LineMetricGraph.java
deleted file mode 100644
index d5553ff..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/LineMetricGraph.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-/**
- * Contains the javascript chart definition for a d3 Line graph chart.
- * NOTE: this class isn't used just provided as an example as how to create
- * other graph types.
- *
- * @author Mike Thompson
- */
-public final class LineMetricGraph extends AbstractGraph {
-
- /**
- * General constructor for stacked bar graph when you have all the data needed to
- * produce the graph. (This is true for all cases but the dashboard portlet).
- */
- public LineMetricGraph(MetricGraphData metricGraphData) {
- setMetricGraphData(metricGraphData);
- }
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart() /*-{
- console.log("Draw Metric Line jsni chart");
- var global = this,
- chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartId()(),
- chartHandle = "#rChart-"+chartId,
- chartSelection = chartHandle + " svg",
- json = $wnd.jQuery.parseJSON(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getJsonMetrics()()),
- yAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartTitle()(),
- yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getYAxisUnits()(),
- xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getXAxisTitle()();
-
- console.log("chart id: "+chartSelection );
- console.log(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getJsonMetrics()());
-
-
- function draw(data){
- "use strict";
-
- var margin = {top: 10, right: 5, bottom: 30, left: 70},
- width = 400 - margin.left - margin.right,
- height = 150 - margin.top - margin.bottom;
-
- var timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain($wnd.d3.extent(data, function(d) { return d.x; }));
-
- var yScale = $wnd.d3.scale.linear()
- .rangeRound([height, 0])
- .domain([$wnd.d3.min(data.map(function(x) {return x.low;})), $wnd.d3.max(data.map(function(x){return x.high;}))]);
-
- var xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(5)
- .orient("bottom");
-
- var yAxis = $wnd.d3.svg.axis()
- .scale(yScale)
- .ticks(5)
- .orient("left");
-
- var interpolation = "basis";
-
- var line = $wnd.d3.svg.line()
- .interpolate(interpolation)
- .x(function(d) { return timeScale(d.x); })
- .y(function(d) { return yScale(+d.y); });
-
- var highLine = $wnd.d3.svg.line()
- .interpolate(interpolation)
- .x(function(d) { return timeScale(d.x); })
- .y(function(d) { return yScale(+d.high); });
-
- var lowLine = $wnd.d3.svg.line()
- .interpolate(interpolation)
- .x(function(d) { return timeScale(d.x); })
- .y(function(d) { return yScale(+d.low); });
-
- var svg = $wnd.d3.select(chartSelection).append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
- svg.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + height + ")")
- .call(xAxis);
-
-
- svg.append("g")
- .attr("class", "y axis")
- .call(yAxis)
- .append("text")
- .attr("transform", "rotate(-90)")
- .attr("y", -60)
- .attr("dy", ".71em")
- .style("text-anchor", "end")
- .text(yAxisUnits === "NONE" ? "" : yAxisUnits);
-
- console.log("finished axes");
-
- svg.append("path")
- .datum(data)
- .attr("class", "line")
- .attr("fill", "none")
- .attr("stroke", "steelblue")
- .attr("stroke-width", "2")
- .attr("d", line);
-
- svg.append("path")
- .datum(data)
- .attr("class", "highLine")
- .attr("fill", "none")
- .attr("stroke", "red")
- .attr("stroke-width", "1.5")
- //.attr("stroke-dasharray", "20,10,5,5,5,10")
- .attr("stroke-dasharray", "5,5")
- .attr("stroke-opacity", ".3")
- .attr("d", highLine);
-
- svg.append("path")
- .datum(data)
- .attr("class", "lowLine")
- .attr("fill", "none")
- .attr("stroke", "blue")
- .attr("stroke-width", "1.5")
- .attr("stroke-dasharray", "5,5")
- .attr("stroke-opacity", ".3")
- .attr("d", lowLine);
-
- console.log("finished paths");
- }(data);
-
- }-*/;
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java
deleted file mode 100644
index b18e91a..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits;
-import org.rhq.core.domain.measurement.composite.MeasurementOOBComposite;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.JsonMetricProducer;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * The data portion of the graphs making these methods accessible via JSNI to
- * classes extending this and implementing graphs.
- * Provide i18n labels and format the json data for the graph.
- * @see AbstractGraph
- *
- * @author Mike Thompson
- */
-public class MetricGraphData implements JsonMetricProducer {
-
- private static final Integer DEFAULT_CHART_HEIGHT = 200;
- // i18n
- final protected Messages MSG = CoreGUI.getMessages();
- private final String chartTitleMinLabel = MSG.chart_title_min_label();
- private final String chartTitleAvgLabel = MSG.chart_title_avg_label();
- private final String chartTitlePeakLabel = MSG.chart_title_peak_label();
- private final String chartDateLabel = MSG.chart_date_label();
- private final String chartTimeLabel = MSG.chart_time_label();
- private final String chartDownLabel = MSG.chart_down_label();
- private final String chartUnknownLabel = MSG.chart_unknown_label();
- private final String chartNoDataLabel = MSG.chart_no_data_label();
- private final String chartHoverStartLabel = MSG.chart_hover_start_label();
- private final String chartHoverEndLabel = MSG.chart_hover_end_label();
- private final String chartHoverPeriodLabel = MSG.chart_hover_period_label();
- private final String chartHoverBarLabel = MSG.chart_hover_bar_label();
- private final String chartHoverTimeFormat = MSG.chart_hover_time_format();
- private final String chartHoverDateFormat = MSG.chart_hover_date_format();
- private int entityId = 0;
- private String entityName;
- private int definitionId;
- private int portalId;
- private MeasurementUnits adjustedMeasurementUnits;
- private MeasurementDefinition definition;
- private List<MeasurementDataNumericHighLowComposite> metricData;
- private PageList<MeasurementOOBComposite> measurementOOBCompositeList;
- private MeasurementOOBComposite lastOOB;
- private Integer chartHeight;
- private boolean isPortalGraph;
-
-
- private MetricGraphData(int portalId) {
- isPortalGraph = true;
- this.portalId = portalId;
- }
-
- public static MetricGraphData createForDashboard(int portalId){
- return new MetricGraphData(portalId);
- }
-
-
- private MetricGraphData(int entityId, String entityName, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> metricData ) {
- this.entityName = entityName;
- setEntityId(entityId);
- setDefinitionId(def.getId());
- this.definition = def;
- this.metricData = metricData;
- this.isPortalGraph = false;
- }
-
- public static MetricGraphData createForResourceGroup(int groupId, String groupName, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> metricData ){
- return new MetricGraphData(groupId,groupName,def, metricData );
- }
-
- private MetricGraphData(int entityId, String entityName, MeasurementDefinition measurementDef,
- List<MeasurementDataNumericHighLowComposite> metrics,
- PageList<MeasurementOOBComposite> measurementOOBCompositeList ) {
- this.entityName = entityName;
- setEntityId(entityId);
- setDefinitionId(measurementDef.getId());
- this.definition = measurementDef;
- this.metricData = metrics;
- this.measurementOOBCompositeList = measurementOOBCompositeList;
- this.isPortalGraph = false;
- }
-
- public static MetricGraphData createForResource(int resourceId, String resourceName, MeasurementDefinition measurementDef,
- List<MeasurementDataNumericHighLowComposite> metrics,
- PageList<MeasurementOOBComposite> measurementOOBCompositeList ){
- return new MetricGraphData(resourceId, resourceName,measurementDef, metrics, measurementOOBCompositeList);
- }
-
- public int getEntityId() {
- return this.entityId;
- }
-
- public void setEntityId(int entityId) {
- this.entityId = entityId;
- //this.definition = null;
- }
-
-
- public void setEntityName(String entityName) {
- this.entityName = entityName;
- //this.definition = null;
- }
-
- public int getDefinitionId() {
- return definitionId;
- }
-
- public void setDefinitionId(int definitionId) {
- this.definitionId = definitionId;
- //this.definition = null;
- }
-
- public MeasurementDefinition getDefinition() {
- return definition;
- }
-
- public void setDefinition(MeasurementDefinition definition) {
- this.definition = definition;
- }
-
- public String getChartId() {
- if(isPortalGraph){
- if(definition != null){
- return entityId + "-" + definition.getId();
- }else {
- // case when portlet has not been configured yet
- return "";
- }
- }else {
- return entityId + "-" + definitionId;
- }
- }
-
-
- public void setMetricData(List<MeasurementDataNumericHighLowComposite> metricData) {
- this.metricData = metricData;
- }
-
-
- public String getChartTitleMinLabel() {
- return chartTitleMinLabel;
- }
-
- public String getChartTitleAvgLabel() {
- return chartTitleAvgLabel;
- }
-
- public String getChartTitlePeakLabel() {
- return chartTitlePeakLabel;
- }
-
- public String getChartDateLabel() {
- return chartDateLabel;
- }
-
- public String getChartDownLabel() {
- return chartDownLabel;
- }
-
- public String getChartTimeLabel() {
- return chartTimeLabel;
- }
-
- public String getChartUnknownLabel() {
- return chartUnknownLabel;
- }
-
- public String getChartNoDataLabel() {
- return chartNoDataLabel;
- }
-
- public String getChartHoverStartLabel() {
- return chartHoverStartLabel;
- }
-
- public String getChartHoverEndLabel() {
- return chartHoverEndLabel;
- }
-
- public String getChartHoverPeriodLabel() {
- return chartHoverPeriodLabel;
- }
-
- public String getChartHoverBarLabel() {
- return chartHoverBarLabel;
- }
-
- public String getChartHoverTimeFormat() {
- return chartHoverTimeFormat;
- }
-
- public String getChartHoverDateFormat() {
- return chartHoverDateFormat;
- }
-
- public int getPortalId() {
- return portalId;
- }
-
- public Integer getChartHeight() {
- if (null != chartHeight) {
- return chartHeight;
- } else {
-
- return DEFAULT_CHART_HEIGHT;
- }
- }
-
- public void setChartHeight(Integer chartHeight) {
- this.chartHeight = chartHeight;
- }
-
- public boolean isPortalGraph() {
- return isPortalGraph;
- }
-
- public String getChartTitle() {
-
- if(definition != null){
- return (entityName == null) ? definition.getDisplayName() : entityName + " - "+definition.getDisplayName();
- }else {
- // handle case when dashboard portlet has not been configured yet.
- return "";
-
- }
-
- }
-
- /**
- * Returns the y-axis units normalized to highest scale (Bytes -> Gb).
- * NOTE: this requires a dependency such that getJsonMetrics is called
- * before this method as the adjustedMeasurementUnits are calculated in that method.
- * @return yAxisUnits -- normalized to highest UOM.
- */
- public String getYAxisUnits() {
- if (adjustedMeasurementUnits == null) {
- Log.warn("ResourceMetricD3GraphView.adjustedMeasurementUnits is populated by getJsonMetrics. Make sure it is called first.");
- return "";
- } else {
- return adjustedMeasurementUnits.toString();
- }
- }
-
- public String getXAxisTitle() {
- return MSG.view_charts_time_axis_label();
- }
-
- @Override
- /**
- * Format the json for the front JSNI(javascript) UI to consume.
- * @todo: future: this should really use GSON or some Json marshaller
- */
- public String getJsonMetrics() {
- StringBuilder sb = new StringBuilder("[");
- boolean gotAdjustedMeasurementUnits = false;
- if (null != metricData) {
- long firstBarTime = metricData.get(0).getTimestamp();
- long secondBarTime = metricData.get(1).getTimestamp();
- long barDuration = secondBarTime - firstBarTime;
- String barDurationString = MeasurementConverterClient.format((double) barDuration,
- MeasurementUnits.MILLISECONDS, true);
-
- calculateOOB();
-
- for (MeasurementDataNumericHighLowComposite measurement : metricData) {
- sb.append("{ \"x\":" + measurement.getTimestamp() + ",");
-
- if (null != lastOOB) {
- sb.append(" \"baselineMin\":" + lastOOB.getBlMin() + ", ");
- sb.append(" \"baselineMax\":" + lastOOB.getBlMax() + ", ");
- }
-
- if (!Double.isNaN(measurement.getValue())) {
-
- MeasurementNumericValueAndUnits newHigh = normalizeUnitsAndValues(measurement.getHighValue(),
- definition.getUnits());
- MeasurementNumericValueAndUnits newLow = normalizeUnitsAndValues(measurement.getLowValue(),
- definition.getUnits());
- MeasurementNumericValueAndUnits newAvg = normalizeUnitsAndValues(measurement.getValue(),
- definition.getUnits());
- if (!gotAdjustedMeasurementUnits) {
- adjustedMeasurementUnits = newAvg.getUnits();
- gotAdjustedMeasurementUnits = true;
- }
- sb.append(" \"barDuration\": \"" + barDurationString + "\", ");
- sb.append(" \"high\":" + cleanseHigh(newLow.getValue(), newAvg.getValue(),newHigh.getValue()) + ",");
- sb.append(" \"low\":" + cleanseLow(newLow.getValue(), newAvg.getValue(), newHigh.getValue()) + ",");
- sb.append(" \"y\":" + newAvg.getValue() + "},");
- } else {
- // give it some values so that we dont have NaN
- sb.append(" \"high\":0,");
- sb.append(" \"low\":0,");
- sb.append(" \"y\":0,");
- sb.append(" \"nodata\":true },");
- }
- if (!sb.toString().endsWith("},")) {
- sb.append(" },");
- }
- }
- sb.setLength(sb.length() - 1); // delete the last ','
- }
- sb.append("]");
- Log.debug("Json data for: "+getChartTitle());
- Log.debug(sb.toString());
- return sb.toString();
- }
-
- /**
- * This is cleaning the data as sometimes the data coming from the metric query
- * is erroneous: for instance the low is greater than the high. This causes the
- * geometries to get weird. We normally should not have to do this!
- * @todo: Remove this data cleansing once we have fixed it at the metric query.
- *
- * @param low supposed low value
- * @param high supposed high value
- * @return the real high value
- */
- private Double cleanseHigh(Double low, Double avg, Double high){
- double highLowMax = Math.max(low, high);
- return Math.max(highLowMax, avg);
- }
-
- private Double cleanseLow(Double low, Double avg, Double high){
- double highLowMin = Math.min(low, high);
- return Math.min(highLowMin, avg);
- }
-
- /**
- * When the scale is adjusted down to a level where bars no longer have
- * highs and lows different from the avg value then have probably hit a
- * scale where aggregates no longer exist and we are looking the individual
- * values. At the very least the data is less interesting and a trendline
- * connecting the points has less meaning because we are essentially a scatterplot.
- * A different algorithm could be used here but this will suffice.
- * @return true if the graphs should show the bar avg line meaning there is aggregates in the data
- * @see StackedBarMetricGraphImpl
- */
- public boolean showBarAvgTrendLine() {
- for (MeasurementDataNumericHighLowComposite measurement : metricData) {
- boolean noValuesInCurrentBarUndefined = (!Double.isNaN(measurement.getValue()) && !Double.isNaN(measurement.getHighValue()) && !Double.isNaN(measurement.getLowValue()));
- boolean foundAggregateBar = (measurement.getValue() != measurement.getHighValue() || measurement.getHighValue() != measurement.getLowValue());
- // if there exists a even one aggregate bar then I can short circuit this and exit
- if (noValuesInCurrentBarUndefined && foundAggregateBar){
- return true;
- }
- }
- return false;
-
- }
-
- private void calculateOOB() {
- if (measurementOOBCompositeList != null && !measurementOOBCompositeList.isEmpty()) {
- Log.debug("OOB List size: " + measurementOOBCompositeList.size());
- List<MeasurementOOBComposite> selectedOOBs = new ArrayList<MeasurementOOBComposite>();
- for (MeasurementOOBComposite measurementOOBComposite : measurementOOBCompositeList) {
- Log.debug("measurementOOBComposite = " + measurementOOBComposite);
- if (measurementOOBComposite.getDefinitionId() == definitionId) {
- selectedOOBs.add(measurementOOBComposite);
- }
- }
- // take the last one (most current) matching the defId
- lastOOB = selectedOOBs.isEmpty() ? null : selectedOOBs.get(selectedOOBs.size() - 1);
- } else {
- lastOOB = null;
- }
- }
-
-
- private MeasurementNumericValueAndUnits normalizeUnitsAndValues(double value, MeasurementUnits measurementUnits) {
- MeasurementNumericValueAndUnits newValue = MeasurementConverterClient.fit(value, measurementUnits);
- MeasurementNumericValueAndUnits returnValue;
-
- // adjust for percentage numbers
- if (measurementUnits.equals(MeasurementUnits.PERCENTAGE)) {
- returnValue = new MeasurementNumericValueAndUnits(newValue.getValue() * 100, newValue.getUnits());
- } else {
- returnValue = new MeasurementNumericValueAndUnits(newValue.getValue(), newValue.getUnits());
- }
-
- return returnValue;
- }
-
-
-
- /**
- * If there is more than 2 days time window then return true so we can show day of week
- * in axis labels. Function to switch the timescale to whichever is more appropriate hours
- * or hours with days of week.
- * @return true if difference between startTime and endTime is >= x days
- */
- public boolean shouldDisplayDayOfWeekInXAxisLabel() {
- Long startTime = metricData.get(0).getTimestamp();
- Long endTime = metricData.get(metricData.size() - 1).getTimestamp();
- long timeThreshold = 24 * 60 * 60 * 1000; // 1 days
- return startTime + timeThreshold < endTime;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("MetricGraphData");
- sb.append("{chartTitleMinLabel='").append(chartTitleMinLabel).append('\'');
- sb.append(", chartTitleAvgLabel='").append(chartTitleAvgLabel).append('\'');
- sb.append(", chartTitlePeakLabel='").append(chartTitlePeakLabel).append('\'');
- sb.append(", chartDateLabel='").append(chartDateLabel).append('\'');
- sb.append(", chartTimeLabel='").append(chartTimeLabel).append('\'');
- sb.append(", chartDownLabel='").append(chartDownLabel).append('\'');
- sb.append(", chartUnknownLabel='").append(chartUnknownLabel).append('\'');
- sb.append(", chartNoDataLabel='").append(chartNoDataLabel).append('\'');
- sb.append(", chartHoverStartLabel='").append(chartHoverStartLabel).append('\'');
- sb.append(", chartHoverEndLabel='").append(chartHoverEndLabel).append('\'');
- sb.append(", chartHoverPeriodLabel='").append(chartHoverPeriodLabel).append('\'');
- sb.append(", chartHoverBarLabel='").append(chartHoverBarLabel).append('\'');
- sb.append(", chartHoverTimeFormat='").append(chartHoverTimeFormat).append('\'');
- sb.append(", chartHoverDateFormat='").append(chartHoverDateFormat).append('\'');
- sb.append(", entityId=").append(entityId);
- sb.append(", entityName='").append(entityName).append('\'');
- sb.append(", definitionId=").append(definitionId);
- sb.append(", isPortalGraph=").append(isPortalGraph);
- sb.append('}');
- return sb.toString();
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3MultiLineGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3MultiLineGraph.java
deleted file mode 100644
index 4928522..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3MultiLineGraph.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-/**
- * Contains the chart definition for a MultiLine Graph.
- *
- * @author Mike Thompson
- */
-public final class MetricNvd3MultiLineGraph extends AbstractGraph
-{
- /**
- * General constructor for stacked bar graph when you have all the data needed to
- * produce the graph. (This is true for all cases but the dashboard portlet).
- */
- public MetricNvd3MultiLineGraph(MetricGraphData metricGraphData){
- setMetricGraphData(metricGraphData);
- }
-
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart() /*-{
- console.log("Draw NVD3 Bar jsni chart");
- console.time("multiChart");
- var global = this,
- chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartId()(),
- chartHandle = "#rChart-"+chartId,
- chartSelection = chartHandle + " svg",
- json = $wnd.jQuery.parseJSON(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getJsonMetrics()()),
- yAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartTitle()(),
- yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getYAxisUnits()(),
- xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getXAxisTitle()(),
- displayDayOfWeek = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::shouldDisplayDayOfWeekInXAxisLabel()(),
- xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I : %M %p",
-
- // nvd3 defines their json models a standard way (same model for other graphs)
- data = function() {
- return [
- {
- values: json,
- key: yAxisLabel ,
- color: '#ff7f0e'
- }
- ];
- };
- $wnd.nv.addGraph(function() {
- var chart = $wnd.nv.models.multiBarChart()
- .showControls(true)
- .tooltips(true);
-
- chart.xAxis.axisLabel(xAxisLabel)
- .tickFormat(function(d) { return $wnd.d3.time.format(xAxisTimeFormat)(new Date(d)) });
-
- chart.yAxis
- .axisLabel(yAxisUnits)
- .tickFormat($wnd.d3.format(',f'));
-
- $wnd.d3.select(chartSelection)
- .datum(data())
- .transition().duration(300)
- .call(chart);
-
- $wnd.nv.utils.windowResize(chart.update);
-
- return chart;
- });
- console.timeEnd("multiChart")
-
- }-*/;
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
deleted file mode 100644
index 75ce6e3..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-/**
- * Contains the javascript chart definition for an IE8 d3 Stacked Bar graph chart.
- * Curr
- *
- * @author Mike Thompson
- */
-public final class StackedBarMetricGraphIE8Impl extends StackedBarMetricGraphImpl {
-
- /**
- * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
- * for all cases but the dashboard portlet).
- */
- public StackedBarMetricGraphIE8Impl() {
- super();
- }
-
-
- /**
- * Empty implementation for IE8.
- */
- @Override
- public native void drawJsniChart() /*-{
- // no-op implementation for ie8
- }-*/;
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
deleted file mode 100644
index 4d71192..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-/**
- * Contains the javascript chart definition for a d3 Stacked Bar graph chart.
- *
- * @author Mike Thompson
- */
-public class StackedBarMetricGraphImpl extends AbstractGraph {
-
- /**
- * GWT constructor for GWT.create() deferred instantiation.
- */
- public StackedBarMetricGraphImpl() {
- super();
- }
-
-
- /**
- * The magic JSNI to draw the charts with $wnd.d3.js
- */
- @Override
- public native void drawJsniChart() /*-{
- console.log("Draw Stacked Bar jsni chart");
- var global = this,
-
- // create a chartContext object (from rhq.js) with the data required to render to a chart
- // this same data could be passed to different chart types
- // This way, we are decoupled from the dependency on globals and JSNI and kept all the java interaction right here.
- chartContext = new $wnd.ChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartId()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartHeight()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getJsonMetrics()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getXAxisTitle()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartTitle()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getYAxisUnits()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartTitleMinLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartTitleAvgLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartTitlePeakLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartDateLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartTimeLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartDownLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartUnknownLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartNoDataLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartHoverEndLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartHoverPeriodLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartHoverBarLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getChartHoverDateFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::isPortalGraph()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::getPortalId()()
- );
-
-
- // Define the Stacked Bar Graph function using the module pattern
- var metricStackedBarGraph = function () {
- "use strict";
- // privates
- var margin = {top: 10, right: 5, bottom: 5, left: 40},
- width = 750 - margin.left - margin.right,
- adjustedChartHeight = chartContext.chartHeight - 50,
- height = adjustedChartHeight - margin.top - margin.bottom,
- smallChartThresholdInPixels = 600,
- titleHeight = 30, titleSpace = 10,
- barOffset = 2,
- chartData,
- interpolation = "basis",
- avg, min, peak,
- oobMax,
- determineLowBound,
- lowBound,
- highBound,
- calcBarWidth,
- yScale,
- yAxis,
- timeScale,
- xAxis,
- chart,
- svg;
-
- function isIEBrowserGreaterThanOrEqualTo(targetIEVersion){
- var myUserAgent = $wnd.navigator.userAgent;
- if (/MSIE (\d+\.\d+);/.test(myUserAgent)){ //test for MSIE x.x;
- var ieVersion=new Number(RegExp.$1); // capture x.x portion and store as a number
- if (ieVersion>=targetIEVersion){
- return true;
- }
- }
- return false;
- }
-
- function getChartWidth() {
- return $wnd.jQuery("#" + chartContext.chartHandle).width();
- }
-
- function useSmallCharts() {
- return getChartWidth() <= smallChartThresholdInPixels;
- }
-
- function determineScale() {
- var xTicks, xTickSubDivide, numberOfBarsForSmallGraph = 20;
- if (chartContext.data.length > 0) {
-
- // if window is too small server up small chart
- if (useSmallCharts()) {
- console.log("Using Small Charts Profile for width: "+getChartWidth());
- width = 250;
- xTicks = 3;
- xTickSubDivide = 2;
- chartData = chartContext.data.slice(chartContext.data.length - numberOfBarsForSmallGraph, chartContext.data.length - 1);
- }
- else {
- console.log("Using Large Charts Profile");
- // we use the width already defined above
- xTicks = 8;
- xTickSubDivide = 5;
- chartData = chartContext.data;
- }
-
- avg = $wnd.d3.mean(chartContext.data.map(function (d) {
- return d.y;
- }));
- peak = $wnd.d3.max(chartContext.data.map(function (d) {
- if (d.high != undefined) {
- return d.high;
- }
- else {
- return 0;
- }
- }));
- min = $wnd.d3.min(chartContext.data.map(function (d) {
- if (d.low != undefined) {
- return d.low;
- }
- else {
- return Number.MAX_VALUE;
- }
- }));
- // adjust the min scale so blue low line is not in axis
- determineLowBound = function (min, peak) {
- var newLow = min - ((peak - min) * 0.1);
- if (newLow < 0) {
- return 0;
- }
- else {
- return newLow;
- }
- };
- lowBound = determineLowBound(min, peak);
- highBound = peak + ((peak - min) * 0.1);
- oobMax = $wnd.d3.max(chartContext.data.map(function (d) {
- if (d.baselineMax == undefined) {
- return 0;
- }
- else {
- return +d.baselineMax;
- }
- }));
- calcBarWidth = function () {
- return (width / chartData.length - barOffset )
- };
-
- yScale = $wnd.d3.scale.linear()
- .clamp(true)
- .rangeRound([height, 0])
- .domain([lowBound, highBound]);
- yAxis = $wnd.d3.svg.axis()
- .scale(yScale)
- .tickSubdivide(1)
- .ticks(5)
- .tickSize(4, 4, 0)
- .orient("left");
-
-
- timeScale = $wnd.d3.time.scale()
- .range([0, width])
- .domain($wnd.d3.extent(chartData, function (d) {
- return d.x;
- }));
-
- xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(xTicks)
- .tickSubdivide(xTickSubDivide)
- .tickSize(4, 4, 0)
- .orient("bottom");
-
- // create the actual chart group
- chart = $wnd.d3.select("#" + chartContext.chartSelection);
-
- svg = chart.append("g")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top - titleHeight - titleSpace + margin.bottom)
- .attr("transform", "translate(" + margin.left + "," + (+titleHeight + titleSpace + margin.top) + ")");
-
- if (!useSmallCharts()) {
- createMinAvgPeakSidePanel(chartContext.minChartTitle, min, chartContext.avgChartTitle, avg, chartContext.peakChartTitle, peak, chartContext.yAxisUnits);
- }
- }
-
- }
-
-
- function createMinAvgPeakSidePanel(minLabel, minValue, avgLabel, avgValue, highLabel, highValue, uom) {
- var xLabel = 772,
- xValue = 820,
- yBase = 100,
- yInc = 25,
- decimalPlaces = 0;
-
- // title/header
- chart.append("g").append("rect")
- .attr("class", "rightSidePanel")
- .attr("x", xLabel - 10)
- .attr("y", margin.top + 70)
- .attr("rx", 10)
- .attr("ry", 10)
- .attr("height", 80)
- .attr("width", 135)
- .attr("opacity", "0.3")
- .attr("fill", "#E8E8E8");
-
- // high
- chart.append("text")
- .attr("class", "highLabel")
- .attr("x", xLabel)
- .attr("y", yBase)
- .text(highLabel + " - ");
-
- chart.append("text")
- .attr("class", "highText")
- .attr("x", xValue)
- .attr("y", yBase)
- .text(highValue.toFixed(decimalPlaces) + " " + uom);
-
-
- //avg
- chart.append("text")
- .attr("class", "avgLabel")
- .attr("x", xLabel)
- .attr("y", yBase + yInc)
- .text(avgLabel + " - ");
-
- chart.append("text")
- .attr("class", "avgText")
- .attr("x", xValue)
- .attr("y", yBase + yInc)
- .text(avgValue.toFixed(decimalPlaces) + " " + uom);
-
- // min
- chart.append("text")
- .attr("class", "minLabel")
- .attr("x", xLabel)
- .attr("y", yBase + 2 * yInc)
- .text(minLabel + " - ");
-
- chart.append("text")
- .attr("class", "minText")
- .attr("x", xValue)
- .attr("y", yBase + 2 * yInc)
- .text(minValue.toFixed(decimalPlaces) + " " + uom);
-
-
- }
-
- function createHeader(titleName) {
- var title = chart.append("g").append("rect")
- .attr("class", "title")
- .attr("x", 10)
- .attr("y", margin.top)
- .attr("height", titleHeight)
- .attr("width", width + 30 + margin.left)
- .attr("fill", "none");
-
- chart.append("text")
- .attr("class", "titleName")
- .attr("x", 40)
- .attr("y", 37)
- .attr("font-size", "12")
- .attr("font-weight", "bold")
- .attr("text-anchor", "left")
- .text(titleName)
- .attr("fill", "#003168");
-
- return title;
-
- }
-
- function createStackedBars() {
-
- var pixelsOffHeight = 0;
-
- // The gray bars at the bottom leading up
- svg.selectAll("rect.leaderBar")
- .data(chartData)
- .enter().append("rect")
- .attr("class", "leaderBar")
- .attr("x", function (d) {
- return timeScale(d.x);
- })
- .attr("y", function (d) {
- if (d.down || d.unknown || d.nodata) {
- return yScale(highBound);
- }
- else {
- return yScale(d.low);
- }
- })
- .attr("height", function (d) {
- if (d.down || d.unknown || d.nodata) {
- return height - yScale(highBound) - pixelsOffHeight;
- }
- else {
- return height - yScale(d.low) - pixelsOffHeight;
- }
- })
- .attr("width", function () {
- return calcBarWidth();
- })
-
- .attr("opacity", ".9")
- .attr("fill", function (d) {
- if (d.down || d.unknown || d.nodata) {
- return "url(#noDataStripes)";
- }
- else {
- return "#d3d3d6";
- }
- });
-
-
- // upper portion representing avg to high
- svg.selectAll("rect.high")
- .data(chartData)
- .enter().append("rect")
- .attr("class", "high")
- .attr("x", function (d) {
- return timeScale(d.x);
- })
- .attr("y", function (d) {
- return isNaN(d.high) ? yScale(lowBound) : yScale(d.high);
- })
- .attr("height", function (d) {
- if (d.down || d.unknown || d.nodata) {
- return height - yScale(lowBound);
- }
- else {
- return yScale(d.y) - yScale(d.high);
- }
- })
- .attr("width", function () {
- return calcBarWidth();
- })
- .attr("data-rhq-value", function (d) {
- return d.y;
- })
- .attr("opacity", 0.9);
-
-
- // lower portion representing avg to low
- svg.selectAll("rect.low")
- .data(chartData)
- .enter().append("rect")
- .attr("class", "low")
- .attr("x", function (d) {
- return timeScale(d.x);
- })
- .attr("y", function (d) {
- return isNaN(d.y) ? height : yScale(d.y);
- })
- .attr("height", function (d) {
- if (d.down || d.unknown || d.nodata) {
- return height - yScale(lowBound);
- }
- else {
- return yScale(d.low) - yScale(d.y);
- }
- })
- .attr("width", function () {
- return calcBarWidth();
- })
- .attr("opacity", 0.9);
-
- // if high == low put a "cap" on the bar to show non-aggregated bar
- svg.selectAll("rect.singleValue")
- .data(chartData)
- .enter().append("rect")
- .attr("class", "singleValue")
- .attr("x", function (d) {
- return timeScale(d.x);
- })
- .attr("y", function (d) {
- return isNaN(d.y) ? height : yScale(d.y) - 2;
- })
- .attr("height", function (d) {
- if (d.down || d.unknown || d.nodata) {
- return height - yScale(lowBound);
- }
- else {
- if (d.low === d.high) {
- return yScale(d.low) - yScale(d.y) + 2;
- }
- else {
- return yScale(d.low) - yScale(d.y);
- }
- }
- })
- .attr("width", function () {
- return calcBarWidth();
- })
- .attr("opacity", 0.9)
- .attr("fill", function (d) {
- if (d.low === d.high) {
- return "#50505a";
- }
- else {
- return "#70c4e2";
- }
- });
- }
-
- function createYAxisGridLines() {
- // create the y axis grid lines
- svg.append("g").classed("grid y_grid", true)
- .call($wnd.d3.svg.axis()
- .scale(yScale)
- .orient("left")
- .ticks(10)
- .tickSize(-width, 0, 0)
- .tickFormat("")
- );
- }
-
- function createXandYAxes() {
-
- // create x-axis
- svg.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
-
-
- // create y-axis
- svg.append("g")
- .attr("class", "y axis")
- .call(yAxis)
- .append("text")
- .attr("transform", "rotate(-90),translate( -60,0)")
- .attr("y", -30)
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .text(chartContext.yAxisUnits === "NONE" ? "" : chartContext.yAxisUnits);
-
- }
-
- function createAvgLines() {
- var showBarAvgTrendline =
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AbstractGraph::showBarAvgTrendLine()(),
- barAvgLine = $wnd.d3.svg.line()
- .interpolate("linear")
- .defined(function (d) {
- return !d.nodata;
- })
- .x(function (d) {
- return timeScale(d.x) + (calcBarWidth() / 2);
- })
- .y(function (d) {
- if (showBarAvgTrendline) {
- return yScale(d.y);
- }
- else {
- return yScale(0);
- }
- });
-
- // Bar avg line
- svg.append("path")
- .datum(chartData)
- .attr("class", "barAvgLine")
- .attr("fill", "none")
- .attr("stroke", "#2e376a")
- .attr("stroke-width", "1.5")
- .attr("stroke-opacity", ".7")
- .attr("d", barAvgLine);
-
- }
-
- function createOOBLines() {
-
- var minBaselineLine = $wnd.d3.svg.line()
- .interpolate(interpolation)
- .x(function (d) {
- return timeScale(d.x);
- })
- .y(function (d) {
- return yScale(d.baselineMin);
- }),
- maxBaselineLine = $wnd.d3.svg.line()
- .interpolate(interpolation)
- .x(function (d) {
- return timeScale(d.x);
- })
- .y(function (d) {
- return yScale(d.baselineMax);
- });
-
- // min baseline Line
- svg.append("path")
- .datum(chartData)
- .attr("class", "minBaselineLine")
- .attr("fill", "none")
- .attr("stroke", "purple")
- .attr("stroke-width", "1")
- .attr("stroke-dasharray", "20,10,5,5,5,10")
- .attr("stroke-opacity", ".9")
- .attr("d", minBaselineLine);
-
- // max baseline Line
- svg.append("path")
- .datum(chartData)
- .attr("class", "maxBaselineLine")
- .attr("fill", "none")
- .attr("stroke", "orange")
- .attr("stroke-width", "1")
- .attr("stroke-dasharray", "20,10,5,5,5,10")
- .attr("stroke-opacity", ".7")
- .attr("d", maxBaselineLine);
-
- }
-
- function formatHovers(chartContext, d) {
- var hoverString,
- xValue = (d.x == undefined) ? 0 : +d.x,
- date = new Date(+xValue),
- barDuration = d.barDuration,
- timeFormatter = $wnd.d3.time.format(chartContext.chartHoverTimeFormat),
- dateFormatter = $wnd.d3.time.format(chartContext.chartHoverDateFormat),
- highValue = d.high.toFixed(2),
- lowValue = d.low.toFixed(2),
- avgValue = d.y.toFixed(2);
-
-
- // our special condition to indicate no data because avg lines dont like discontinuous data
- if (d.y === 0 && d.high === 0 && d.low === 0) {
- // no data
- hoverString =
- '<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel" >' + chartContext.timeLabel + ': </span>' + timeFormatter(date) +
- '<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span>' + dateFormatter(date) + '</div>' +
- '<hr class="chartHoverDivider" ></hr>' +
- '<div class="chartHoverAlignRight"><span class="chartHoverLabelSpan">' + chartContext.noDataLabel + '</span></div>' +
- '</div>';
-
-
- }
- else {
- // regular bar hover
- hoverString =
- '<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel">' + chartContext.timeLabel + ': </span><span style="width:50px;">' + timeFormatter(date) + '</span>' +
- '<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span><span style="width:50px;">' + dateFormatter(date) + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span class="chartHoverLabelSpan">' + chartContext.hoverBarLabel + ": " + barDuration + '</span></div>' +
- '<hr class="chartHoverDivider"></hr>' +
- '<div class="chartHoverAlignRight"><span id="chartHoverPeakValue" >' + chartContext.peakChartTitle + ': </span><span style="width:50px;">' + highValue + '</span></div>' +
- '<div class="chartHoverAlignRight"><span id="chartHoverAvgValue" >' + chartContext.avgChartTitle + ': </span><span style="width:50px;">' + avgValue + '</span></div>' +
- '<div class="chartHoverAlignRight"><span id="chartHoverLowValue" >' + chartContext.minChartTitle + ': </span><span style="width:50px;">' + lowValue + '</span></div>' +
- '</div>';
- }
- return hoverString;
-
- }
-
- function createHovers(chartContext) {
- $wnd.jQuery('svg rect.leaderBar, svg rect.high, svg rect.low, svg rect.singleValue').tipsy({
- gravity: 'w',
- html: true,
- trigger: 'hover',
- title: function () {
- var d = this.__data__;
- return formatHovers(chartContext, d);
- },
- show: function (e, el) {
- el.css({ 'z-index': '990000'})
- }
- });
- }
-
- return {
- // Public API
- draw: function (chartContext) {
- "use strict";
- // Guard condition that can occur when a portlet has not been configured yet
- if (chartContext.data.length > 0) {
- console.log("Creating Chart: "+ chartContext.chartSelection + " --> "+ chartContext.chartTitle);
-
- determineScale();
- createHeader(chartContext.chartTitle);
-
- createYAxisGridLines();
- createStackedBars();
- createXandYAxes();
- createAvgLines();
- if (oobMax > 0) {
- console.log("OOB Data Exists!");
- createOOBLines();
- }
- createHovers(chartContext);
- }
- }
- }; // end public closure
- }();
-
- metricStackedBarGraph.draw(chartContext);
-
- }-*/;
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractGraph.java
new file mode 100644
index 0000000..6498f65
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AbstractGraph.java
@@ -0,0 +1,174 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+
+import com.smartgwt.client.widgets.layout.VLayout;
+
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+
+/**
+ * Common Graph capability used across multiple graphs.
+ * The MetricGraphData delegate is wrapped for JSNI access via d3 charts.
+ * Also, by delegating and directly extending MetricGraphData we have more
+ * control over the visibility of what we want graphs to 'see'.
+ *
+ * @see MetricGraphData
+ *
+ * @author Mike Thompson
+ */
+public abstract class AbstractGraph extends VLayout implements HasD3MetricJsniChart {
+
+ private MetricGraphData metricGraphData;
+
+ public MetricGraphData getMetricGraphData() {
+ return metricGraphData;
+ }
+
+ public void setMetricGraphData(MetricGraphData metricGraphData) {
+ this.metricGraphData = metricGraphData;
+ }
+
+ public int getEntityId() {
+ return metricGraphData.getEntityId();
+ }
+
+ @Override
+ public void setEntityId(int entityId) {
+ metricGraphData.setEntityId(entityId);
+ }
+
+
+ @Override
+ public void setEntityName(String entityName) {
+ metricGraphData.setEntityName(entityName);
+ }
+
+ public int getDefinitionId() {
+ return metricGraphData.getDefinitionId();
+ }
+
+ public MeasurementDefinition getDefinition() {
+ return metricGraphData.getDefinition();
+ }
+
+ @Override
+ public void setDefinition(MeasurementDefinition definition) {
+ metricGraphData.setDefinition(definition);
+ }
+
+ public String getChartId() {
+ return metricGraphData.getChartId();
+ }
+
+ public boolean showBarAvgTrendLine(){
+ return metricGraphData.showBarAvgTrendLine();
+ }
+
+ public String getChartTitleMinLabel() {
+ return metricGraphData.getChartTitleMinLabel();
+ }
+
+ public String getChartTitleAvgLabel() {
+ return metricGraphData.getChartTitleAvgLabel();
+ }
+
+ public String getChartTitlePeakLabel() {
+ return metricGraphData.getChartTitlePeakLabel();
+ }
+
+ public String getChartDateLabel() {
+ return metricGraphData.getChartDateLabel();
+ }
+
+ public String getChartDownLabel() {
+ return metricGraphData.getChartDownLabel();
+ }
+
+ public String getChartTimeLabel() {
+ return metricGraphData.getChartTimeLabel();
+ }
+
+ public String getChartUnknownLabel() {
+ return metricGraphData.getChartUnknownLabel();
+ }
+
+ public String getChartNoDataLabel() {
+ return metricGraphData.getChartNoDataLabel();
+ }
+
+ public String getChartHoverStartLabel() {
+ return metricGraphData.getChartHoverStartLabel();
+ }
+
+ public String getChartHoverEndLabel() {
+ return metricGraphData.getChartHoverEndLabel();
+ }
+
+ public String getChartHoverPeriodLabel() {
+ return metricGraphData.getChartHoverPeriodLabel();
+ }
+
+ public String getChartHoverBarLabel() {
+ return metricGraphData.getChartHoverBarLabel();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return metricGraphData.getChartHoverTimeFormat();
+ }
+
+ public String getChartHoverDateFormat() {
+ return metricGraphData.getChartHoverDateFormat();
+ }
+
+
+ public int getChartHeight() {
+ return metricGraphData.getChartHeight();
+ }
+
+ public void setChartHeight(Integer chartHeight) {
+ metricGraphData.setChartHeight(chartHeight);
+ }
+
+ public String getChartTitle() {
+ return metricGraphData != null ? metricGraphData.getChartTitle() : "";
+ }
+ public boolean isPortalGraph(){
+ return metricGraphData.isPortalGraph();
+ }
+
+
+ public String getYAxisUnits() {
+ return metricGraphData.getYAxisUnits();
+ }
+
+ public String getXAxisTitle() {
+ return metricGraphData.getXAxisTitle();
+ }
+
+ public String getJsonMetrics() {
+ return metricGraphData.getJsonMetrics();
+ }
+
+ public int getPortalId() {
+ return metricGraphData.getPortalId();
+ }
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AvailabilityGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AvailabilityGraphType.java
new file mode 100644
index 0000000..9360ad3
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/AvailabilityGraphType.java
@@ -0,0 +1,44 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import java.util.List;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+
+/**
+ * Contract for an Availability Graph Implementation. This gives the ability for
+ * Availability graphs to swap implementations giving different chart types.
+ *
+ * @author Mike Thompson
+ */
+public interface AvailabilityGraphType {
+
+ void setAvailabilityList(List<Availability> availabilityList);
+
+ void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList);
+
+ String getAvailabilityJson();
+
+ String getChartId();
+
+ void drawJsniChart();
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
new file mode 100644
index 0000000..17dd595
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/GraphDateTimeRangeEditor.java
@@ -0,0 +1,193 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import com.google.gwt.user.client.Timer;
+import com.smartgwt.client.widgets.HTMLFlow;
+
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+
+/**
+ * Component to allow selection of Date/Time range for graphs using a button group from bootstrap.
+ *
+ * @author Mike Thompson
+ */
+public class GraphDateTimeRangeEditor extends EnhancedVLayout {
+
+ private JQueryDateTimeRangeEditor graphDateTimeRangeEditor;
+ private MeasurementUserPreferences measurementUserPreferences;
+
+
+ public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs) {
+ this.measurementUserPreferences = measurementUserPrefs;
+ this.graphDateTimeRangeEditor = new JQueryDateTimeRangeEditor();
+ }
+
+ /**
+ * Setup the page elements especially the div and svg elements that serve as
+ * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
+ * Later the drawJsniGraph() is called to actually fill in the div/svg element
+ * created here with the actual svg element.
+ * NOTE: auxiliary javascript functions in rhq.js
+ *
+ */
+ public void createGraphMarker() {
+ Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
+
+ // append the bootstrap buttongroup since smartGWT doesn't have one
+ StringBuilder divAndSvgDefs = new StringBuilder();
+ divAndSvgDefs.append("<div id=\"graphDateTimeRangeEditor\">" +
+ "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:875px;>\n" +
+ " <div class=\"accordion-group\">\n" +
+ " \n" +
+ " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">\n" +
+ " <div class=\"accordion-inner\">\n" +
+ " <span class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
+ " <button id=\"radioMin\" type=\"button\" class=\"btn \" >Min</button>\n" +
+ " <button id=\"radioHour\" type=\"button\" class=\"btn \">Hour</button>\n" +
+ " <button id=\"radioWeek\" type=\"button\" class=\"btn \">Week</button>\n" +
+ " <button id=\"radioMonth\" type=\"button\" class=\"btn \">Month</button>\n" +
+ " <button id=\"radioYear\" type=\"button\" class=\"btn \">Year</button>\n" +
+ " </span>\n" +
+ " <input id=\"dateRange\" style=\"margin-left:30px;width:280px;\" type=\"text\" readonly=\"readonly\" />\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n"+
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
+ divAndSvgDefs.append("</svg></div>");
+ HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
+ graph.setWidth100();
+ graph.setHeight(65);
+ addMember(graph);
+ new Timer(){
+ @Override
+ public void run() {
+ attachGraphDateRangeEditorButtonGroupHandlers();
+ }
+ }.schedule(400);
+ }
+
+ public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
+ console.log("Draw GraphDateTimeRangeEditor");
+
+ function updateDateDisplay(startDate, endDate ) {
+ var formattedDateRange;
+
+ if (isSameDay(startDate, endDate) && isSameMonth(startDate, endDate) && isSameYear(startDate, endDate)) {
+ // no need to display date only time
+ formattedDateRange = startDate.format('ddd') + ': ' + startDate.format('h:mm a') + ' - ' + endDate.format('h:mm a');
+ } else {
+ formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ }
+ $wnd.jQuery('#dateRange').val(formattedDateRange);
+ }
+
+ function isSameDay(startDate, endDate) {
+ return (startDate.date() === endDate.date());
+ }
+ function isSameMonth(startDate, endDate) {
+ return (startDate.month() === endDate.month());
+ }
+ function isSameYear(startDate, endDate) {
+ return (startDate.year() === endDate.year());
+ }
+
+ var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
+
+
+ $wnd.jQuery("#radioMin").bind('click', function (event) {
+ console.log("minute selected");
+ graphDateContext.startDate = $wnd.moment().startOf('hour');
+ updateDateDisplay(graphDateContext);
+ });
+ $wnd.jQuery("#radioHour").bind('click', function (event) {
+ console.log("Hour selected");
+ graphDateContext.startDate = $wnd.moment().startOf('hour');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioWeek").bind('click', function (event) {
+ console.log("Week selected");
+ graphDateContext.startDate = $wnd.moment().startOf('week');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioMonth").bind('click', function (event) {
+ console.log("month selected");
+ graphDateContext.startDate = $wnd.moment().startOf('month');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioYear").bind('click', function (event) {
+ console.log("year selected");
+ graphDateContext.startDate = $wnd.moment().startOf('year');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+
+ // initially populate
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ $wnd.jQuery("#radioHour").click();
+
+ }-*/;
+
+ public native void refreshGraphs() /*-{
+
+ }-*/;
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ removeMembers(getMembers());
+ createGraphMarker();
+ }
+
+ @Override
+ public void parentResized() {
+ super.parentResized();
+ removeMembers(getMembers());
+ createGraphMarker();
+ drawJsniChart();
+ }
+
+
+ /**
+ * Delegate the call to rendering the JSNI chart.
+ * This way the chart type can be swapped out at any time.
+ */
+ public void drawJsniChart() {
+ graphDateTimeRangeEditor.drawJsniChart();
+ }
+
+
+ public Long getStartTime() {
+ return measurementUserPreferences.getMetricRangePreferences().begin;
+ }
+
+// public void setStartTime(Long startTime) {
+// this.startTime = startTime;
+// }
+
+ public Long getEndTime() {
+ return measurementUserPreferences.getMetricRangePreferences().end;
+ }
+
+// public void setEndTime(Long endTime) {
+// this.endTime = endTime;
+// }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/HasD3MetricJsniChart.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/HasD3MetricJsniChart.java
new file mode 100644
index 0000000..909be29
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/HasD3MetricJsniChart.java
@@ -0,0 +1,38 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+
+/**
+ * Defines GWT JSNI charting capability. Indicator of a class producing
+ * d3 (javascript) charts. Allows us to quickly find, in a standard
+ * way JSNI charts like d3. Finding implementations of this class
+ * will reveal all the d3 charting implementations.
+ *
+ * @author Mike Thompson
+ */
+public interface HasD3MetricJsniChart
+{
+ void drawJsniChart();
+ void setEntityId(int entityId) ;
+ void setEntityName(String entityName) ;
+ void setDefinition(MeasurementDefinition measurementDefinition) ;
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/JQueryDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/JQueryDateTimeRangeEditor.java
new file mode 100644
index 0000000..5266e7f
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/JQueryDateTimeRangeEditor.java
@@ -0,0 +1,261 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+
+/**
+ * An implementation using JQuery UI components because smartGWT doesn't contain buttonsets or dual range sliders.
+ *
+ * @author Mike Thompson
+ */
+@Deprecated
+public class JQueryDateTimeRangeEditor {
+ private static Messages MSG = CoreGUI.getMessages();
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw GraphDateTimeRangeEditor");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(8)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.log("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+ })
+ .attr("height", function (d) {
+ return 10;
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("fill", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text(availChartContext.chartTitle);
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartUpLabel);
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartDownLabel);
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart);
+
+ return '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+
+ }
+
+ return {
+ // Public API
+ draw: function (availChartContext) {
+ "use strict";
+ console.log("AvailabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java
new file mode 100644
index 0000000..45d0aba
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/MetricGraphData.java
@@ -0,0 +1,454 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
+import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementOOBComposite;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.JsonMetricProducer;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+/**
+ * The data portion of the graphs making these methods accessible via JSNI to
+ * classes extending this and implementing graphs.
+ * Provide i18n labels and format the json data for the graph.
+ * @see AbstractGraph
+ *
+ * @author Mike Thompson
+ */
+public class MetricGraphData implements JsonMetricProducer {
+
+ private static final Integer DEFAULT_CHART_HEIGHT = 200;
+ // i18n
+ final protected Messages MSG = CoreGUI.getMessages();
+ private final String chartTitleMinLabel = MSG.chart_title_min_label();
+ private final String chartTitleAvgLabel = MSG.chart_title_avg_label();
+ private final String chartTitlePeakLabel = MSG.chart_title_peak_label();
+ private final String chartDateLabel = MSG.chart_date_label();
+ private final String chartTimeLabel = MSG.chart_time_label();
+ private final String chartDownLabel = MSG.chart_down_label();
+ private final String chartUnknownLabel = MSG.chart_unknown_label();
+ private final String chartNoDataLabel = MSG.chart_no_data_label();
+ private final String chartHoverStartLabel = MSG.chart_hover_start_label();
+ private final String chartHoverEndLabel = MSG.chart_hover_end_label();
+ private final String chartHoverPeriodLabel = MSG.chart_hover_period_label();
+ private final String chartHoverBarLabel = MSG.chart_hover_bar_label();
+ private final String chartHoverTimeFormat = MSG.chart_hover_time_format();
+ private final String chartHoverDateFormat = MSG.chart_hover_date_format();
+ private int entityId = 0;
+ private String entityName;
+ private int definitionId;
+ private int portalId;
+ private MeasurementUnits adjustedMeasurementUnits;
+ private MeasurementDefinition definition;
+ private List<MeasurementDataNumericHighLowComposite> metricData;
+ private PageList<MeasurementOOBComposite> measurementOOBCompositeList;
+ private MeasurementOOBComposite lastOOB;
+ private Integer chartHeight;
+ private boolean isPortalGraph;
+
+
+ private MetricGraphData(int portalId) {
+ isPortalGraph = true;
+ this.portalId = portalId;
+ }
+
+ public static MetricGraphData createForDashboard(int portalId){
+ return new MetricGraphData(portalId);
+ }
+
+
+ private MetricGraphData(int entityId, String entityName, MeasurementDefinition def,
+ List<MeasurementDataNumericHighLowComposite> metricData ) {
+ this.entityName = entityName;
+ setEntityId(entityId);
+ setDefinitionId(def.getId());
+ this.definition = def;
+ this.metricData = metricData;
+ this.isPortalGraph = false;
+ }
+
+ public static MetricGraphData createForResourceGroup(int groupId, String groupName, MeasurementDefinition def,
+ List<MeasurementDataNumericHighLowComposite> metricData ){
+ return new MetricGraphData(groupId,groupName,def, metricData );
+ }
+
+ private MetricGraphData(int entityId, String entityName, MeasurementDefinition measurementDef,
+ List<MeasurementDataNumericHighLowComposite> metrics,
+ PageList<MeasurementOOBComposite> measurementOOBCompositeList ) {
+ this.entityName = entityName;
+ setEntityId(entityId);
+ setDefinitionId(measurementDef.getId());
+ this.definition = measurementDef;
+ this.metricData = metrics;
+ this.measurementOOBCompositeList = measurementOOBCompositeList;
+ this.isPortalGraph = false;
+ }
+
+ public static MetricGraphData createForResource(int resourceId, String resourceName, MeasurementDefinition measurementDef,
+ List<MeasurementDataNumericHighLowComposite> metrics,
+ PageList<MeasurementOOBComposite> measurementOOBCompositeList ){
+ return new MetricGraphData(resourceId, resourceName,measurementDef, metrics, measurementOOBCompositeList);
+ }
+
+ public int getEntityId() {
+ return this.entityId;
+ }
+
+ public void setEntityId(int entityId) {
+ this.entityId = entityId;
+ //this.definition = null;
+ }
+
+
+ public void setEntityName(String entityName) {
+ this.entityName = entityName;
+ //this.definition = null;
+ }
+
+ public int getDefinitionId() {
+ return definitionId;
+ }
+
+ public void setDefinitionId(int definitionId) {
+ this.definitionId = definitionId;
+ //this.definition = null;
+ }
+
+ public MeasurementDefinition getDefinition() {
+ return definition;
+ }
+
+ public void setDefinition(MeasurementDefinition definition) {
+ this.definition = definition;
+ }
+
+ public String getChartId() {
+ if(isPortalGraph){
+ if(definition != null){
+ return entityId + "-" + definition.getId();
+ }else {
+ // case when portlet has not been configured yet
+ return "";
+ }
+ }else {
+ return entityId + "-" + definitionId;
+ }
+ }
+
+
+ public void setMetricData(List<MeasurementDataNumericHighLowComposite> metricData) {
+ this.metricData = metricData;
+ }
+
+
+ public String getChartTitleMinLabel() {
+ return chartTitleMinLabel;
+ }
+
+ public String getChartTitleAvgLabel() {
+ return chartTitleAvgLabel;
+ }
+
+ public String getChartTitlePeakLabel() {
+ return chartTitlePeakLabel;
+ }
+
+ public String getChartDateLabel() {
+ return chartDateLabel;
+ }
+
+ public String getChartDownLabel() {
+ return chartDownLabel;
+ }
+
+ public String getChartTimeLabel() {
+ return chartTimeLabel;
+ }
+
+ public String getChartUnknownLabel() {
+ return chartUnknownLabel;
+ }
+
+ public String getChartNoDataLabel() {
+ return chartNoDataLabel;
+ }
+
+ public String getChartHoverStartLabel() {
+ return chartHoverStartLabel;
+ }
+
+ public String getChartHoverEndLabel() {
+ return chartHoverEndLabel;
+ }
+
+ public String getChartHoverPeriodLabel() {
+ return chartHoverPeriodLabel;
+ }
+
+ public String getChartHoverBarLabel() {
+ return chartHoverBarLabel;
+ }
+
+ public String getChartHoverTimeFormat() {
+ return chartHoverTimeFormat;
+ }
+
+ public String getChartHoverDateFormat() {
+ return chartHoverDateFormat;
+ }
+
+ public int getPortalId() {
+ return portalId;
+ }
+
+ public Integer getChartHeight() {
+ if (null != chartHeight) {
+ return chartHeight;
+ } else {
+
+ return DEFAULT_CHART_HEIGHT;
+ }
+ }
+
+ public void setChartHeight(Integer chartHeight) {
+ this.chartHeight = chartHeight;
+ }
+
+ public boolean isPortalGraph() {
+ return isPortalGraph;
+ }
+
+ public String getChartTitle() {
+
+ if(definition != null){
+ return (entityName == null) ? definition.getDisplayName() : entityName + " - "+definition.getDisplayName();
+ }else {
+ // handle case when dashboard portlet has not been configured yet.
+ return "";
+
+ }
+
+ }
+
+ /**
+ * Returns the y-axis units normalized to highest scale (Bytes -> Gb).
+ * NOTE: this requires a dependency such that getJsonMetrics is called
+ * before this method as the adjustedMeasurementUnits are calculated in that method.
+ * @return yAxisUnits -- normalized to highest UOM.
+ */
+ public String getYAxisUnits() {
+ if (adjustedMeasurementUnits == null) {
+ Log.warn("ResourceMetricD3GraphView.adjustedMeasurementUnits is populated by getJsonMetrics. Make sure it is called first.");
+ return "";
+ } else {
+ return adjustedMeasurementUnits.toString();
+ }
+ }
+
+ public String getXAxisTitle() {
+ return MSG.view_charts_time_axis_label();
+ }
+
+ @Override
+ /**
+ * Format the json for the front JSNI(javascript) UI to consume.
+ * @todo: future: this should really use GSON or some Json marshaller
+ */
+ public String getJsonMetrics() {
+ StringBuilder sb = new StringBuilder("[");
+ boolean gotAdjustedMeasurementUnits = false;
+ if (null != metricData) {
+ long firstBarTime = metricData.get(0).getTimestamp();
+ long secondBarTime = metricData.get(1).getTimestamp();
+ long barDuration = secondBarTime - firstBarTime;
+ String barDurationString = MeasurementConverterClient.format((double) barDuration,
+ MeasurementUnits.MILLISECONDS, true);
+
+ calculateOOB();
+
+ for (MeasurementDataNumericHighLowComposite measurement : metricData) {
+ sb.append("{ \"x\":" + measurement.getTimestamp() + ",");
+
+ if (null != lastOOB) {
+ sb.append(" \"baselineMin\":" + lastOOB.getBlMin() + ", ");
+ sb.append(" \"baselineMax\":" + lastOOB.getBlMax() + ", ");
+ }
+
+ if (!Double.isNaN(measurement.getValue())) {
+
+ MeasurementNumericValueAndUnits newHigh = normalizeUnitsAndValues(measurement.getHighValue(),
+ definition.getUnits());
+ MeasurementNumericValueAndUnits newLow = normalizeUnitsAndValues(measurement.getLowValue(),
+ definition.getUnits());
+ MeasurementNumericValueAndUnits newAvg = normalizeUnitsAndValues(measurement.getValue(),
+ definition.getUnits());
+ if (!gotAdjustedMeasurementUnits) {
+ adjustedMeasurementUnits = newAvg.getUnits();
+ gotAdjustedMeasurementUnits = true;
+ }
+ sb.append(" \"barDuration\": \"" + barDurationString + "\", ");
+ sb.append(" \"high\":" + cleanseHigh(newLow.getValue(), newAvg.getValue(),newHigh.getValue()) + ",");
+ sb.append(" \"low\":" + cleanseLow(newLow.getValue(), newAvg.getValue(), newHigh.getValue()) + ",");
+ sb.append(" \"y\":" + newAvg.getValue() + "},");
+ } else {
+ // give it some values so that we dont have NaN
+ sb.append(" \"high\":0,");
+ sb.append(" \"low\":0,");
+ sb.append(" \"y\":0,");
+ sb.append(" \"nodata\":true },");
+ }
+ if (!sb.toString().endsWith("},")) {
+ sb.append(" },");
+ }
+ }
+ sb.setLength(sb.length() - 1); // delete the last ','
+ }
+ sb.append("]");
+ Log.debug("Json data for: "+getChartTitle());
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * This is cleaning the data as sometimes the data coming from the metric query
+ * is erroneous: for instance the low is greater than the high. This causes the
+ * geometries to get weird. We normally should not have to do this!
+ * @todo: Remove this data cleansing once we have fixed it at the metric query.
+ *
+ * @param low supposed low value
+ * @param high supposed high value
+ * @return the real high value
+ */
+ private Double cleanseHigh(Double low, Double avg, Double high){
+ double highLowMax = Math.max(low, high);
+ return Math.max(highLowMax, avg);
+ }
+
+ private Double cleanseLow(Double low, Double avg, Double high){
+ double highLowMin = Math.min(low, high);
+ return Math.min(highLowMin, avg);
+ }
+
+ /**
+ * When the scale is adjusted down to a level where bars no longer have
+ * highs and lows different from the avg value then have probably hit a
+ * scale where aggregates no longer exist and we are looking the individual
+ * values. At the very least the data is less interesting and a trendline
+ * connecting the points has less meaning because we are essentially a scatterplot.
+ * A different algorithm could be used here but this will suffice.
+ * @return true if the graphs should show the bar avg line meaning there is aggregates in the data
+ * @see StackedBarMetricGraphImpl
+ */
+ public boolean showBarAvgTrendLine() {
+ for (MeasurementDataNumericHighLowComposite measurement : metricData) {
+ boolean noValuesInCurrentBarUndefined = (!Double.isNaN(measurement.getValue()) && !Double.isNaN(measurement.getHighValue()) && !Double.isNaN(measurement.getLowValue()));
+ boolean foundAggregateBar = (measurement.getValue() != measurement.getHighValue() || measurement.getHighValue() != measurement.getLowValue());
+ // if there exists a even one aggregate bar then I can short circuit this and exit
+ if (noValuesInCurrentBarUndefined && foundAggregateBar){
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ private void calculateOOB() {
+ if (measurementOOBCompositeList != null && !measurementOOBCompositeList.isEmpty()) {
+ Log.debug("OOB List size: " + measurementOOBCompositeList.size());
+ List<MeasurementOOBComposite> selectedOOBs = new ArrayList<MeasurementOOBComposite>();
+ for (MeasurementOOBComposite measurementOOBComposite : measurementOOBCompositeList) {
+ Log.debug("measurementOOBComposite = " + measurementOOBComposite);
+ if (measurementOOBComposite.getDefinitionId() == definitionId) {
+ selectedOOBs.add(measurementOOBComposite);
+ }
+ }
+ // take the last one (most current) matching the defId
+ lastOOB = selectedOOBs.isEmpty() ? null : selectedOOBs.get(selectedOOBs.size() - 1);
+ } else {
+ lastOOB = null;
+ }
+ }
+
+
+ private MeasurementNumericValueAndUnits normalizeUnitsAndValues(double value, MeasurementUnits measurementUnits) {
+ MeasurementNumericValueAndUnits newValue = MeasurementConverterClient.fit(value, measurementUnits);
+ MeasurementNumericValueAndUnits returnValue;
+
+ // adjust for percentage numbers
+ if (measurementUnits.equals(MeasurementUnits.PERCENTAGE)) {
+ returnValue = new MeasurementNumericValueAndUnits(newValue.getValue() * 100, newValue.getUnits());
+ } else {
+ returnValue = new MeasurementNumericValueAndUnits(newValue.getValue(), newValue.getUnits());
+ }
+
+ return returnValue;
+ }
+
+
+
+ /**
+ * If there is more than 2 days time window then return true so we can show day of week
+ * in axis labels. Function to switch the timescale to whichever is more appropriate hours
+ * or hours with days of week.
+ * @return true if difference between startTime and endTime is >= x days
+ */
+ public boolean shouldDisplayDayOfWeekInXAxisLabel() {
+ Long startTime = metricData.get(0).getTimestamp();
+ Long endTime = metricData.get(metricData.size() - 1).getTimestamp();
+ long timeThreshold = 24 * 60 * 60 * 1000; // 1 days
+ return startTime + timeThreshold < endTime;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("MetricGraphData");
+ sb.append("{chartTitleMinLabel='").append(chartTitleMinLabel).append('\'');
+ sb.append(", chartTitleAvgLabel='").append(chartTitleAvgLabel).append('\'');
+ sb.append(", chartTitlePeakLabel='").append(chartTitlePeakLabel).append('\'');
+ sb.append(", chartDateLabel='").append(chartDateLabel).append('\'');
+ sb.append(", chartTimeLabel='").append(chartTimeLabel).append('\'');
+ sb.append(", chartDownLabel='").append(chartDownLabel).append('\'');
+ sb.append(", chartUnknownLabel='").append(chartUnknownLabel).append('\'');
+ sb.append(", chartNoDataLabel='").append(chartNoDataLabel).append('\'');
+ sb.append(", chartHoverStartLabel='").append(chartHoverStartLabel).append('\'');
+ sb.append(", chartHoverEndLabel='").append(chartHoverEndLabel).append('\'');
+ sb.append(", chartHoverPeriodLabel='").append(chartHoverPeriodLabel).append('\'');
+ sb.append(", chartHoverBarLabel='").append(chartHoverBarLabel).append('\'');
+ sb.append(", chartHoverTimeFormat='").append(chartHoverTimeFormat).append('\'');
+ sb.append(", chartHoverDateFormat='").append(chartHoverDateFormat).append('\'');
+ sb.append(", entityId=").append(entityId);
+ sb.append(", entityName='").append(entityName).append('\'');
+ sb.append(", definitionId=").append(definitionId);
+ sb.append(", isPortalGraph=").append(isPortalGraph);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityLineGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityLineGraphType.java
new file mode 100644
index 0000000..60b5e26
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityLineGraphType.java
@@ -0,0 +1,308 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import java.util.Date;
+import java.util.List;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AvailabilityGraphType;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+/**
+ * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
+ * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
+ * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityLineGraphType implements AvailabilityGraphType {
+
+ private static Messages MSG = CoreGUI.getMessages();
+ private List<Availability> availabilityList;
+ private List<ResourceGroupAvailability> groupAvailabilityList;
+ private Integer entityId;
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public AvailabilityLineGraphType(Integer entityId) {
+ this.entityId = entityId;
+ }
+
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ this.availabilityList = availabilityList;
+ }
+
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ this.groupAvailabilityList = groupAvailabilityList;
+ }
+
+ public String getAvailabilityJson() {
+ StringBuilder sb = new StringBuilder("[");
+ if (null != availabilityList) {
+ // loop through the avail intervals
+ for (Availability availability : availabilityList) {
+ sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType()+ "\", ");
+ sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - availability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+
+ } else if (null != groupAvailabilityList) {
+ // loop through the group avail down intervals
+ for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
+ // allows substitution for situations like WARN=MIXED for easier terminology
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType().equals(ResourceGroupComposite.GroupAvailabilityType.WARN))
+ ? MSG.chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+
+ sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
+ sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
+ .getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - groupAvailability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+ }
+
+ sb.append("]");
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw Availability chart");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartHoverEndLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityLineGraphType::getChartHoverDateFormat()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 20 - margin.top - margin.bottom,
+ pixelsOffHeight = 0,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ // The gray bars at the bottom leading up
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return yScale(0);
+ })
+ .attr("height", function (d) {
+ return height - yScale(4) - pixelsOffHeight;
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "#FF9933"; // orange
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFFF00"; // yellow
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.warn("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ });
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 'n',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var hoverString,
+ timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart),
+ availEnd = new Date(+d.availEnd);
+
+ hoverString =
+ '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverStartLabel + ': </span><span style="width:50px;">' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span >' + ' </span><span style="width:50px;">' + dateFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverEndLabel + ': </span><span style="width:50px;">' + timeFormatter(availEnd) + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span >' + ' </span><span style="width:50px;">' + dateFormatter(availEnd) + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+ return hoverString;
+
+ }
+
+ return {
+ // Public API
+ draw: function (chartContext) {
+ "use strict";
+ console.info("AvailabilityChart");
+ //console.time("availabilityChart");
+
+ drawBars(availChartContext);
+ createHovers();
+ //console.timeEnd("availabilityChart");
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+ public String getChartId() {
+ return String.valueOf(entityId);
+ }
+
+ public String getChartTimeLabel() {
+ return MSG.chart_time_label();
+ }
+
+ public String getChartDateLabel() {
+ return MSG.chart_date_label();
+ }
+
+ public String getChartHoverAvailabilityLabel() {
+ return MSG.chart_hover_availability_label();
+ }
+
+ public String getChartHoverStartLabel() {
+ return MSG.chart_hover_start_label();
+ }
+
+ public String getChartHoverEndLabel() {
+ return MSG.chart_hover_end_label();
+ }
+
+ public String getChartHoverBarLabel() {
+ return MSG.chart_hover_bar_label();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return MSG.chart_hover_time_format();
+ }
+
+ public String getChartHoverDateFormat() {
+ return MSG.chart_hover_date_format();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java
new file mode 100644
index 0000000..d7528db
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java
@@ -0,0 +1,384 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import java.util.Date;
+import java.util.List;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AvailabilityGraphType;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+/**
+ * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
+ * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
+ * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityOverUnderGraphType implements AvailabilityGraphType {
+
+ private static Messages MSG = CoreGUI.getMessages();
+ private List<Availability> availabilityList;
+ private List<ResourceGroupAvailability> groupAvailabilityList;
+ private Integer entityId;
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public AvailabilityOverUnderGraphType(Integer entityId) {
+ this.entityId = entityId;
+ }
+
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ this.availabilityList = availabilityList;
+ }
+
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ this.groupAvailabilityList = groupAvailabilityList;
+ }
+
+ public String getAvailabilityJson() {
+ StringBuilder sb = new StringBuilder("[");
+ if (null != availabilityList) {
+ // loop through the avail intervals
+ for (Availability availability : availabilityList) {
+ sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - availability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+
+ } else if (null != groupAvailabilityList) {
+ // loop through the group avail down intervals
+ for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
+ // allows substitution for situations like WARN=MIXED for easier terminology
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
+ .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
+ .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+
+ sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
+ sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
+ .getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - groupAvailability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+ }
+
+ sb.append("]");
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw Enhanced Availability chart");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(8)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.log("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+ })
+ .attr("height", function (d) {
+ return 10;
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("fill", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text(availChartContext.chartTitle);
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartUpLabel);
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartDownLabel);
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart);
+
+ return '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+
+ }
+
+ return {
+ // Public API
+ draw: function (availChartContext) {
+ "use strict";
+ console.log("AvailabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+ public String getChartId() {
+ return String.valueOf(entityId);
+ }
+
+ public String getChartTimeLabel() {
+ return MSG.chart_time_label();
+ }
+
+ public String getChartDateLabel() {
+ return MSG.chart_date_label();
+ }
+
+ public String getChartHoverAvailabilityLabel() {
+ return MSG.chart_hover_availability_label();
+ }
+
+ public String getChartHoverStartLabel() {
+ return MSG.chart_hover_start_label();
+ }
+
+ public String getAvailChartDownLabel() {
+ return MSG.avail_chart_down_label();
+ }
+
+ public String getAvailChartUpLabel() {
+ return MSG.avail_chart_up_label();
+ }
+
+ public String getAvailChartTitleLabel() {
+ return MSG.avail_chart_title_label();
+ }
+
+ public String getChartHoverBarLabel() {
+ return MSG.chart_hover_bar_label();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return MSG.chart_hover_time_format();
+ }
+
+ public String getChartHoverDateFormat() {
+ return MSG.chart_hover_date_format();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
new file mode 100644
index 0000000..6f9ef81
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphWithSliderType.java
@@ -0,0 +1,388 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import java.util.Date;
+import java.util.List;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AvailabilityGraphType;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+/**
+ * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
+ * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
+ * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGraphType {
+
+ private static Messages MSG = CoreGUI.getMessages();
+ private List<Availability> availabilityList;
+ private List<ResourceGroupAvailability> groupAvailabilityList;
+ private Integer entityId;
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public AvailabilityOverUnderGraphWithSliderType(Integer entityId) {
+ this.entityId = entityId;
+ }
+
+ @Override
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ this.availabilityList = availabilityList;
+ }
+
+ @Override
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ this.groupAvailabilityList = groupAvailabilityList;
+ }
+
+ @Override
+ public String getAvailabilityJson() {
+ StringBuilder sb = new StringBuilder("[");
+ if (null != availabilityList) {
+ // loop through the avail intervals
+ for (Availability availability : availabilityList) {
+ sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - availability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+
+ } else if (null != groupAvailabilityList) {
+ // loop through the group avail down intervals
+ for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
+ // allows substitution for situations like WARN=MIXED for easier terminology
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
+ .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
+ .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+
+ sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
+ sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
+ .getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - groupAvailability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+ }
+
+ sb.append("]");
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ @Override
+ public native void drawJsniChart() /*-{
+ console.log("Draw Enhanced Availability chart");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType::getAvailChartDownLabel()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(8)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.log("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+ })
+ .attr("height", function (d) {
+ return 10;
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("fill", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text(availChartContext.chartTitle);
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartUpLabel);
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartDownLabel);
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart);
+
+ return '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+
+ }
+
+ return {
+ // Public API
+ draw: function (availChartContext) {
+ "use strict";
+ console.log("AvailabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+ public String getChartId() {
+ return String.valueOf(entityId);
+ }
+
+ public String getChartTimeLabel() {
+ return MSG.chart_time_label();
+ }
+
+ public String getChartDateLabel() {
+ return MSG.chart_date_label();
+ }
+
+ public String getChartHoverAvailabilityLabel() {
+ return MSG.chart_hover_availability_label();
+ }
+
+ public String getChartHoverStartLabel() {
+ return MSG.chart_hover_start_label();
+ }
+
+ public String getAvailChartDownLabel() {
+ return MSG.avail_chart_down_label();
+ }
+
+ public String getAvailChartUpLabel() {
+ return MSG.avail_chart_up_label();
+ }
+
+ public String getAvailChartTitleLabel() {
+ return MSG.avail_chart_title_label();
+ }
+
+ public String getChartHoverBarLabel() {
+ return MSG.chart_hover_bar_label();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return MSG.chart_hover_time_format();
+ }
+
+ public String getChartHoverDateFormat() {
+ return MSG.chart_hover_date_format();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java
new file mode 100644
index 0000000..279921c
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/LineMetricGraph.java
@@ -0,0 +1,158 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
+
+/**
+ * Contains the javascript chart definition for a d3 Line graph chart.
+ * NOTE: this class isn't used just provided as an example as how to create
+ * other graph types.
+ *
+ * @author Mike Thompson
+ */
+public final class LineMetricGraph extends AbstractGraph {
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to
+ * produce the graph. (This is true for all cases but the dashboard portlet).
+ */
+ public LineMetricGraph(MetricGraphData metricGraphData) {
+ setMetricGraphData(metricGraphData);
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw Metric Line jsni chart");
+ var global = this,
+ chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getChartId()(),
+ chartHandle = "#rChart-"+chartId,
+ chartSelection = chartHandle + " svg",
+ json = $wnd.jQuery.parseJSON(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getJsonMetrics()()),
+ yAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getChartTitle()(),
+ yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getYAxisUnits()(),
+ xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getXAxisTitle()();
+
+ console.log("chart id: "+chartSelection );
+ console.log(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getJsonMetrics()());
+
+
+ function draw(data){
+ "use strict";
+
+ var margin = {top: 10, right: 5, bottom: 30, left: 70},
+ width = 400 - margin.left - margin.right,
+ height = 150 - margin.top - margin.bottom;
+
+ var timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain($wnd.d3.extent(data, function(d) { return d.x; }));
+
+ var yScale = $wnd.d3.scale.linear()
+ .rangeRound([height, 0])
+ .domain([$wnd.d3.min(data.map(function(x) {return x.low;})), $wnd.d3.max(data.map(function(x){return x.high;}))]);
+
+ var xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(5)
+ .orient("bottom");
+
+ var yAxis = $wnd.d3.svg.axis()
+ .scale(yScale)
+ .ticks(5)
+ .orient("left");
+
+ var interpolation = "basis";
+
+ var line = $wnd.d3.svg.line()
+ .interpolate(interpolation)
+ .x(function(d) { return timeScale(d.x); })
+ .y(function(d) { return yScale(+d.y); });
+
+ var highLine = $wnd.d3.svg.line()
+ .interpolate(interpolation)
+ .x(function(d) { return timeScale(d.x); })
+ .y(function(d) { return yScale(+d.high); });
+
+ var lowLine = $wnd.d3.svg.line()
+ .interpolate(interpolation)
+ .x(function(d) { return timeScale(d.x); })
+ .y(function(d) { return yScale(+d.low); });
+
+ var svg = $wnd.d3.select(chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("transform", "translate(0," + height + ")")
+ .call(xAxis);
+
+
+ svg.append("g")
+ .attr("class", "y axis")
+ .call(yAxis)
+ .append("text")
+ .attr("transform", "rotate(-90)")
+ .attr("y", -60)
+ .attr("dy", ".71em")
+ .style("text-anchor", "end")
+ .text(yAxisUnits === "NONE" ? "" : yAxisUnits);
+
+ console.log("finished axes");
+
+ svg.append("path")
+ .datum(data)
+ .attr("class", "line")
+ .attr("fill", "none")
+ .attr("stroke", "steelblue")
+ .attr("stroke-width", "2")
+ .attr("d", line);
+
+ svg.append("path")
+ .datum(data)
+ .attr("class", "highLine")
+ .attr("fill", "none")
+ .attr("stroke", "red")
+ .attr("stroke-width", "1.5")
+ //.attr("stroke-dasharray", "20,10,5,5,5,10")
+ .attr("stroke-dasharray", "5,5")
+ .attr("stroke-opacity", ".3")
+ .attr("d", highLine);
+
+ svg.append("path")
+ .datum(data)
+ .attr("class", "lowLine")
+ .attr("fill", "none")
+ .attr("stroke", "blue")
+ .attr("stroke-width", "1.5")
+ .attr("stroke-dasharray", "5,5")
+ .attr("stroke-opacity", ".3")
+ .attr("d", lowLine);
+
+ console.log("finished paths");
+ }(data);
+
+ }-*/;
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java
new file mode 100644
index 0000000..544a71b
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/MetricNvd3MultiLineGraph.java
@@ -0,0 +1,92 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
+
+/**
+ * Contains the chart definition for a MultiLine Graph.
+ *
+ * @author Mike Thompson
+ */
+public final class MetricNvd3MultiLineGraph extends AbstractGraph
+{
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to
+ * produce the graph. (This is true for all cases but the dashboard portlet).
+ */
+ public MetricNvd3MultiLineGraph(MetricGraphData metricGraphData){
+ setMetricGraphData(metricGraphData);
+ }
+
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw NVD3 Bar jsni chart");
+ console.time("multiChart");
+ var global = this,
+ chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getChartId()(),
+ chartHandle = "#rChart-"+chartId,
+ chartSelection = chartHandle + " svg",
+ json = $wnd.jQuery.parseJSON(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getJsonMetrics()()),
+ yAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getChartTitle()(),
+ yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getYAxisUnits()(),
+ xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::getXAxisTitle()(),
+ displayDayOfWeek = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData::shouldDisplayDayOfWeekInXAxisLabel()(),
+ xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I : %M %p",
+
+ // nvd3 defines their json models a standard way (same model for other graphs)
+ data = function() {
+ return [
+ {
+ values: json,
+ key: yAxisLabel ,
+ color: '#ff7f0e'
+ }
+ ];
+ };
+ $wnd.nv.addGraph(function() {
+ var chart = $wnd.nv.models.multiBarChart()
+ .showControls(true)
+ .tooltips(true);
+
+ chart.xAxis.axisLabel(xAxisLabel)
+ .tickFormat(function(d) { return $wnd.d3.time.format(xAxisTimeFormat)(new Date(d)) });
+
+ chart.yAxis
+ .axisLabel(yAxisUnits)
+ .tickFormat($wnd.d3.format(',f'));
+
+ $wnd.d3.select(chartSelection)
+ .datum(data())
+ .transition().duration(300)
+ .call(chart);
+
+ $wnd.nv.utils.windowResize(chart.update);
+
+ return chart;
+ });
+ console.timeEnd("multiChart")
+
+ }-*/;
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java
new file mode 100644
index 0000000..8a1998a
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphIE8Impl.java
@@ -0,0 +1,46 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+/**
+ * Contains the javascript chart definition for an IE8 d3 Stacked Bar graph chart.
+ * Curr
+ *
+ * @author Mike Thompson
+ */
+public final class StackedBarMetricGraphIE8Impl extends StackedBarMetricGraphImpl {
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public StackedBarMetricGraphIE8Impl() {
+ super();
+ }
+
+
+ /**
+ * Empty implementation for IE8.
+ */
+ @Override
+ public native void drawJsniChart() /*-{
+ // no-op implementation for ie8
+ }-*/;
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
new file mode 100644
index 0000000..aca67b9
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -0,0 +1,636 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype;
+
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph;
+
+/**
+ * Contains the javascript chart definition for a d3 Stacked Bar graph chart.
+ *
+ * @author Mike Thompson
+ */
+public class StackedBarMetricGraphImpl extends AbstractGraph {
+
+ /**
+ * GWT constructor for GWT.create() deferred instantiation.
+ */
+ public StackedBarMetricGraphImpl() {
+ super();
+ }
+
+
+ /**
+ * The magic JSNI to draw the charts with $wnd.d3.js
+ */
+ @Override
+ public native void drawJsniChart() /*-{
+ console.log("Draw Stacked Bar jsni chart");
+ var global = this,
+
+ // create a chartContext object (from rhq.js) with the data required to render to a chart
+ // this same data could be passed to different chart types
+ // This way, we are decoupled from the dependency on globals and JSNI and kept all the java interaction right here.
+ chartContext = new $wnd.ChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHeight()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getJsonMetrics()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getXAxisTitle()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitle()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getYAxisUnits()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitleMinLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitleAvgLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTitlePeakLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartDownLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartUnknownLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartNoDataLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverEndLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverPeriodLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::isPortalGraph()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::getPortalId()()
+ );
+
+
+ // Define the Stacked Bar Graph function using the module pattern
+ var metricStackedBarGraph = function () {
+ "use strict";
+ // privates
+ var margin = {top: 10, right: 5, bottom: 5, left: 40},
+ width = 750 - margin.left - margin.right,
+ adjustedChartHeight = chartContext.chartHeight - 50,
+ height = adjustedChartHeight - margin.top - margin.bottom,
+ smallChartThresholdInPixels = 600,
+ titleHeight = 30, titleSpace = 10,
+ barOffset = 2,
+ chartData,
+ interpolation = "basis",
+ avg, min, peak,
+ oobMax,
+ determineLowBound,
+ lowBound,
+ highBound,
+ calcBarWidth,
+ yScale,
+ yAxis,
+ timeScale,
+ xAxis,
+ chart,
+ svg;
+
+ function isIEBrowserGreaterThanOrEqualTo(targetIEVersion){
+ var myUserAgent = $wnd.navigator.userAgent;
+ if (/MSIE (\d+\.\d+);/.test(myUserAgent)){ //test for MSIE x.x;
+ var ieVersion=new Number(RegExp.$1); // capture x.x portion and store as a number
+ if (ieVersion>=targetIEVersion){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function getChartWidth() {
+ return $wnd.jQuery("#" + chartContext.chartHandle).width();
+ }
+
+ function useSmallCharts() {
+ return getChartWidth() <= smallChartThresholdInPixels;
+ }
+
+ function determineScale() {
+ var xTicks, xTickSubDivide, numberOfBarsForSmallGraph = 20;
+ if (chartContext.data.length > 0) {
+
+ // if window is too small server up small chart
+ if (useSmallCharts()) {
+ console.log("Using Small Charts Profile for width: "+getChartWidth());
+ width = 250;
+ xTicks = 3;
+ xTickSubDivide = 2;
+ chartData = chartContext.data.slice(chartContext.data.length - numberOfBarsForSmallGraph, chartContext.data.length - 1);
+ }
+ else {
+ console.log("Using Large Charts Profile");
+ // we use the width already defined above
+ xTicks = 8;
+ xTickSubDivide = 5;
+ chartData = chartContext.data;
+ }
+
+ avg = $wnd.d3.mean(chartContext.data.map(function (d) {
+ return d.y;
+ }));
+ peak = $wnd.d3.max(chartContext.data.map(function (d) {
+ if (d.high != undefined) {
+ return d.high;
+ }
+ else {
+ return 0;
+ }
+ }));
+ min = $wnd.d3.min(chartContext.data.map(function (d) {
+ if (d.low != undefined) {
+ return d.low;
+ }
+ else {
+ return Number.MAX_VALUE;
+ }
+ }));
+ // adjust the min scale so blue low line is not in axis
+ determineLowBound = function (min, peak) {
+ var newLow = min - ((peak - min) * 0.1);
+ if (newLow < 0) {
+ return 0;
+ }
+ else {
+ return newLow;
+ }
+ };
+ lowBound = determineLowBound(min, peak);
+ highBound = peak + ((peak - min) * 0.1);
+ oobMax = $wnd.d3.max(chartContext.data.map(function (d) {
+ if (d.baselineMax == undefined) {
+ return 0;
+ }
+ else {
+ return +d.baselineMax;
+ }
+ }));
+ calcBarWidth = function () {
+ return (width / chartData.length - barOffset )
+ };
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([lowBound, highBound]);
+ yAxis = $wnd.d3.svg.axis()
+ .scale(yScale)
+ .tickSubdivide(1)
+ .ticks(5)
+ .tickSize(4, 4, 0)
+ .orient("left");
+
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain($wnd.d3.extent(chartData, function (d) {
+ return d.x;
+ }));
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(xTicks)
+ .tickSubdivide(xTickSubDivide)
+ .tickSize(4, 4, 0)
+ .orient("bottom");
+
+ // create the actual chart group
+ chart = $wnd.d3.select("#" + chartContext.chartSelection);
+
+ svg = chart.append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top - titleHeight - titleSpace + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + (+titleHeight + titleSpace + margin.top) + ")");
+
+ if (!useSmallCharts()) {
+ createMinAvgPeakSidePanel(chartContext.minChartTitle, min, chartContext.avgChartTitle, avg, chartContext.peakChartTitle, peak, chartContext.yAxisUnits);
+ }
+ }
+
+ }
+
+
+ function createMinAvgPeakSidePanel(minLabel, minValue, avgLabel, avgValue, highLabel, highValue, uom) {
+ var xLabel = 772,
+ xValue = 820,
+ yBase = 100,
+ yInc = 25,
+ decimalPlaces = 0;
+
+ // title/header
+ chart.append("g").append("rect")
+ .attr("class", "rightSidePanel")
+ .attr("x", xLabel - 10)
+ .attr("y", margin.top + 70)
+ .attr("rx", 10)
+ .attr("ry", 10)
+ .attr("height", 80)
+ .attr("width", 135)
+ .attr("opacity", "0.3")
+ .attr("fill", "#E8E8E8");
+
+ // high
+ chart.append("text")
+ .attr("class", "highLabel")
+ .attr("x", xLabel)
+ .attr("y", yBase)
+ .text(highLabel + " - ");
+
+ chart.append("text")
+ .attr("class", "highText")
+ .attr("x", xValue)
+ .attr("y", yBase)
+ .text(highValue.toFixed(decimalPlaces) + " " + uom);
+
+
+ //avg
+ chart.append("text")
+ .attr("class", "avgLabel")
+ .attr("x", xLabel)
+ .attr("y", yBase + yInc)
+ .text(avgLabel + " - ");
+
+ chart.append("text")
+ .attr("class", "avgText")
+ .attr("x", xValue)
+ .attr("y", yBase + yInc)
+ .text(avgValue.toFixed(decimalPlaces) + " " + uom);
+
+ // min
+ chart.append("text")
+ .attr("class", "minLabel")
+ .attr("x", xLabel)
+ .attr("y", yBase + 2 * yInc)
+ .text(minLabel + " - ");
+
+ chart.append("text")
+ .attr("class", "minText")
+ .attr("x", xValue)
+ .attr("y", yBase + 2 * yInc)
+ .text(minValue.toFixed(decimalPlaces) + " " + uom);
+
+
+ }
+
+ function createHeader(titleName) {
+ var title = chart.append("g").append("rect")
+ .attr("class", "title")
+ .attr("x", 10)
+ .attr("y", margin.top)
+ .attr("height", titleHeight)
+ .attr("width", width + 30 + margin.left)
+ .attr("fill", "none");
+
+ chart.append("text")
+ .attr("class", "titleName")
+ .attr("x", 40)
+ .attr("y", 37)
+ .attr("font-size", "12")
+ .attr("font-weight", "bold")
+ .attr("text-anchor", "left")
+ .text(titleName)
+ .attr("fill", "#003168");
+
+ return title;
+
+ }
+
+ function createStackedBars() {
+
+ var pixelsOffHeight = 0;
+
+ // The gray bars at the bottom leading up
+ svg.selectAll("rect.leaderBar")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "leaderBar")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return yScale(highBound);
+ }
+ else {
+ return yScale(d.low);
+ }
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(highBound) - pixelsOffHeight;
+ }
+ else {
+ return height - yScale(d.low) - pixelsOffHeight;
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return "url(#noDataStripes)";
+ }
+ else {
+ return "#d3d3d6";
+ }
+ });
+
+
+ // upper portion representing avg to high
+ svg.selectAll("rect.high")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "high")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ return isNaN(d.high) ? yScale(lowBound) : yScale(d.high);
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(lowBound);
+ }
+ else {
+ return yScale(d.y) - yScale(d.high);
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+ .attr("data-rhq-value", function (d) {
+ return d.y;
+ })
+ .attr("opacity", 0.9);
+
+
+ // lower portion representing avg to low
+ svg.selectAll("rect.low")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "low")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ return isNaN(d.y) ? height : yScale(d.y);
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(lowBound);
+ }
+ else {
+ return yScale(d.low) - yScale(d.y);
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+ .attr("opacity", 0.9);
+
+ // if high == low put a "cap" on the bar to show non-aggregated bar
+ svg.selectAll("rect.singleValue")
+ .data(chartData)
+ .enter().append("rect")
+ .attr("class", "singleValue")
+ .attr("x", function (d) {
+ return timeScale(d.x);
+ })
+ .attr("y", function (d) {
+ return isNaN(d.y) ? height : yScale(d.y) - 2;
+ })
+ .attr("height", function (d) {
+ if (d.down || d.unknown || d.nodata) {
+ return height - yScale(lowBound);
+ }
+ else {
+ if (d.low === d.high) {
+ return yScale(d.low) - yScale(d.y) + 2;
+ }
+ else {
+ return yScale(d.low) - yScale(d.y);
+ }
+ }
+ })
+ .attr("width", function () {
+ return calcBarWidth();
+ })
+ .attr("opacity", 0.9)
+ .attr("fill", function (d) {
+ if (d.low === d.high) {
+ return "#50505a";
+ }
+ else {
+ return "#70c4e2";
+ }
+ });
+ }
+
+ function createYAxisGridLines() {
+ // create the y axis grid lines
+ svg.append("g").classed("grid y_grid", true)
+ .call($wnd.d3.svg.axis()
+ .scale(yScale)
+ .orient("left")
+ .ticks(10)
+ .tickSize(-width, 0, 0)
+ .tickFormat("")
+ );
+ }
+
+ function createXandYAxes() {
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+
+ // create y-axis
+ svg.append("g")
+ .attr("class", "y axis")
+ .call(yAxis)
+ .append("text")
+ .attr("transform", "rotate(-90),translate( -60,0)")
+ .attr("y", -30)
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .text(chartContext.yAxisUnits === "NONE" ? "" : chartContext.yAxisUnits);
+
+ }
+
+ function createAvgLines() {
+ var showBarAvgTrendline =
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AbstractGraph::showBarAvgTrendLine()(),
+ barAvgLine = $wnd.d3.svg.line()
+ .interpolate("linear")
+ .defined(function (d) {
+ return !d.nodata;
+ })
+ .x(function (d) {
+ return timeScale(d.x) + (calcBarWidth() / 2);
+ })
+ .y(function (d) {
+ if (showBarAvgTrendline) {
+ return yScale(d.y);
+ }
+ else {
+ return yScale(0);
+ }
+ });
+
+ // Bar avg line
+ svg.append("path")
+ .datum(chartData)
+ .attr("class", "barAvgLine")
+ .attr("fill", "none")
+ .attr("stroke", "#2e376a")
+ .attr("stroke-width", "1.5")
+ .attr("stroke-opacity", ".7")
+ .attr("d", barAvgLine);
+
+ }
+
+ function createOOBLines() {
+
+ var minBaselineLine = $wnd.d3.svg.line()
+ .interpolate(interpolation)
+ .x(function (d) {
+ return timeScale(d.x);
+ })
+ .y(function (d) {
+ return yScale(d.baselineMin);
+ }),
+ maxBaselineLine = $wnd.d3.svg.line()
+ .interpolate(interpolation)
+ .x(function (d) {
+ return timeScale(d.x);
+ })
+ .y(function (d) {
+ return yScale(d.baselineMax);
+ });
+
+ // min baseline Line
+ svg.append("path")
+ .datum(chartData)
+ .attr("class", "minBaselineLine")
+ .attr("fill", "none")
+ .attr("stroke", "purple")
+ .attr("stroke-width", "1")
+ .attr("stroke-dasharray", "20,10,5,5,5,10")
+ .attr("stroke-opacity", ".9")
+ .attr("d", minBaselineLine);
+
+ // max baseline Line
+ svg.append("path")
+ .datum(chartData)
+ .attr("class", "maxBaselineLine")
+ .attr("fill", "none")
+ .attr("stroke", "orange")
+ .attr("stroke-width", "1")
+ .attr("stroke-dasharray", "20,10,5,5,5,10")
+ .attr("stroke-opacity", ".7")
+ .attr("d", maxBaselineLine);
+
+ }
+
+ function formatHovers(chartContext, d) {
+ var hoverString,
+ xValue = (d.x == undefined) ? 0 : +d.x,
+ date = new Date(+xValue),
+ barDuration = d.barDuration,
+ timeFormatter = $wnd.d3.time.format(chartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(chartContext.chartHoverDateFormat),
+ highValue = d.high.toFixed(2),
+ lowValue = d.low.toFixed(2),
+ avgValue = d.y.toFixed(2);
+
+
+ // our special condition to indicate no data because avg lines dont like discontinuous data
+ if (d.y === 0 && d.high === 0 && d.low === 0) {
+ // no data
+ hoverString =
+ '<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel" >' + chartContext.timeLabel + ': </span>' + timeFormatter(date) +
+ '<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span>' + dateFormatter(date) + '</div>' +
+ '<hr class="chartHoverDivider" ></hr>' +
+ '<div class="chartHoverAlignRight"><span class="chartHoverLabelSpan">' + chartContext.noDataLabel + '</span></div>' +
+ '</div>';
+
+
+ }
+ else {
+ // regular bar hover
+ hoverString =
+ '<div class="chartHoverEnclosingDiv"><span class="chartHoverTimeLabel">' + chartContext.timeLabel + ': </span><span style="width:50px;">' + timeFormatter(date) + '</span>' +
+ '<div class="chartHoverAlignLeft"><span class="chartHoverDateLabel">' + chartContext.dateLabel + ': </span><span style="width:50px;">' + dateFormatter(date) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span class="chartHoverLabelSpan">' + chartContext.hoverBarLabel + ": " + barDuration + '</span></div>' +
+ '<hr class="chartHoverDivider"></hr>' +
+ '<div class="chartHoverAlignRight"><span id="chartHoverPeakValue" >' + chartContext.peakChartTitle + ': </span><span style="width:50px;">' + highValue + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span id="chartHoverAvgValue" >' + chartContext.avgChartTitle + ': </span><span style="width:50px;">' + avgValue + '</span></div>' +
+ '<div class="chartHoverAlignRight"><span id="chartHoverLowValue" >' + chartContext.minChartTitle + ': </span><span style="width:50px;">' + lowValue + '</span></div>' +
+ '</div>';
+ }
+ return hoverString;
+
+ }
+
+ function createHovers(chartContext) {
+ $wnd.jQuery('svg rect.leaderBar, svg rect.high, svg rect.low, svg rect.singleValue').tipsy({
+ gravity: 'w',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(chartContext, d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ return {
+ // Public API
+ draw: function (chartContext) {
+ "use strict";
+ // Guard condition that can occur when a portlet has not been configured yet
+ if (chartContext.data.length > 0) {
+ console.log("Creating Chart: "+ chartContext.chartSelection + " --> "+ chartContext.chartTitle);
+
+ determineScale();
+ createHeader(chartContext.chartTitle);
+
+ createYAxisGridLines();
+ createStackedBars();
+ createXandYAxes();
+ createAvgLines();
+ if (oobMax > 0) {
+ console.log("OOB Data Exists!");
+ createOOBLines();
+ }
+ createHovers(chartContext);
+ }
+ }
+ }; // end public closure
+ }();
+
+ metricStackedBarGraph.draw(chartContext);
+
+ }-*/;
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index 37b0f88..448a08f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -41,9 +41,9 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index c79c92d..38a5544 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -45,10 +45,10 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.GraphDateTimeRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphWithSliderType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.GraphDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.MetricGraphData;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.util.Log;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
index f8887bf..21025fc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
@@ -21,7 +21,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitori
import com.google.gwt.user.client.Timer;
import com.smartgwt.client.widgets.HTMLFlow;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
index 7509659..92bc69e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
@@ -24,7 +24,7 @@ import com.smartgwt.client.widgets.HTMLFlow;
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AvailabilityGraphType;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index a19d47a..f576ca1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -36,12 +36,12 @@
</any>
</replace-with>
- <replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl">
- <when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl"/>
+ <replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl">
+ <when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl"/>
</replace-with>
- <replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphIE8Impl">
- <when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl"/>
+ <replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphIE8Impl">
+ <when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl"/>
<when-property-is name="user.agent" value="ie8"/>
</replace-with>
commit 823c35fa92bb7dcccbe26ef1a9e53273f69d577b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 17 15:57:55 2013 -0700
Add AvailabilityGraphType Generics.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index 7eea0dd..37b0f88 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -74,7 +74,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
addMember(graphDateTimeRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3GraphView(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
+ availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphType>(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 63e1f93..c79c92d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -131,7 +131,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
addMember(graphDateTimeRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3GraphView(new AvailabilityOverUnderGraphWithSliderType(resource.getId()));
+ availabilityGraph = new AvailabilityD3GraphView<AvailabilityOverUnderGraphWithSliderType>(new AvailabilityOverUnderGraphWithSliderType(resource.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
index dc70645..7509659 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
@@ -34,11 +34,11 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
*
* @author Mike Thompson
*/
-public class AvailabilityD3GraphView extends EnhancedVLayout {
+public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends EnhancedVLayout {
- protected AvailabilityGraphType availabilityGraphType;
+ protected T availabilityGraphType;
- public AvailabilityD3GraphView(AvailabilityGraphType availabilityGraphType) {
+ public AvailabilityD3GraphView(T availabilityGraphType) {
super();
this.availabilityGraphType = availabilityGraphType;
setHeight(65);
commit 373cb38207d522166b433c35e7a110ccc8099840
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 15 14:49:18 2013 -0700
Remove jquery ui and replace with bootstrap.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index d942b8c..e358774 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -26,12 +26,14 @@ import com.smartgwt.client.widgets.Label;
import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.AutoRefreshUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3Graph;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.GraphDateTimeRangeEditor;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
/**
* Provide the shared stuff for create GraphListViews like Availability graphs
@@ -42,15 +44,17 @@ public abstract class AbstractD3GraphListView extends EnhancedVLayout implements
protected final static int MULTI_CHART_HEIGHT = 195;
protected List<Availability> availabilityList;
protected List<ResourceGroupAvailability> groupAvailabilityList;
- protected AvailabilityD3Graph availabilityGraph;
+ protected AvailabilityD3GraphView availabilityGraph;
protected static Label loadingLabel = new Label(MSG.common_msg_loading());
- protected UserPreferencesMeasurementRangeEditor measurementRangeEditor;
+ protected MeasurementUserPreferences measurementUserPrefs;
protected boolean showAvailabilityGraph = false;
+ protected GraphDateTimeRangeEditor graphDateTimeRangeEditor;
protected Timer refreshTimer;
public AbstractD3GraphListView() {
super();
- measurementRangeEditor = new UserPreferencesMeasurementRangeEditor();
+ measurementUserPrefs = new MeasurementUserPreferences(UserSessionManager.getUserPreferences());
+ graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs);
startRefreshCycle();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java
index a5f3f02..36d0807 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraph.java
@@ -26,6 +26,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
*
* @author Mike Thompson
*/
+@Deprecated
public interface AvailabilityGraph {
/**
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraphType.java
new file mode 100644
index 0000000..f390c6e
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityGraphType.java
@@ -0,0 +1,44 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+
+import java.util.List;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+
+/**
+ * Contract for an Availability Graph Implementation. This gives the abilility for
+ * Availability graphs to swap implementations giving different chart types.
+ *
+ * @author Mike Thompson
+ */
+public interface AvailabilityGraphType {
+
+ void setAvailabilityList(List<Availability> availabilityList);
+
+ void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList);
+
+ String getAvailabilityJson();
+
+ String getChartId();
+
+ void drawJsniChart();
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java
index 4324b7a..1b14f8c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityLineGraphType.java
@@ -37,7 +37,7 @@ import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
*
* @author Mike Thompson
*/
-public class AvailabilityLineGraphType {
+public class AvailabilityLineGraphType implements AvailabilityGraphType {
private static Messages MSG = CoreGUI.getMessages();
private List<Availability> availabilityList;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index fbce610..29d5742 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -37,7 +37,7 @@ import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
*
* @author Mike Thompson
*/
-public class AvailabilityOverUnderGraphType {
+public class AvailabilityOverUnderGraphType implements AvailabilityGraphType{
private static Messages MSG = CoreGUI.getMessages();
private List<Availability> availabilityList;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphWithSliderType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphWithSliderType.java
new file mode 100644
index 0000000..24c3ae1
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphWithSliderType.java
@@ -0,0 +1,387 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+
+import java.util.Date;
+import java.util.List;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+/**
+ * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
+ * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
+ * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityOverUnderGraphWithSliderType implements AvailabilityGraphType {
+
+ private static Messages MSG = CoreGUI.getMessages();
+ private List<Availability> availabilityList;
+ private List<ResourceGroupAvailability> groupAvailabilityList;
+ private Integer entityId;
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public AvailabilityOverUnderGraphWithSliderType(Integer entityId) {
+ this.entityId = entityId;
+ }
+
+ @Override
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ this.availabilityList = availabilityList;
+ }
+
+ @Override
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ this.groupAvailabilityList = groupAvailabilityList;
+ }
+
+ @Override
+ public String getAvailabilityJson() {
+ StringBuilder sb = new StringBuilder("[");
+ if (null != availabilityList) {
+ // loop through the avail intervals
+ for (Availability availability : availabilityList) {
+ sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - availability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+
+ } else if (null != groupAvailabilityList) {
+ // loop through the group avail down intervals
+ for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
+ // allows substitution for situations like WARN=MIXED for easier terminology
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
+ .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
+ .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+
+ sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
+ sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
+ .getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - groupAvailability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+ }
+
+ sb.append("]");
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ @Override
+ public native void drawJsniChart() /*-{
+ console.log("Draw Enhanced Availability chart");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType::getAvailChartDownLabel()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(8)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.log("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+ })
+ .attr("height", function (d) {
+ return 10;
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("fill", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text(availChartContext.chartTitle);
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartUpLabel);
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartDownLabel);
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart);
+
+ return '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+
+ }
+
+ return {
+ // Public API
+ draw: function (availChartContext) {
+ "use strict";
+ console.log("AvailabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+ public String getChartId() {
+ return String.valueOf(entityId);
+ }
+
+ public String getChartTimeLabel() {
+ return MSG.chart_time_label();
+ }
+
+ public String getChartDateLabel() {
+ return MSG.chart_date_label();
+ }
+
+ public String getChartHoverAvailabilityLabel() {
+ return MSG.chart_hover_availability_label();
+ }
+
+ public String getChartHoverStartLabel() {
+ return MSG.chart_hover_start_label();
+ }
+
+ public String getAvailChartDownLabel() {
+ return MSG.avail_chart_down_label();
+ }
+
+ public String getAvailChartUpLabel() {
+ return MSG.avail_chart_up_label();
+ }
+
+ public String getAvailChartTitleLabel() {
+ return MSG.avail_chart_title_label();
+ }
+
+ public String getChartHoverBarLabel() {
+ return MSG.chart_hover_bar_label();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return MSG.chart_hover_time_format();
+ }
+
+ public String getChartHoverDateFormat() {
+ return MSG.chart_hover_date_format();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/GraphDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/GraphDateTimeRangeEditor.java
new file mode 100644
index 0000000..9dd7b4a
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/GraphDateTimeRangeEditor.java
@@ -0,0 +1,190 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+
+import com.google.gwt.user.client.Timer;
+import com.smartgwt.client.widgets.HTMLFlow;
+
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPreferences;
+
+/**
+ * Component to allow selection of Date/Time range for graphs.
+ *
+ * @author Mike Thompson
+ */
+public class GraphDateTimeRangeEditor extends EnhancedVLayout {
+
+ private JQueryDateTimeRangeEditor graphDateTimeRangeEditor;
+ private MeasurementUserPreferences measurementUserPreferences;
+
+
+ public GraphDateTimeRangeEditor(MeasurementUserPreferences measurementUserPrefs) {
+ this.measurementUserPreferences = measurementUserPrefs;
+ this.graphDateTimeRangeEditor = new JQueryDateTimeRangeEditor();
+ }
+
+ /**
+ * Setup the page elements especially the div and svg elements that serve as
+ * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
+ * Later the drawJsniGraph() is called to actually fill in the div/svg element
+ * created here with the actual svg element.
+ * NOTE: auxiliary javascript functions in rhq.js
+ *
+ */
+ public void createGraphMarker() {
+ Log.debug("drawGraph marker in AvailabilityD3Graph for: graphDateTimeRangeEditor" );
+
+ // append the bootstrap buttongroup since smartGWT doesn't have one
+ StringBuilder divAndSvgDefs = new StringBuilder();
+ divAndSvgDefs.append("<div id=\"graphDateTimeRangeEditor\">" +
+ "<div class=\"accordion\" id=\"graphDateTimeEditorAccordion\" style=\"width:875px;>\n" +
+ " <div class=\"accordion-group\">\n" +
+ " \n" +
+ " <div id=\"graphDateTimeEditorCollapse\" class=\"accordion-body collapse in\">\n" +
+ " <div class=\"accordion-inner\">\n" +
+ " <span class=\"btn-group\" data-toggle=\"buttons-radio\">\n" +
+ " <button id=\"radioMin\" type=\"button\" class=\"btn \" >Min</button>\n" +
+ " <button id=\"radioHour\" type=\"button\" class=\"btn \">Hour</button>\n" +
+ " <button id=\"radioWeek\" type=\"button\" class=\"btn \">Week</button>\n" +
+ " <button id=\"radioMonth\" type=\"button\" class=\"btn \">Month</button>\n" +
+ " <button id=\"radioYear\" type=\"button\" class=\"btn \">Year</button>\n" +
+ " </span>\n" +
+ " <input id=\"dateRange\" style=\"margin-left:30px;width:280px;\" type=\"text\"/>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n"+
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
+ divAndSvgDefs.append("</svg></div>");
+ HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
+ graph.setWidth100();
+ graph.setHeight(65);
+ addMember(graph);
+ new Timer(){
+ @Override
+ public void run() {
+ attachGraphDateRangeEditorButtonGroupHandlers();
+ }
+ }.schedule(400);
+ }
+
+ public native void attachGraphDateRangeEditorButtonGroupHandlers() /*-{
+ console.log("Draw GraphDateTimeRangeEditor");
+ console.warn("Registering Handlers");
+
+ function updateDateDisplay(startDate, endDate ) {
+ var formattedDateRange;
+
+ if (isSameDay(startDate, endDate) && isSameMonth(startDate, endDate) && isSameYear(startDate, endDate)) {
+ // no need to display date only time
+ formattedDateRange = startDate.format('ddd') + ': ' + startDate.format('h:mm a') + ' - ' + endDate.format('h:mm a');
+ } else {
+ formattedDateRange = startDate.format('MM/DD/YYYY h:mm a') + ' - ' + endDate.format('MM/DD/YYYY h:mm a');
+ }
+ $wnd.jQuery('#dateRange').val(formattedDateRange);
+ }
+
+ function isSameDay(startDate, endDate) {
+ return (startDate.date() === endDate.date());
+ }
+ function isSameMonth(startDate, endDate) {
+ return (startDate.month() === endDate.month());
+ }
+ function isSameYear(startDate, endDate) {
+ return (startDate.year() === endDate.year());
+ }
+
+ var graphDateContext = new $wnd.GraphDateContext($wnd.moment().startOf('day'), $wnd.moment() );
+
+
+ $wnd.jQuery("#radioMin").bind('click', function (event) {
+ console.warn("minute selected");
+ graphDateContext.startDate = $wnd.moment().startOf('hour');
+ updateDateDisplay(graphDateContext);
+ });
+ $wnd.jQuery("#radioHour").bind('click', function (event) {
+ console.log("Hour selected");
+ graphDateContext.startDate = $wnd.moment().startOf('hour');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioWeek").bind('click', function (event) {
+ console.log("Week selected");
+ graphDateContext.startDate = $wnd.moment().startOf('week');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioMonth").bind('click', function (event) {
+ console.log("month selected");
+ graphDateContext.startDate = $wnd.moment().startOf('month');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+ $wnd.jQuery("#radioYear").bind('click', function (event) {
+ console.log("year selected");
+ graphDateContext.startDate = $wnd.moment().startOf('year');
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ });
+
+ // initially populate
+ updateDateDisplay(graphDateContext.startDate, graphDateContext.endDate);
+ $wnd.jQuery("#radioHour").click();
+
+ }-*/;
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ removeMembers(getMembers());
+ createGraphMarker();
+ }
+
+ @Override
+ public void parentResized() {
+ super.parentResized();
+ removeMembers(getMembers());
+ createGraphMarker();
+ drawJsniChart();
+ }
+
+
+ /**
+ * Delegate the call to rendering the JSNI chart.
+ * This way the chart type can be swapped out at any time.
+ */
+ public void drawJsniChart() {
+ graphDateTimeRangeEditor.drawJsniChart();
+ }
+
+
+ public Long getStartTime() {
+ return measurementUserPreferences.getMetricRangePreferences().begin;
+ }
+
+// public void setStartTime(Long startTime) {
+// this.startTime = startTime;
+// }
+
+ public Long getEndTime() {
+ return measurementUserPreferences.getMetricRangePreferences().end;
+ }
+
+// public void setEndTime(Long endTime) {
+// this.endTime = endTime;
+// }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/JQueryDateTimeRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/JQueryDateTimeRangeEditor.java
new file mode 100644
index 0000000..656e47a
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/JQueryDateTimeRangeEditor.java
@@ -0,0 +1,260 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+
+/**
+ * An implementation using JQuery UI components because smartGWT doesn't contain buttonsets or dual range sliders.
+ *
+ * @author Mike Thompson
+ */
+public class JQueryDateTimeRangeEditor {
+ private static Messages MSG = CoreGUI.getMessages();
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw GraphDateTimeRangeEditor");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(8)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.log("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+ })
+ .attr("height", function (d) {
+ return 10;
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("fill", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text(availChartContext.chartTitle);
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartUpLabel);
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text(availChartContext.chartDownLabel);
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart);
+
+ return '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+
+ }
+
+ return {
+ // Public API
+ draw: function (availChartContext) {
+ "use strict";
+ console.log("AvailabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java
index 94a935f..b18e91a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricGraphData.java
@@ -71,10 +71,7 @@ public class MetricGraphData implements JsonMetricProducer {
private MeasurementOOBComposite lastOOB;
private Integer chartHeight;
private boolean isPortalGraph;
- /**
- * WindowWidth is used in determining what size graph to display in the dashboard portlets.
- */
- //private Integer windowWidth;
+
private MetricGraphData(int portalId) {
isPortalGraph = true;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
deleted file mode 100644
index a2de9c6..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
-
-/**
- * Contains the chart definition for a MultiLine Graph.
- *
- * @author Mike Thompson
- */
-public final class MetricNvd3BarChartGraph extends AbstractGraph
-{
- /**
- * General constructor for stacked bar graph when you have all the data needed to
- * produce the graph. (This is true for all cases but the dashboard portlet).
- */
- public MetricNvd3BarChartGraph(MetricGraphData metricGraphData){
- setMetricGraphData(metricGraphData);
- }
-
-
- /**
- * The magic JSNI to draw the charts with d3.
- */
- public native void drawJsniChart() /*-{
- console.log("Draw NVD3 Bar jsni chart");
- console.time("multiChart");
- var global = this,
- chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartId()(),
- chartHandle = "#rChart-"+chartId,
- chartSelection = chartHandle + " svg",
- json = $wnd.jQuery.parseJSON(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getJsonMetrics()()),
- yAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartTitle()(),
- yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getYAxisUnits()(),
- xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getXAxisTitle()(),
- displayDayOfWeek = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::shouldDisplayDayOfWeekInXAxisLabel()(),
- xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I : %M %p",
-
- // nvd3 defines their json models a standard way (same model for other graphs)
- data = function() {
- return [
- {
- values: json,
- key: yAxisLabel ,
- color: '#ff7f0e'
- }
- ];
- };
- $wnd.nv.addGraph(function() {
- var chart = $wnd.nv.models.multiBarChart()
- .showControls(true)
- .tooltips(true);
-
- chart.xAxis.axisLabel(xAxisLabel)
- .tickFormat(function(d) { return $wnd.d3.time.format(xAxisTimeFormat)(new Date(d)) });
-
- chart.yAxis
- .axisLabel(yAxisUnits)
- .tickFormat($wnd.d3.format(',f'));
-
- $wnd.d3.select(chartSelection)
- .datum(data())
- .transition().duration(300)
- .call(chart);
-
- $wnd.nv.utils.windowResize(chart.update);
-
- return chart;
- });
- console.timeEnd("multiChart")
-
- }-*/;
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3MultiLineGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3MultiLineGraph.java
new file mode 100644
index 0000000..4928522
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3MultiLineGraph.java
@@ -0,0 +1,89 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+
+/**
+ * Contains the chart definition for a MultiLine Graph.
+ *
+ * @author Mike Thompson
+ */
+public final class MetricNvd3MultiLineGraph extends AbstractGraph
+{
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to
+ * produce the graph. (This is true for all cases but the dashboard portlet).
+ */
+ public MetricNvd3MultiLineGraph(MetricGraphData metricGraphData){
+ setMetricGraphData(metricGraphData);
+ }
+
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw NVD3 Bar jsni chart");
+ console.time("multiChart");
+ var global = this,
+ chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartId()(),
+ chartHandle = "#rChart-"+chartId,
+ chartSelection = chartHandle + " svg",
+ json = $wnd.jQuery.parseJSON(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getJsonMetrics()()),
+ yAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartTitle()(),
+ yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getYAxisUnits()(),
+ xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getXAxisTitle()(),
+ displayDayOfWeek = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::shouldDisplayDayOfWeekInXAxisLabel()(),
+ xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I : %M %p",
+
+ // nvd3 defines their json models a standard way (same model for other graphs)
+ data = function() {
+ return [
+ {
+ values: json,
+ key: yAxisLabel ,
+ color: '#ff7f0e'
+ }
+ ];
+ };
+ $wnd.nv.addGraph(function() {
+ var chart = $wnd.nv.models.multiBarChart()
+ .showControls(true)
+ .tooltips(true);
+
+ chart.xAxis.axisLabel(xAxisLabel)
+ .tickFormat(function(d) { return $wnd.d3.time.format(xAxisTimeFormat)(new Date(d)) });
+
+ chart.yAxis
+ .axisLabel(yAxisUnits)
+ .tickFormat($wnd.d3.format(',f'));
+
+ $wnd.d3.select(chartSelection)
+ .datum(data())
+ .transition().duration(300)
+ .call(chart);
+
+ $wnd.nv.utils.windowResize(chart.update);
+
+ return chart;
+ });
+ console.timeEnd("multiChart")
+
+ }-*/;
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index 7691c5f..7eea0dd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -41,12 +41,11 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3Graph;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch;
@@ -73,9 +72,9 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
destroyMembers();
- addMember(measurementRangeEditor);
+ addMember(graphDateTimeRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3Graph(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
+ availabilityGraph = new AvailabilityD3GraphView(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
@@ -102,8 +101,8 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
*/
private void buildGraphs() {
- queryAvailability(EntityContext.forGroup(resourceGroup), measurementRangeEditor.getStartTime(),
- measurementRangeEditor.getEndTime(), null);
+ queryAvailability(EntityContext.forGroup(resourceGroup), graphDateTimeRangeEditor.getStartTime(),
+ graphDateTimeRangeEditor.getEndTime(), null);
ResourceTypeRepository.Cache.getInstance().getResourceTypes(resourceGroup.getResourceType().getId(),
EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
@@ -130,7 +129,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
}
GWTServiceLookup.getMeasurementDataService().findDataForCompatibleGroup(resourceGroup.getId(),
- measDefIdArray, measurementRangeEditor.getStartTime(), measurementRangeEditor.getEndTime(), 60,
+ measDefIdArray, graphDateTimeRangeEditor.getStartTime(), graphDateTimeRangeEditor.getEndTime(), 60,
new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
@Override
public void onFailure(Throwable caught) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 58d3050..63e1f93 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -43,14 +43,13 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphWithSliderType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.GraphDateTimeRangeEditor;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3Graph;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.async.Command;
@@ -113,13 +112,14 @@ public class D3GraphListView extends AbstractD3GraphListView {
}
private void commonConstructorSettings() {
- measurementRangeEditor = new UserPreferencesMeasurementRangeEditor();
+ graphDateTimeRangeEditor = new GraphDateTimeRangeEditor(measurementUserPrefs);
setOverflow(Overflow.HIDDEN);
}
+ @Deprecated
public void addSetButtonClickHandler(ClickHandler clickHandler) {
- Log.debug("measurementRangeEditor " + measurementRangeEditor);
- measurementRangeEditor.getSetButton().addClickHandler(clickHandler);
+ Log.debug("measurementRangeEditor " + graphDateTimeRangeEditor);
+ // graphDateTimeRangeEditor.getSetButton().addClickHandler(clickHandler);
}
@Override
@@ -128,10 +128,10 @@ public class D3GraphListView extends AbstractD3GraphListView {
Log.debug("D3GraphListView.onDraw() for: " + resource.getName());
destroyMembers();
- addMember(measurementRangeEditor);
+ addMember(graphDateTimeRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3Graph(new AvailabilityOverUnderGraphType(resource.getId()));
+ availabilityGraph = new AvailabilityD3GraphView(new AvailabilityOverUnderGraphWithSliderType(resource.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
@@ -191,8 +191,8 @@ public class D3GraphListView extends AbstractD3GraphListView {
private void buildGraphs() {
final long startTimer = System.currentTimeMillis();
- queryAvailability(EntityContext.forResource(resource.getId()), measurementRangeEditor.getStartTime(),
- measurementRangeEditor.getEndTime(), null);
+ queryAvailability(EntityContext.forResource(resource.getId()), graphDateTimeRangeEditor.getStartTime(),
+ graphDateTimeRangeEditor.getEndTime(), null);
ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(),
EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
@@ -267,7 +267,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
private void queryMetricData(final int[] measDefIdArray, final CountDownLatch countDownLatch) {
GWTServiceLookup.getMeasurementDataService().findDataForResource(resource.getId(), measDefIdArray,
- measurementRangeEditor.getStartTime(), measurementRangeEditor.getEndTime(), 60,
+ graphDateTimeRangeEditor.getStartTime(), graphDateTimeRangeEditor.getEndTime(), 60,
new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
@Override
public void onFailure(Throwable caught) {
@@ -371,7 +371,6 @@ public class D3GraphListView extends AbstractD3GraphListView {
MetricGraphData metricGraphData = MetricGraphData.createForResource(resource.getId(), resource.getName(),
measurementDefinition, data, measurementOOBCompositeList );
- //StackedBarMetricGraphImpl graph = new StackedBarMetricGraphImpl(metricGraphData);
StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
graph.setMetricGraphData(metricGraphData);
MetricD3GraphView graphView = new MetricD3GraphView(graph);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
deleted file mode 100644
index ca8b117..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail;
-
-import java.util.List;
-
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityGraph;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-
-/**
- * A special graph implementation just for representing Availability (with hovers) for
- * a resource or resource group.
- *
- * @author Mike Thompson
- */
-public class AvailabilityD3Graph extends EnhancedVLayout implements AvailabilityGraph {
-
- protected AvailabilityOverUnderGraphType availabilityGraphType;
-
- public AvailabilityD3Graph(AvailabilityOverUnderGraphType graphType) {
- super();
- this.availabilityGraphType = graphType;
- setHeight(65);
- setWidth100();
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- removeMembers(getMembers());
- createGraphMarker();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- createGraphMarker();
- drawJsniChart();
- }
-
- public void setAvailabilityList(List<Availability> availabilityList) {
- availabilityGraphType.setAvailabilityList(availabilityList);
- }
-
- public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
- availabilityGraphType.setGroupAvailabilityList(groupAvailabilityList);
- }
-
- /**
- * Setup the page elements especially the div and svg elements that serve as
- * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
- * Later the drawJsniGraph() is called to actually fill in the div/svg element
- * created here with the actual svg element.
- *
- */
-
- public void createGraphMarker() {
- Log.debug("drawGraph marker in AvailabilityD3Graph for: " + availabilityGraphType.getChartId());
-
- StringBuilder divAndSvgDefs = new StringBuilder();
- divAndSvgDefs.append("<div id=\"availChart-" + availabilityGraphType.getChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
- divAndSvgDefs.append(getSvgDefs());
- divAndSvgDefs.append("</svg></div>");
- HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
- graph.setWidth100();
- graph.setHeight(65);
- addMember(graph);
-
- }
-
- /**
- * Svg definitions for patterns and gradients to use on SVG shapes.
- * @return xml String
- */
- private static String getSvgDefs() {
- return " <defs>"+
- "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" width=\"4\" height=\"4\"> <path d=\"M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2\" /> </pattern>"
- + "</defs>";
- }
-
- @Override
- public void destroy() {
- super.destroy();
- }
-
- @Override
- public void hide() {
- super.hide();
- }
-
- /**
- * Delegate the call to rendering the JSNI chart.
- * This way the chart type can be swapped out at any time.
- */
- public void drawJsniChart() {
- availabilityGraphType.drawJsniChart();
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
new file mode 100644
index 0000000..dc70645
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java
@@ -0,0 +1,122 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail;
+
+import java.util.List;
+
+import com.smartgwt.client.widgets.HTMLFlow;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityGraphType;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+
+/**
+ * A special graph implementation just for representing Availability (with hovers) for
+ * a resource or resource group.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityD3GraphView extends EnhancedVLayout {
+
+ protected AvailabilityGraphType availabilityGraphType;
+
+ public AvailabilityD3GraphView(AvailabilityGraphType availabilityGraphType) {
+ super();
+ this.availabilityGraphType = availabilityGraphType;
+ setHeight(65);
+ setWidth100();
+ }
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ removeMembers(getMembers());
+ createGraphMarker();
+ }
+
+ @Override
+ public void parentResized() {
+ super.parentResized();
+ removeMembers(getMembers());
+ createGraphMarker();
+ drawJsniChart();
+ }
+
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ availabilityGraphType.setAvailabilityList(availabilityList);
+ }
+
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ availabilityGraphType.setGroupAvailabilityList(groupAvailabilityList);
+ }
+
+ /**
+ * Setup the page elements especially the div and svg elements that serve as
+ * placeholders for the d3 stuff to grab onto and add svg tags to render the chart.
+ * Later the drawJsniGraph() is called to actually fill in the div/svg element
+ * created here with the actual svg element.
+ *
+ */
+
+ public void createGraphMarker() {
+ Log.debug("drawGraph marker in AvailabilityD3Graph for: " + availabilityGraphType.getChartId());
+
+ StringBuilder divAndSvgDefs = new StringBuilder();
+ divAndSvgDefs.append("<div id=\"availChart-" + availabilityGraphType.getChartId()
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
+ divAndSvgDefs.append(getSvgDefs());
+ divAndSvgDefs.append("</svg></div>");
+ HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
+ graph.setWidth100();
+ graph.setHeight(65);
+ addMember(graph);
+
+ }
+
+ /**
+ * Svg definitions for patterns and gradients to use on SVG shapes.
+ * @return xml String
+ */
+ private static String getSvgDefs() {
+ return " <defs>"+
+ "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" width=\"4\" height=\"4\"> <path d=\"M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2\" /> </pattern>"
+ + "</defs>";
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ }
+
+ @Override
+ public void hide() {
+ super.hide();
+ }
+
+ /**
+ * Delegate the call to rendering the JSNI chart.
+ * This way the chart type can be swapped out at any time.
+ */
+ public void drawJsniChart() {
+ availabilityGraphType.drawJsniChart();
+ }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index d5ae804..a19d47a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -50,10 +50,10 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
+ <script src="/coregui/js/moment.min.js"/>
+ <script src="/coregui/js/rhq.js"/>
<!-- External javascript libraries -->
- <!-- jquery.sparkline requires jquery. We don't explicitly provide jquery here because it is already
- embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 2.4.2 requires
- the version of jquery (1.7.2).
+ <!-- jquery.sparkline requires jquery.
-->
<script src="/coregui/js/jquery-1.7.2.min.js"/>
<script src="/coregui/js/jquery.sparkline-2.1.min.js"/>
@@ -61,6 +61,9 @@
<script src="/coregui/js/nv.d3.js"/>
<script src="/coregui/js/jquery.tipsy.js"/>
+ <!-- for d3 dual slider control only -->
+ <script src="/coregui/js/bootstrap.min.js" />
+
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 430365f..47700bf 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -10,15 +10,14 @@
<!-- support internationalized characters -->
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
-
<link rel="stylesheet" href="CoreGUI.css">
<!-- for d3 charting -->
<link rel="stylesheet" href="css/nv.d3.css">
<link rel="stylesheet" href="css/tipsy.css">
<link rel="stylesheet" href="css/charts.css">
+
<!-- for d3 dual slider control -->
- <link rel="stylesheet" href="css/jquery-ui-1.10.3.custom.css">
- <link href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css">
+ <link rel="stylesheet" href="css/bootstrap.min.css" >
<script type="text/javascript">
var search = location.search;
@@ -29,9 +28,7 @@
lang = lang.replace("-", "_");
document.write("<meta name='gwt:property' content='locale="+lang +"'>");
}
- jQuery(function () {
- jQuery("#dateRangeRadio").buttonset();
- });
+
</script>
<title>RHQ</title>
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.css b/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.css
new file mode 100755
index 0000000..e5e2ce3
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.css
@@ -0,0 +1,766 @@
+/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+.clearfix {
+ *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+ display: table;
+ content: "";
+ line-height: 0;
+}
+
+.clearfix:after {
+ clear: both;
+}
+
+.hide-text {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+
+.input-block-level {
+ display: block;
+ width: 100%;
+ min-height: 30px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.btn {
+ display: inline-block;
+ *display: inline;
+ /* IE7 inline-block hack */
+
+ *zoom: 1;
+ padding: 4px 12px;
+ margin-bottom: 0;
+ font-size: 14px;
+ line-height: 20px;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ color: #333333;
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
+ background-color: #f5f5f5;
+ background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+ background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
+ border-color: #e6e6e6 #e6e6e6 #bfbfbf;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ *background-color: #e6e6e6;
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
+
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+ border: 1px solid #cccccc;
+ *border: 0;
+ border-bottom-color: #b3b3b3;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ *margin-left: .3em;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
+}
+
+.btn:hover,
+.btn:focus,
+.btn:active,
+.btn.active,
+.btn.disabled,
+.btn[disabled] {
+ color: #333333;
+ background-color: #e6e6e6;
+ *background-color: #d9d9d9;
+}
+
+.btn:active,
+.btn.active {
+ background-color: #cccccc \9;
+}
+
+.btn:first-child {
+ *margin-left: 0;
+}
+
+.btn:hover,
+.btn:focus {
+ color: #333333;
+ text-decoration: none;
+ background-position: 0 -15px;
+ -webkit-transition: background-position 0.1s linear;
+ -moz-transition: background-position 0.1s linear;
+ -o-transition: background-position 0.1s linear;
+ transition: background-position 0.1s linear;
+}
+
+.btn:focus {
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+.btn.active,
+.btn:active {
+ background-image: none;
+ outline: 0;
+ -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
+ -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
+}
+
+.btn.disabled,
+.btn[disabled] {
+ cursor: default;
+ background-image: none;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+}
+
+.btn-large {
+ padding: 11px 19px;
+ font-size: 17.5px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.btn-large [class^="icon-"],
+.btn-large [class*=" icon-"] {
+ margin-top: 4px;
+}
+
+.btn-small {
+ padding: 2px 10px;
+ font-size: 11.9px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.btn-small [class^="icon-"],
+.btn-small [class*=" icon-"] {
+ margin-top: 0;
+}
+
+.btn-mini [class^="icon-"],
+.btn-mini [class*=" icon-"] {
+ margin-top: -1px;
+}
+
+.btn-mini {
+ padding: 0 6px;
+ font-size: 10.5px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.btn-block {
+ display: block;
+ width: 100%;
+ padding-left: 0;
+ padding-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-inverse.active {
+ color: rgba(255, 255, 255, 0.75);
+}
+
+.btn-primary {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #006dcc;
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+ background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
+ border-color: #0044cc #0044cc #002a80;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ *background-color: #0044cc;
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
+
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.btn-primary.disabled,
+.btn-primary[disabled] {
+ color: #ffffff;
+ background-color: #0044cc;
+ *background-color: #003bb3;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+ background-color: #003399 \9;
+}
+
+.btn-warning {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #faa732;
+ background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+ background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+ background-image: -o-linear-gradient(top, #fbb450, #f89406);
+ background-image: linear-gradient(to bottom, #fbb450, #f89406);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+ border-color: #f89406 #f89406 #ad6704;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ *background-color: #f89406;
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
+
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.btn-warning.disabled,
+.btn-warning[disabled] {
+ color: #ffffff;
+ background-color: #f89406;
+ *background-color: #df8505;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+ background-color: #c67605 \9;
+}
+
+.btn-danger {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #da4f49;
+ background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
+ border-color: #bd362f #bd362f #802420;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ *background-color: #bd362f;
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
+
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.btn-danger.disabled,
+.btn-danger[disabled] {
+ color: #ffffff;
+ background-color: #bd362f;
+ *background-color: #a9302a;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+ background-color: #942a25 \9;
+}
+
+.btn-success {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #5bb75b;
+ background-image: -moz-linear-gradient(top, #62c462, #51a351);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
+ background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+ background-image: -o-linear-gradient(top, #62c462, #51a351);
+ background-image: linear-gradient(to bottom, #62c462, #51a351);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
+ border-color: #51a351 #51a351 #387038;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ *background-color: #51a351;
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
+
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.btn-success.disabled,
+.btn-success[disabled] {
+ color: #ffffff;
+ background-color: #51a351;
+ *background-color: #499249;
+}
+
+.btn-success:active,
+.btn-success.active {
+ background-color: #408140 \9;
+}
+
+.btn-info {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #49afcd;
+ background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
+ background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
+ border-color: #2f96b4 #2f96b4 #1f6377;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ *background-color: #2f96b4;
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
+
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.btn-info.disabled,
+.btn-info[disabled] {
+ color: #ffffff;
+ background-color: #2f96b4;
+ *background-color: #2a85a0;
+}
+
+.btn-info:active,
+.btn-info.active {
+ background-color: #24748c \9;
+}
+
+.btn-inverse {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #363636;
+ background-image: -moz-linear-gradient(top, #444444, #222222);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
+ background-image: -webkit-linear-gradient(top, #444444, #222222);
+ background-image: -o-linear-gradient(top, #444444, #222222);
+ background-image: linear-gradient(to bottom, #444444, #222222);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
+ border-color: #222222 #222222 #000000;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ *background-color: #222222;
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
+
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-inverse:hover,
+.btn-inverse:focus,
+.btn-inverse:active,
+.btn-inverse.active,
+.btn-inverse.disabled,
+.btn-inverse[disabled] {
+ color: #ffffff;
+ background-color: #222222;
+ *background-color: #151515;
+}
+
+.btn-inverse:active,
+.btn-inverse.active {
+ background-color: #080808 \9;
+}
+
+button.btn,
+input[type="submit"].btn {
+ *padding-top: 3px;
+ *padding-bottom: 3px;
+}
+
+button.btn::-moz-focus-inner,
+input[type="submit"].btn::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+
+button.btn.btn-large,
+input[type="submit"].btn.btn-large {
+ *padding-top: 7px;
+ *padding-bottom: 7px;
+}
+
+button.btn.btn-small,
+input[type="submit"].btn.btn-small {
+ *padding-top: 3px;
+ *padding-bottom: 3px;
+}
+
+button.btn.btn-mini,
+input[type="submit"].btn.btn-mini {
+ *padding-top: 1px;
+ *padding-bottom: 1px;
+}
+
+.btn-link,
+.btn-link:active,
+.btn-link[disabled] {
+ background-color: transparent;
+ background-image: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+}
+
+.btn-link {
+ border-color: transparent;
+ cursor: pointer;
+ color: #0088cc;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-link:hover,
+.btn-link:focus {
+ color: #005580;
+ text-decoration: underline;
+ background-color: transparent;
+}
+
+.btn-link[disabled]:hover,
+.btn-link[disabled]:focus {
+ color: #333333;
+ text-decoration: none;
+}
+
+.btn-group {
+ position: relative;
+ display: inline-block;
+ *display: inline;
+ /* IE7 inline-block hack */
+
+ *zoom: 1;
+ font-size: 0;
+ vertical-align: middle;
+ white-space: nowrap;
+ *margin-left: .3em;
+}
+
+.btn-group:first-child {
+ *margin-left: 0;
+}
+
+.btn-group + .btn-group {
+ margin-left: 5px;
+}
+
+.btn-toolbar {
+ font-size: 0;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+.btn-toolbar > .btn + .btn,
+.btn-toolbar > .btn-group + .btn,
+.btn-toolbar > .btn + .btn-group {
+ margin-left: 5px;
+}
+
+.btn-group > .btn {
+ position: relative;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-group > .btn + .btn {
+ margin-left: -1px;
+}
+
+.btn-group > .btn,
+.btn-group > .dropdown-menu,
+.btn-group > .popover {
+ font-size: 12px;
+}
+
+.btn-group > .btn-mini {
+ font-size: 10.5px;
+}
+
+.btn-group > .btn-small {
+ font-size: 11.9px;
+}
+
+.btn-group > .btn-large {
+ font-size: 17.5px;
+}
+
+.btn-group > .btn:first-child {
+ margin-left: 0;
+ -webkit-border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+ border-top-left-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ border-bottom-left-radius: 4px;
+}
+
+.btn-group > .btn:last-child,
+.btn-group > .dropdown-toggle {
+ -webkit-border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+ border-bottom-right-radius: 4px;
+}
+
+.btn-group > .btn.large:first-child {
+ margin-left: 0;
+ -webkit-border-top-left-radius: 6px;
+ -moz-border-radius-topleft: 6px;
+ border-top-left-radius: 6px;
+ -webkit-border-bottom-left-radius: 6px;
+ -moz-border-radius-bottomleft: 6px;
+ border-bottom-left-radius: 6px;
+}
+
+.btn-group > .btn.large:last-child,
+.btn-group > .large.dropdown-toggle {
+ -webkit-border-top-right-radius: 6px;
+ -moz-border-radius-topright: 6px;
+ border-top-right-radius: 6px;
+ -webkit-border-bottom-right-radius: 6px;
+ -moz-border-radius-bottomright: 6px;
+ border-bottom-right-radius: 6px;
+}
+
+.btn-group > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group > .btn:active,
+.btn-group > .btn.active {
+ z-index: 2;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+
+.btn-group > .btn + .dropdown-toggle {
+ padding-left: 8px;
+ padding-right: 8px;
+ -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, .125), inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
+ -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, .125), inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: inset 1px 0 0 rgba(255, 255, 255, .125), inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
+ *padding-top: 5px;
+ *padding-bottom: 5px;
+}
+
+.btn-group > .btn-mini + .dropdown-toggle {
+ padding-left: 5px;
+ padding-right: 5px;
+ *padding-top: 2px;
+ *padding-bottom: 2px;
+}
+
+.btn-group > .btn-small + .dropdown-toggle {
+ *padding-top: 5px;
+ *padding-bottom: 4px;
+}
+
+.btn-group > .btn-large + .dropdown-toggle {
+ padding-left: 12px;
+ padding-right: 12px;
+ *padding-top: 7px;
+ *padding-bottom: 7px;
+}
+
+.btn-group.open .dropdown-toggle {
+ background-image: none;
+ -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
+ -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05);
+}
+
+.btn-group.open .btn.dropdown-toggle {
+ background-color: #e6e6e6;
+}
+
+.btn-group.open .btn-primary.dropdown-toggle {
+ background-color: #0044cc;
+}
+
+.btn-group.open .btn-warning.dropdown-toggle {
+ background-color: #f89406;
+}
+
+.btn-group.open .btn-danger.dropdown-toggle {
+ background-color: #bd362f;
+}
+
+.btn-group.open .btn-success.dropdown-toggle {
+ background-color: #51a351;
+}
+
+.btn-group.open .btn-info.dropdown-toggle {
+ background-color: #2f96b4;
+}
+
+.btn-group.open .btn-inverse.dropdown-toggle {
+ background-color: #222222;
+}
+
+.btn .caret {
+ margin-top: 8px;
+ margin-left: 0;
+}
+
+.btn-large .caret {
+ margin-top: 6px;
+}
+
+.btn-large .caret {
+ border-left-width: 5px;
+ border-right-width: 5px;
+ border-top-width: 5px;
+}
+
+.btn-mini .caret,
+.btn-small .caret {
+ margin-top: 8px;
+}
+
+.dropup .btn-large .caret {
+ border-bottom-width: 5px;
+}
+
+.btn-primary .caret,
+.btn-warning .caret,
+.btn-danger .caret,
+.btn-info .caret,
+.btn-success .caret,
+.btn-inverse .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+}
+
+.btn-group-vertical {
+ display: inline-block;
+ *display: inline;
+ /* IE7 inline-block hack */
+
+ *zoom: 1;
+}
+
+.btn-group-vertical > .btn {
+ display: block;
+ float: none;
+ max-width: 100%;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-group-vertical > .btn + .btn {
+ margin-left: 0;
+ margin-top: -1px;
+}
+
+.btn-group-vertical > .btn:first-child {
+ -webkit-border-radius: 4px 4px 0 0;
+ -moz-border-radius: 4px 4px 0 0;
+ border-radius: 4px 4px 0 0;
+}
+
+.btn-group-vertical > .btn:last-child {
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+}
+
+.btn-group-vertical > .btn-large:first-child {
+ -webkit-border-radius: 6px 6px 0 0;
+ -moz-border-radius: 6px 6px 0 0;
+ border-radius: 6px 6px 0 0;
+}
+
+.btn-group-vertical > .btn-large:last-child {
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
+}
+
+.accordion {
+ margin-bottom: 20px;
+}
+
+.accordion-group {
+ margin-bottom: 2px;
+ border: 1px solid #e5e5e5;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.accordion-heading {
+ border-bottom: 0;
+}
+
+.accordion-heading .accordion-toggle {
+ display: block;
+ padding: 8px 15px;
+}
+
+.accordion-toggle {
+ cursor: pointer;
+}
+
+.accordion-inner {
+ padding: 9px 15px;
+ border-top: 1px solid #e5e5e5;
+}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.min.css b/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.min.css
new file mode 100755
index 0000000..4d7b8c7
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/bootstrap.min.css
@@ -0,0 +1,96 @@
+/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;}
+.clearfix:after{clear:both;}
+.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}
+.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
+.btn{display:inline-block;*display:inline;*zoom:1;padding:4px 12px;margin-bottom:0;font-size:14px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#333333;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #ffffff, #e6e6e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(top, #ffffff, #e6e6e6);background-image:-o-linear-gradient(top, #ffffff, #e6e6e6);background-image:linear-gradient(to bottom, #ffffff, #e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #cccccc;*border:0;border-bottom-color:#b
3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333333;background-color:#e6e6e6;*background-color:#d9d9d9;}
+.btn:active,.btn.active{background-color:#cccccc \9;}
+.btn:first-child{*margin-left:0;}
+.btn:hover,.btn:focus{color:#333333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;}
+.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
+.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
+.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
+.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px;}
+.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0;}
+.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px;}
+.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+.btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
+.btn-block+.btn-block{margin-top:5px;}
+input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;}
+.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255, 255, 255, 0.75);}
+.btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(to bottom, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#0044cc;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#ffffff;background-color:#0044cc;*background-color:#003bb3;}
+.btn-primary:active,.btn-primary.active{background-color:#003399 \9;}
+.btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#ffffff;background-color:#f89406;*background-color:#df8505;}
+.btn-warning:active,.btn-warning.active{background-color:#c67605 \9;}
+.btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(to bottom, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#ffffff;background-color:#bd362f;*background-color:#a9302a;}
+.btn-danger:active,.btn-danger.active{background-color:#942a25 \9;}
+.btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(to bottom, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#ffffff;background-color:#51a351;*background-color:#499249;}
+.btn-success:active,.btn-success.active{background-color:#408140 \9;}
+.btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(to bottom, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#ffffff;background-color:#2f96b4;*background-color:#2a85a0;}
+.btn-info:active,.btn-info.active{background-color:#24748c \9;}
+.btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#363636;background-image:-moz-linear-gradient(top, #444444, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));background-image:-webkit-linear-gradient(top, #444444, #222222);background-image:-o-linear-gradient(top, #444444, #222222);background-image:linear-gradient(to bottom, #444444, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#222222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#ffffff;background-color:#222222;*background-color:#151515;}
+.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9;}
+button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}
+button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px;}
+button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px;}
+button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px;}
+.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn-link{border-color:transparent;cursor:pointer;color:#0088cc;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent;}
+.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333333;text-decoration:none;}
+.btn-group{position:relative;display:inline-block;*display:inline;*zoom:1;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em;}.btn-group:first-child{*margin-left:0;}
+.btn-group+.btn-group{margin-left:5px;}
+.btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px;}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px;}
+.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.btn-group>.btn+.btn{margin-left:-1px;}
+.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px;}
+.btn-group>.btn-mini{font-size:10.5px;}
+.btn-group>.btn-small{font-size:11.9px;}
+.btn-group>.btn-large{font-size:17.5px;}
+.btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
+.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
+.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
+.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
+.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2;}
+.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}
+.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);*padding-top:5px;*padding-bottom:5px;}
+.btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px;}
+.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px;}
+.btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px;}
+.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
+.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6;}
+.btn-group.open .btn-primary.dropdown-toggle{background-color:#0044cc;}
+.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406;}
+.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f;}
+.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351;}
+.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4;}
+.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222222;}
+.btn .caret{margin-top:8px;margin-left:0;}
+.btn-large .caret{margin-top:6px;}
+.btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px;}
+.btn-mini .caret,.btn-small .caret{margin-top:8px;}
+.dropup .btn-large .caret{border-bottom-width:5px;}
+.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.btn-group-vertical{display:inline-block;*display:inline;*zoom:1;}
+.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px;}
+.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}
+.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}
+.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0;}
+.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;}
+.accordion{margin-bottom:20px;}
+.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
+.accordion-heading{border-bottom:0;}
+.accordion-heading .accordion-toggle{display:block;padding:8px 15px;}
+.accordion-toggle{cursor:pointer;}
+.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.css b/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.css
deleted file mode 100755
index 569ed54..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.css
+++ /dev/null
@@ -1,924 +0,0 @@
-/*! jQuery UI - v1.10.3 - 2013-05-11
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerd...
lorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden {
- display: none;
-}
-.ui-helper-hidden-accessible {
- border: 0;
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-.ui-helper-reset {
- margin: 0;
- padding: 0;
- border: 0;
- outline: 0;
- line-height: 1.3;
- text-decoration: none;
- font-size: 100%;
- list-style: none;
-}
-.ui-helper-clearfix:before,
-.ui-helper-clearfix:after {
- content: "";
- display: table;
- border-collapse: collapse;
-}
-.ui-helper-clearfix:after {
- clear: both;
-}
-.ui-helper-clearfix {
- min-height: 0; /* support: IE7 */
-}
-.ui-helper-zfix {
- width: 100%;
- height: 100%;
- top: 0;
- left: 0;
- position: absolute;
- opacity: 0;
- filter:Alpha(Opacity=0);
-}
-
-.ui-front {
- z-index: 100;
-}
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled {
- cursor: default !important;
-}
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- display: block;
- text-indent: -99999px;
- overflow: hidden;
- background-repeat: no-repeat;
-}
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-.ui-button {
- display: inline-block;
- position: relative;
- padding: 0;
- line-height: normal;
- margin-right: .1em;
- cursor: pointer;
- vertical-align: middle;
- text-align: center;
- overflow: visible; /* removes extra width in IE */
-}
-.ui-button,
-.ui-button:link,
-.ui-button:visited,
-.ui-button:hover,
-.ui-button:active {
- text-decoration: none;
-}
-/* to make room for the icon, a width needs to be set here */
-.ui-button-icon-only {
- width: 2.2em;
-}
-/* button elements seem to need a little more width */
-button.ui-button-icon-only {
- width: 2.4em;
-}
-.ui-button-icons-only {
- width: 3.4em;
-}
-button.ui-button-icons-only {
- width: 3.7em;
-}
-
-/* button text element */
-.ui-button .ui-button-text {
- display: block;
- line-height: normal;
-}
-.ui-button-text-only .ui-button-text {
- padding: .4em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
- padding: .4em;
- text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 1em .4em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 2.1em .4em 1em;
-}
-.ui-button-text-icons .ui-button-text {
- padding-left: 2.1em;
- padding-right: 2.1em;
-}
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
- padding: .4em 1em;
-}
-
-/* button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-icons-only .ui-icon {
- position: absolute;
- top: 50%;
- margin-top: -8px;
-}
-.ui-button-icon-only .ui-icon {
- left: 50%;
- margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
- left: .5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
- right: .5em;
-}
-
-/* button sets */
-.ui-buttonset {
- margin-right: 7px;
-}
-.ui-buttonset .ui-button {
- margin-left: 0;
- margin-right: -.3em;
-}
-
-/* workarounds */
-/* reset extra padding in Firefox, see h5bp.com/l */
-input.ui-button::-moz-focus-inner,
-button.ui-button::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-.ui-datepicker {
- width: 17em;
- padding: .2em .2em 0;
- display: none;
-}
-.ui-datepicker .ui-datepicker-header {
- position: relative;
- padding: .2em 0;
-}
-.ui-datepicker .ui-datepicker-prev,
-.ui-datepicker .ui-datepicker-next {
- position: absolute;
- top: 2px;
- width: 1.8em;
- height: 1.8em;
-}
-.ui-datepicker .ui-datepicker-prev-hover,
-.ui-datepicker .ui-datepicker-next-hover {
- top: 1px;
-}
-.ui-datepicker .ui-datepicker-prev {
- left: 2px;
-}
-.ui-datepicker .ui-datepicker-next {
- right: 2px;
-}
-.ui-datepicker .ui-datepicker-prev-hover {
- left: 1px;
-}
-.ui-datepicker .ui-datepicker-next-hover {
- right: 1px;
-}
-.ui-datepicker .ui-datepicker-prev span,
-.ui-datepicker .ui-datepicker-next span {
- display: block;
- position: absolute;
- left: 50%;
- margin-left: -8px;
- top: 50%;
- margin-top: -8px;
-}
-.ui-datepicker .ui-datepicker-title {
- margin: 0 2.3em;
- line-height: 1.8em;
- text-align: center;
-}
-.ui-datepicker .ui-datepicker-title select {
- font-size: 1em;
- margin: 1px 0;
-}
-.ui-datepicker select.ui-datepicker-month-year {
- width: 100%;
-}
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year {
- width: 49%;
-}
-.ui-datepicker table {
- width: 100%;
- font-size: .9em;
- border-collapse: collapse;
- margin: 0 0 .4em;
-}
-.ui-datepicker th {
- padding: .7em .3em;
- text-align: center;
- font-weight: bold;
- border: 0;
-}
-.ui-datepicker td {
- border: 0;
- padding: 1px;
-}
-.ui-datepicker td span,
-.ui-datepicker td a {
- display: block;
- padding: .2em;
- text-align: right;
- text-decoration: none;
-}
-.ui-datepicker .ui-datepicker-buttonpane {
- background-image: none;
- margin: .7em 0 0 0;
- padding: 0 .2em;
- border-left: 0;
- border-right: 0;
- border-bottom: 0;
-}
-.ui-datepicker .ui-datepicker-buttonpane button {
- float: right;
- margin: .5em .2em .4em;
- cursor: pointer;
- padding: .2em .6em .3em .6em;
- width: auto;
- overflow: visible;
-}
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
- float: left;
-}
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi {
- width: auto;
-}
-.ui-datepicker-multi .ui-datepicker-group {
- float: left;
-}
-.ui-datepicker-multi .ui-datepicker-group table {
- width: 95%;
- margin: 0 auto .4em;
-}
-.ui-datepicker-multi-2 .ui-datepicker-group {
- width: 50%;
-}
-.ui-datepicker-multi-3 .ui-datepicker-group {
- width: 33.3%;
-}
-.ui-datepicker-multi-4 .ui-datepicker-group {
- width: 25%;
-}
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
- border-left-width: 0;
-}
-.ui-datepicker-multi .ui-datepicker-buttonpane {
- clear: left;
-}
-.ui-datepicker-row-break {
- clear: both;
- width: 100%;
- font-size: 0;
-}
-
-/* RTL support */
-.ui-datepicker-rtl {
- direction: rtl;
-}
-.ui-datepicker-rtl .ui-datepicker-prev {
- right: 2px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next {
- left: 2px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-prev:hover {
- right: 1px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next:hover {
- left: 1px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane {
- clear: right;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button {
- float: left;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
-.ui-datepicker-rtl .ui-datepicker-group {
- float: right;
-}
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
- border-right-width: 0;
- border-left-width: 1px;
-}
-.ui-slider {
- position: relative;
- text-align: left;
-}
-.ui-slider .ui-slider-handle {
- position: absolute;
- z-index: 2;
- width: 1.2em;
- height: 1.2em;
- cursor: default;
-}
-.ui-slider .ui-slider-range {
- position: absolute;
- z-index: 1;
- font-size: .7em;
- display: block;
- border: 0;
- background-position: 0 0;
-}
-
-/* For IE8 - See #6727 */
-.ui-slider.ui-state-disabled .ui-slider-handle,
-.ui-slider.ui-state-disabled .ui-slider-range {
- filter: inherit;
-}
-
-.ui-slider-horizontal {
- height: .8em;
-}
-.ui-slider-horizontal .ui-slider-handle {
- top: -.3em;
- margin-left: -.6em;
-}
-.ui-slider-horizontal .ui-slider-range {
- top: 0;
- height: 100%;
-}
-.ui-slider-horizontal .ui-slider-range-min {
- left: 0;
-}
-.ui-slider-horizontal .ui-slider-range-max {
- right: 0;
-}
-
-.ui-slider-vertical {
- width: .8em;
- height: 100px;
-}
-.ui-slider-vertical .ui-slider-handle {
- left: -.3em;
- margin-left: 0;
- margin-bottom: -.6em;
-}
-.ui-slider-vertical .ui-slider-range {
- left: 0;
- width: 100%;
-}
-.ui-slider-vertical .ui-slider-range-min {
- bottom: 0;
-}
-.ui-slider-vertical .ui-slider-range-max {
- top: 0;
-}
-.ui-spinner {
- position: relative;
- display: inline-block;
- overflow: hidden;
- padding: 0;
- vertical-align: middle;
-}
-.ui-spinner-input {
- border: none;
- background: none;
- color: inherit;
- padding: 0;
- margin: .2em 0;
- vertical-align: middle;
- margin-left: .4em;
- margin-right: 22px;
-}
-.ui-spinner-button {
- width: 16px;
- height: 50%;
- font-size: .5em;
- padding: 0;
- margin: 0;
- text-align: center;
- position: absolute;
- cursor: default;
- display: block;
- overflow: hidden;
- right: 0;
-}
-/* more specificity required here to overide default borders */
-.ui-spinner a.ui-spinner-button {
- border-top: none;
- border-bottom: none;
- border-right: none;
-}
-/* vertical centre icon */
-.ui-spinner .ui-icon {
- position: absolute;
- margin-top: -8px;
- top: 50%;
- left: 0;
-}
-.ui-spinner-up {
- top: 0;
-}
-.ui-spinner-down {
- bottom: 0;
-}
-
-/* TR overrides */
-.ui-spinner .ui-icon-triangle-1-s {
- /* need to fix icons sprite */
- background-position: -65px -16px;
-}
-.ui-tabs {
- position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
- padding: .2em;
-}
-.ui-tabs .ui-tabs-nav {
- margin: 0;
- padding: .2em .2em 0;
-}
-.ui-tabs .ui-tabs-nav li {
- list-style: none;
- float: left;
- position: relative;
- top: 0;
- margin: 1px .2em 0 0;
- border-bottom-width: 0;
- padding: 0;
- white-space: nowrap;
-}
-.ui-tabs .ui-tabs-nav li a {
- float: left;
- padding: .5em 1em;
- text-decoration: none;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active {
- margin-bottom: -1px;
- padding-bottom: 1px;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active a,
-.ui-tabs .ui-tabs-nav li.ui-state-disabled a,
-.ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
- cursor: text;
-}
-.ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
- cursor: pointer;
-}
-.ui-tabs .ui-tabs-panel {
- display: block;
- border-width: 0;
- padding: 1em 1.4em;
- background: none;
-}
-.ui-tooltip {
- padding: 8px;
- position: absolute;
- z-index: 9999;
- max-width: 300px;
- -webkit-box-shadow: 0 0 5px #aaa;
- box-shadow: 0 0 5px #aaa;
-}
-body .ui-tooltip {
- border-width: 2px;
-}
-
-/* Component containers
-----------------------------------*/
-.ui-widget {
- font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
- font-size: 1.1em;
-}
-.ui-widget .ui-widget {
- font-size: 1em;
-}
-.ui-widget input,
-.ui-widget select,
-.ui-widget textarea,
-.ui-widget button {
- font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
- font-size: 1em;
-}
-.ui-widget-content {
- border: 1px solid #dddddd;
- background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;
- color: #333333;
-}
-.ui-widget-content a {
- color: #333333;
-}
-.ui-widget-header {
- border: 1px solid #e78f08;
- background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;
- color: #ffffff;
- font-weight: bold;
-}
-.ui-widget-header a {
- color: #ffffff;
-}
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default,
-.ui-widget-content .ui-state-default,
-.ui-widget-header .ui-state-default {
- border: 1px solid #cccccc;
- background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;
- font-weight: bold;
- color: #1c94c4;
-}
-.ui-state-default a,
-.ui-state-default a:link,
-.ui-state-default a:visited {
- color: #1c94c4;
- text-decoration: none;
-}
-.ui-state-hover,
-.ui-widget-content .ui-state-hover,
-.ui-widget-header .ui-state-hover,
-.ui-state-focus,
-.ui-widget-content .ui-state-focus,
-.ui-widget-header .ui-state-focus {
- border: 1px solid #fbcb09;
- background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;
- font-weight: bold;
- color: #c77405;
-}
-.ui-state-hover a,
-.ui-state-hover a:hover,
-.ui-state-hover a:link,
-.ui-state-hover a:visited {
- color: #c77405;
- text-decoration: none;
-}
-.ui-state-active,
-.ui-widget-content .ui-state-active,
-.ui-widget-header .ui-state-active {
- border: 1px solid #fbd850;
- background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;
- font-weight: bold;
- color: #eb8f00;
-}
-.ui-state-active a,
-.ui-state-active a:link,
-.ui-state-active a:visited {
- color: #eb8f00;
- text-decoration: none;
-}
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight,
-.ui-widget-content .ui-state-highlight,
-.ui-widget-header .ui-state-highlight {
- border: 1px solid #fed22f;
- background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;
- color: #363636;
-}
-.ui-state-highlight a,
-.ui-widget-content .ui-state-highlight a,
-.ui-widget-header .ui-state-highlight a {
- color: #363636;
-}
-.ui-state-error,
-.ui-widget-content .ui-state-error,
-.ui-widget-header .ui-state-error {
- border: 1px solid #cd0a0a;
- background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;
- color: #ffffff;
-}
-.ui-state-error a,
-.ui-widget-content .ui-state-error a,
-.ui-widget-header .ui-state-error a {
- color: #ffffff;
-}
-.ui-state-error-text,
-.ui-widget-content .ui-state-error-text,
-.ui-widget-header .ui-state-error-text {
- color: #ffffff;
-}
-.ui-priority-primary,
-.ui-widget-content .ui-priority-primary,
-.ui-widget-header .ui-priority-primary {
- font-weight: bold;
-}
-.ui-priority-secondary,
-.ui-widget-content .ui-priority-secondary,
-.ui-widget-header .ui-priority-secondary {
- opacity: .7;
- filter:Alpha(Opacity=70);
- font-weight: normal;
-}
-.ui-state-disabled,
-.ui-widget-content .ui-state-disabled,
-.ui-widget-header .ui-state-disabled {
- opacity: .35;
- filter:Alpha(Opacity=35);
- background-image: none;
-}
-.ui-state-disabled .ui-icon {
- filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
-}
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- width: 16px;
- height: 16px;
-}
-.ui-icon,
-.ui-widget-content .ui-icon {
- background-image: url(images/ui-icons_222222_256x240.png);
-}
-.ui-widget-header .ui-icon {
- background-image: url(images/ui-icons_ffffff_256x240.png);
-}
-.ui-state-default .ui-icon {
- background-image: url(images/ui-icons_ef8c08_256x240.png);
-}
-.ui-state-hover .ui-icon,
-.ui-state-focus .ui-icon {
- background-image: url(images/ui-icons_ef8c08_256x240.png);
-}
-.ui-state-active .ui-icon {
- background-image: url(images/ui-icons_ef8c08_256x240.png);
-}
-.ui-state-highlight .ui-icon {
- background-image: url(images/ui-icons_228ef1_256x240.png);
-}
-.ui-state-error .ui-icon,
-.ui-state-error-text .ui-icon {
- background-image: url(images/ui-icons_ffd27a_256x240.png);
-}
-
-/* positioning */
-.ui-icon-blank { background-position: 16px 16px; }
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-on { background-position: -96px -144px; }
-.ui-icon-radio-off { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-left,
-.ui-corner-tl {
- border-top-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-right,
-.ui-corner-tr {
- border-top-right-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-left,
-.ui-corner-bl {
- border-bottom-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-right,
-.ui-corner-br {
- border-bottom-right-radius: 4px;
-}
-
-/* Overlays */
-.ui-widget-overlay {
- background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;
- opacity: .5;
- filter: Alpha(Opacity=50);
-}
-.ui-widget-shadow {
- margin: -5px 0 0 -5px;
- padding: 5px;
- background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;
- opacity: .2;
- filter: Alpha(Opacity=20);
- border-radius: 5px;
-}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.min.css b/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.min.css
deleted file mode 100755
index ab5191b..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.min.css
+++ /dev/null
@@ -1,5 +0,0 @@
-/*! jQuery UI - v1.10.3 - 2013-05-11
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerd...
lorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:
middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.
ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepi
cker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane
{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepic
ker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-
disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:0;background:0;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner
a.ui-spinner-button{border-top:0;border-bottom:0;border-right:0}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0}.ui-tooltip{padding:8px;pos
ition:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-st
ate-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;backgr
ound:#ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header
.ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_228ef1_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-
32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32
px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-a
rrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position
:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui
-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calcul
ator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-i
con-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-s
tart{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}
.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position
:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.js b/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.js
new file mode 100755
index 0000000..b5ca464
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.js
@@ -0,0 +1,165 @@
+/* ===================================================
+ * bootstrap-transition.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed 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.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+ * ======================================================= */
+
+ $(function () {
+
+ $.support.transition = (function () {
+
+ var transitionEnd = (function () {
+
+ var el = document.createElement('bootstrap')
+ , transEndEventNames = {
+ 'WebkitTransition' : 'webkitTransitionEnd'
+ , 'MozTransition' : 'transitionend'
+ , 'OTransition' : 'oTransitionEnd otransitionend'
+ , 'transition' : 'transitionend'
+ }
+ , name
+
+ for (name in transEndEventNames){
+ if (el.style[name] !== undefined) {
+ return transEndEventNames[name]
+ }
+ }
+
+ }())
+
+ return transitionEnd && {
+ end: transitionEnd
+ }
+
+ })()
+
+ })
+
+}(window.jQuery);
+/* ============================================================
+ * bootstrap-button.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed 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.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+ * ============================== */
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.button.defaults, options)
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ , $el = this.$element
+ , data = $el.data()
+ , val = $el.is('input') ? 'val' : 'html'
+
+ state = state + 'Text'
+ data.resetText || $el.data('resetText', $el[val]())
+
+ $el[val](data[state] || this.options[state])
+
+ // push to event loop to allow forms to submit
+ setTimeout(function () {
+ state == 'loadingText' ?
+ $el.addClass(d).attr(d, d) :
+ $el.removeClass(d).removeAttr(d)
+ }, 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+ $parent && $parent
+ .find('.active')
+ .removeClass('active')
+
+ this.$element.toggleClass('active')
+ }
+
+
+ /* BUTTON PLUGIN DEFINITION
+ * ======================== */
+
+ var old = $.fn.button
+
+ $.fn.button = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('button')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('button', (data = new Button(this, options)))
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ $.fn.button.defaults = {
+ loadingText: 'loading...'
+ }
+
+ $.fn.button.Constructor = Button
+
+
+ /* BUTTON NO CONFLICT
+ * ================== */
+
+ $.fn.button.noConflict = function () {
+ $.fn.button = old
+ return this
+ }
+
+
+ /* BUTTON DATA-API
+ * =============== */
+
+ $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ $btn.button('toggle')
+ })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.min.js
new file mode 100755
index 0000000..ba3c81a
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/bootstrap.min.js
@@ -0,0 +1,7 @@
+/**
+* Bootstrap.js by @fat & @mdo
+* plugins: bootstrap-transition.js, bootstrap-button.js
+* Copyright 2012 Twitter, Inc.
+* http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+!function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(t
his),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})}(window.jQuery)
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.js
deleted file mode 100755
index 453f99f..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.js
+++ /dev/null
@@ -1,6253 +0,0 @@
-/*! jQuery UI - v1.10.3 - 2013-05-11
-* http://jqueryui.com
-* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
-
-(function( $, undefined ) {
-
-var uuid = 0,
- runiqueId = /^ui-id-\d+$/;
-
-// $.ui might exist from components with no dependencies, e.g., $.ui.position
-$.ui = $.ui || {};
-
-$.extend( $.ui, {
- version: "1.10.3",
-
- keyCode: {
- BACKSPACE: 8,
- COMMA: 188,
- DELETE: 46,
- DOWN: 40,
- END: 35,
- ENTER: 13,
- ESCAPE: 27,
- HOME: 36,
- LEFT: 37,
- NUMPAD_ADD: 107,
- NUMPAD_DECIMAL: 110,
- NUMPAD_DIVIDE: 111,
- NUMPAD_ENTER: 108,
- NUMPAD_MULTIPLY: 106,
- NUMPAD_SUBTRACT: 109,
- PAGE_DOWN: 34,
- PAGE_UP: 33,
- PERIOD: 190,
- RIGHT: 39,
- SPACE: 32,
- TAB: 9,
- UP: 38
- }
-});
-
-// plugins
-$.fn.extend({
- focus: (function( orig ) {
- return function( delay, fn ) {
- return typeof delay === "number" ?
- this.each(function() {
- var elem = this;
- setTimeout(function() {
- $( elem ).focus();
- if ( fn ) {
- fn.call( elem );
- }
- }, delay );
- }) :
- orig.apply( this, arguments );
- };
- })( $.fn.focus ),
-
- scrollParent: function() {
- var scrollParent;
- if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
- scrollParent = this.parents().filter(function() {
- return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
- }).eq(0);
- } else {
- scrollParent = this.parents().filter(function() {
- return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
- }).eq(0);
- }
-
- return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
- },
-
- zIndex: function( zIndex ) {
- if ( zIndex !== undefined ) {
- return this.css( "zIndex", zIndex );
- }
-
- if ( this.length ) {
- var elem = $( this[ 0 ] ), position, value;
- while ( elem.length && elem[ 0 ] !== document ) {
- // Ignore z-index if position is set to a value where z-index is ignored by the browser
- // This makes behavior of this function consistent across browsers
- // WebKit always returns auto if the element is positioned
- position = elem.css( "position" );
- if ( position === "absolute" || position === "relative" || position === "fixed" ) {
- // IE returns 0 when zIndex is not specified
- // other browsers return a string
- // we ignore the case of nested elements with an explicit value of 0
- // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
- value = parseInt( elem.css( "zIndex" ), 10 );
- if ( !isNaN( value ) && value !== 0 ) {
- return value;
- }
- }
- elem = elem.parent();
- }
- }
-
- return 0;
- },
-
- uniqueId: function() {
- return this.each(function() {
- if ( !this.id ) {
- this.id = "ui-id-" + (++uuid);
- }
- });
- },
-
- removeUniqueId: function() {
- return this.each(function() {
- if ( runiqueId.test( this.id ) ) {
- $( this ).removeAttr( "id" );
- }
- });
- }
-});
-
-// selectors
-function focusable( element, isTabIndexNotNaN ) {
- var map, mapName, img,
- nodeName = element.nodeName.toLowerCase();
- if ( "area" === nodeName ) {
- map = element.parentNode;
- mapName = map.name;
- if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
- return false;
- }
- img = $( "img[usemap=#" + mapName + "]" )[0];
- return !!img && visible( img );
- }
- return ( /input|select|textarea|button|object/.test( nodeName ) ?
- !element.disabled :
- "a" === nodeName ?
- element.href || isTabIndexNotNaN :
- isTabIndexNotNaN) &&
- // the element and all of its ancestors must be visible
- visible( element );
-}
-
-function visible( element ) {
- return $.expr.filters.visible( element ) &&
- !$( element ).parents().addBack().filter(function() {
- return $.css( this, "visibility" ) === "hidden";
- }).length;
-}
-
-$.extend( $.expr[ ":" ], {
- data: $.expr.createPseudo ?
- $.expr.createPseudo(function( dataName ) {
- return function( elem ) {
- return !!$.data( elem, dataName );
- };
- }) :
- // support: jQuery <1.8
- function( elem, i, match ) {
- return !!$.data( elem, match[ 3 ] );
- },
-
- focusable: function( element ) {
- return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
- },
-
- tabbable: function( element ) {
- var tabIndex = $.attr( element, "tabindex" ),
- isTabIndexNaN = isNaN( tabIndex );
- return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
- }
-});
-
-// support: jQuery <1.8
-if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
- $.each( [ "Width", "Height" ], function( i, name ) {
- var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
- type = name.toLowerCase(),
- orig = {
- innerWidth: $.fn.innerWidth,
- innerHeight: $.fn.innerHeight,
- outerWidth: $.fn.outerWidth,
- outerHeight: $.fn.outerHeight
- };
-
- function reduce( elem, size, border, margin ) {
- $.each( side, function() {
- size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
- if ( border ) {
- size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
- }
- if ( margin ) {
- size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
- }
- });
- return size;
- }
-
- $.fn[ "inner" + name ] = function( size ) {
- if ( size === undefined ) {
- return orig[ "inner" + name ].call( this );
- }
-
- return this.each(function() {
- $( this ).css( type, reduce( this, size ) + "px" );
- });
- };
-
- $.fn[ "outer" + name] = function( size, margin ) {
- if ( typeof size !== "number" ) {
- return orig[ "outer" + name ].call( this, size );
- }
-
- return this.each(function() {
- $( this).css( type, reduce( this, size, true, margin ) + "px" );
- });
- };
- });
-}
-
-// support: jQuery <1.8
-if ( !$.fn.addBack ) {
- $.fn.addBack = function( selector ) {
- return this.add( selector == null ?
- this.prevObject : this.prevObject.filter( selector )
- );
- };
-}
-
-// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
-if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
- $.fn.removeData = (function( removeData ) {
- return function( key ) {
- if ( arguments.length ) {
- return removeData.call( this, $.camelCase( key ) );
- } else {
- return removeData.call( this );
- }
- };
- })( $.fn.removeData );
-}
-
-
-
-
-
-// deprecated
-$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
-
-$.support.selectstart = "onselectstart" in document.createElement( "div" );
-$.fn.extend({
- disableSelection: function() {
- return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
- ".ui-disableSelection", function( event ) {
- event.preventDefault();
- });
- },
-
- enableSelection: function() {
- return this.unbind( ".ui-disableSelection" );
- }
-});
-
-$.extend( $.ui, {
- // $.ui.plugin is deprecated. Use $.widget() extensions instead.
- plugin: {
- add: function( module, option, set ) {
- var i,
- proto = $.ui[ module ].prototype;
- for ( i in set ) {
- proto.plugins[ i ] = proto.plugins[ i ] || [];
- proto.plugins[ i ].push( [ option, set[ i ] ] );
- }
- },
- call: function( instance, name, args ) {
- var i,
- set = instance.plugins[ name ];
- if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
- return;
- }
-
- for ( i = 0; i < set.length; i++ ) {
- if ( instance.options[ set[ i ][ 0 ] ] ) {
- set[ i ][ 1 ].apply( instance.element, args );
- }
- }
- }
- },
-
- // only used by resizable
- hasScroll: function( el, a ) {
-
- //If overflow is hidden, the element might have extra content, but the user wants to hide it
- if ( $( el ).css( "overflow" ) === "hidden") {
- return false;
- }
-
- var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
- has = false;
-
- if ( el[ scroll ] > 0 ) {
- return true;
- }
-
- // TODO: determine which cases actually cause this to happen
- // if the element doesn't have the scroll set, see if it's possible to
- // set the scroll
- el[ scroll ] = 1;
- has = ( el[ scroll ] > 0 );
- el[ scroll ] = 0;
- return has;
- }
-});
-
-})( jQuery );
-(function( $, undefined ) {
-
-var uuid = 0,
- slice = Array.prototype.slice,
- _cleanData = $.cleanData;
-$.cleanData = function( elems ) {
- for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
- try {
- $( elem ).triggerHandler( "remove" );
- // http://bugs.jquery.com/ticket/8235
- } catch( e ) {}
- }
- _cleanData( elems );
-};
-
-$.widget = function( name, base, prototype ) {
- var fullName, existingConstructor, constructor, basePrototype,
- // proxiedPrototype allows the provided prototype to remain unmodified
- // so that it can be used as a mixin for multiple widgets (#8876)
- proxiedPrototype = {},
- namespace = name.split( "." )[ 0 ];
-
- name = name.split( "." )[ 1 ];
- fullName = namespace + "-" + name;
-
- if ( !prototype ) {
- prototype = base;
- base = $.Widget;
- }
-
- // create selector for plugin
- $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
- return !!$.data( elem, fullName );
- };
-
- $[ namespace ] = $[ namespace ] || {};
- existingConstructor = $[ namespace ][ name ];
- constructor = $[ namespace ][ name ] = function( options, element ) {
- // allow instantiation without "new" keyword
- if ( !this._createWidget ) {
- return new constructor( options, element );
- }
-
- // allow instantiation without initializing for simple inheritance
- // must use "new" keyword (the code above always passes args)
- if ( arguments.length ) {
- this._createWidget( options, element );
- }
- };
- // extend with the existing constructor to carry over any static properties
- $.extend( constructor, existingConstructor, {
- version: prototype.version,
- // copy the object used to create the prototype in case we need to
- // redefine the widget later
- _proto: $.extend( {}, prototype ),
- // track widgets that inherit from this widget in case this widget is
- // redefined after a widget inherits from it
- _childConstructors: []
- });
-
- basePrototype = new base();
- // we need to make the options hash a property directly on the new instance
- // otherwise we'll modify the options hash on the prototype that we're
- // inheriting from
- basePrototype.options = $.widget.extend( {}, basePrototype.options );
- $.each( prototype, function( prop, value ) {
- if ( !$.isFunction( value ) ) {
- proxiedPrototype[ prop ] = value;
- return;
- }
- proxiedPrototype[ prop ] = (function() {
- var _super = function() {
- return base.prototype[ prop ].apply( this, arguments );
- },
- _superApply = function( args ) {
- return base.prototype[ prop ].apply( this, args );
- };
- return function() {
- var __super = this._super,
- __superApply = this._superApply,
- returnValue;
-
- this._super = _super;
- this._superApply = _superApply;
-
- returnValue = value.apply( this, arguments );
-
- this._super = __super;
- this._superApply = __superApply;
-
- return returnValue;
- };
- })();
- });
- constructor.prototype = $.widget.extend( basePrototype, {
- // TODO: remove support for widgetEventPrefix
- // always use the name + a colon as the prefix, e.g., draggable:start
- // don't prefix for widgets that aren't DOM-based
- widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
- }, proxiedPrototype, {
- constructor: constructor,
- namespace: namespace,
- widgetName: name,
- widgetFullName: fullName
- });
-
- // If this widget is being redefined then we need to find all widgets that
- // are inheriting from it and redefine all of them so that they inherit from
- // the new version of this widget. We're essentially trying to replace one
- // level in the prototype chain.
- if ( existingConstructor ) {
- $.each( existingConstructor._childConstructors, function( i, child ) {
- var childPrototype = child.prototype;
-
- // redefine the child widget using the same prototype that was
- // originally used, but inherit from the new version of the base
- $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
- });
- // remove the list of existing child constructors from the old constructor
- // so the old child constructors can be garbage collected
- delete existingConstructor._childConstructors;
- } else {
- base._childConstructors.push( constructor );
- }
-
- $.widget.bridge( name, constructor );
-};
-
-$.widget.extend = function( target ) {
- var input = slice.call( arguments, 1 ),
- inputIndex = 0,
- inputLength = input.length,
- key,
- value;
- for ( ; inputIndex < inputLength; inputIndex++ ) {
- for ( key in input[ inputIndex ] ) {
- value = input[ inputIndex ][ key ];
- if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
- // Clone objects
- if ( $.isPlainObject( value ) ) {
- target[ key ] = $.isPlainObject( target[ key ] ) ?
- $.widget.extend( {}, target[ key ], value ) :
- // Don't extend strings, arrays, etc. with objects
- $.widget.extend( {}, value );
- // Copy everything else by reference
- } else {
- target[ key ] = value;
- }
- }
- }
- }
- return target;
-};
-
-$.widget.bridge = function( name, object ) {
- var fullName = object.prototype.widgetFullName || name;
- $.fn[ name ] = function( options ) {
- var isMethodCall = typeof options === "string",
- args = slice.call( arguments, 1 ),
- returnValue = this;
-
- // allow multiple hashes to be passed on init
- options = !isMethodCall && args.length ?
- $.widget.extend.apply( null, [ options ].concat(args) ) :
- options;
-
- if ( isMethodCall ) {
- this.each(function() {
- var methodValue,
- instance = $.data( this, fullName );
- if ( !instance ) {
- return $.error( "cannot call methods on " + name + " prior to initialization; " +
- "attempted to call method '" + options + "'" );
- }
- if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
- return $.error( "no such method '" + options + "' for " + name + " widget instance" );
- }
- methodValue = instance[ options ].apply( instance, args );
- if ( methodValue !== instance && methodValue !== undefined ) {
- returnValue = methodValue && methodValue.jquery ?
- returnValue.pushStack( methodValue.get() ) :
- methodValue;
- return false;
- }
- });
- } else {
- this.each(function() {
- var instance = $.data( this, fullName );
- if ( instance ) {
- instance.option( options || {} )._init();
- } else {
- $.data( this, fullName, new object( options, this ) );
- }
- });
- }
-
- return returnValue;
- };
-};
-
-$.Widget = function( /* options, element */ ) {};
-$.Widget._childConstructors = [];
-
-$.Widget.prototype = {
- widgetName: "widget",
- widgetEventPrefix: "",
- defaultElement: "<div>",
- options: {
- disabled: false,
-
- // callbacks
- create: null
- },
- _createWidget: function( options, element ) {
- element = $( element || this.defaultElement || this )[ 0 ];
- this.element = $( element );
- this.uuid = uuid++;
- this.eventNamespace = "." + this.widgetName + this.uuid;
- this.options = $.widget.extend( {},
- this.options,
- this._getCreateOptions(),
- options );
-
- this.bindings = $();
- this.hoverable = $();
- this.focusable = $();
-
- if ( element !== this ) {
- $.data( element, this.widgetFullName, this );
- this._on( true, this.element, {
- remove: function( event ) {
- if ( event.target === element ) {
- this.destroy();
- }
- }
- });
- this.document = $( element.style ?
- // element within the document
- element.ownerDocument :
- // element is window or document
- element.document || element );
- this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
- }
-
- this._create();
- this._trigger( "create", null, this._getCreateEventData() );
- this._init();
- },
- _getCreateOptions: $.noop,
- _getCreateEventData: $.noop,
- _create: $.noop,
- _init: $.noop,
-
- destroy: function() {
- this._destroy();
- // we can probably remove the unbind calls in 2.0
- // all event bindings should go through this._on()
- this.element
- .unbind( this.eventNamespace )
- // 1.9 BC for #7810
- // TODO remove dual storage
- .removeData( this.widgetName )
- .removeData( this.widgetFullName )
- // support: jquery <1.6.3
- // http://bugs.jquery.com/ticket/9413
- .removeData( $.camelCase( this.widgetFullName ) );
- this.widget()
- .unbind( this.eventNamespace )
- .removeAttr( "aria-disabled" )
- .removeClass(
- this.widgetFullName + "-disabled " +
- "ui-state-disabled" );
-
- // clean up events and states
- this.bindings.unbind( this.eventNamespace );
- this.hoverable.removeClass( "ui-state-hover" );
- this.focusable.removeClass( "ui-state-focus" );
- },
- _destroy: $.noop,
-
- widget: function() {
- return this.element;
- },
-
- option: function( key, value ) {
- var options = key,
- parts,
- curOption,
- i;
-
- if ( arguments.length === 0 ) {
- // don't return a reference to the internal hash
- return $.widget.extend( {}, this.options );
- }
-
- if ( typeof key === "string" ) {
- // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
- options = {};
- parts = key.split( "." );
- key = parts.shift();
- if ( parts.length ) {
- curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
- for ( i = 0; i < parts.length - 1; i++ ) {
- curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
- curOption = curOption[ parts[ i ] ];
- }
- key = parts.pop();
- if ( value === undefined ) {
- return curOption[ key ] === undefined ? null : curOption[ key ];
- }
- curOption[ key ] = value;
- } else {
- if ( value === undefined ) {
- return this.options[ key ] === undefined ? null : this.options[ key ];
- }
- options[ key ] = value;
- }
- }
-
- this._setOptions( options );
-
- return this;
- },
- _setOptions: function( options ) {
- var key;
-
- for ( key in options ) {
- this._setOption( key, options[ key ] );
- }
-
- return this;
- },
- _setOption: function( key, value ) {
- this.options[ key ] = value;
-
- if ( key === "disabled" ) {
- this.widget()
- .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
- .attr( "aria-disabled", value );
- this.hoverable.removeClass( "ui-state-hover" );
- this.focusable.removeClass( "ui-state-focus" );
- }
-
- return this;
- },
-
- enable: function() {
- return this._setOption( "disabled", false );
- },
- disable: function() {
- return this._setOption( "disabled", true );
- },
-
- _on: function( suppressDisabledCheck, element, handlers ) {
- var delegateElement,
- instance = this;
-
- // no suppressDisabledCheck flag, shuffle arguments
- if ( typeof suppressDisabledCheck !== "boolean" ) {
- handlers = element;
- element = suppressDisabledCheck;
- suppressDisabledCheck = false;
- }
-
- // no element argument, shuffle and use this.element
- if ( !handlers ) {
- handlers = element;
- element = this.element;
- delegateElement = this.widget();
- } else {
- // accept selectors, DOM elements
- element = delegateElement = $( element );
- this.bindings = this.bindings.add( element );
- }
-
- $.each( handlers, function( event, handler ) {
- function handlerProxy() {
- // allow widgets to customize the disabled handling
- // - disabled as an array instead of boolean
- // - disabled class as method for disabling individual parts
- if ( !suppressDisabledCheck &&
- ( instance.options.disabled === true ||
- $( this ).hasClass( "ui-state-disabled" ) ) ) {
- return;
- }
- return ( typeof handler === "string" ? instance[ handler ] : handler )
- .apply( instance, arguments );
- }
-
- // copy the guid so direct unbinding works
- if ( typeof handler !== "string" ) {
- handlerProxy.guid = handler.guid =
- handler.guid || handlerProxy.guid || $.guid++;
- }
-
- var match = event.match( /^(\w+)\s*(.*)$/ ),
- eventName = match[1] + instance.eventNamespace,
- selector = match[2];
- if ( selector ) {
- delegateElement.delegate( selector, eventName, handlerProxy );
- } else {
- element.bind( eventName, handlerProxy );
- }
- });
- },
-
- _off: function( element, eventName ) {
- eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
- element.unbind( eventName ).undelegate( eventName );
- },
-
- _delay: function( handler, delay ) {
- function handlerProxy() {
- return ( typeof handler === "string" ? instance[ handler ] : handler )
- .apply( instance, arguments );
- }
- var instance = this;
- return setTimeout( handlerProxy, delay || 0 );
- },
-
- _hoverable: function( element ) {
- this.hoverable = this.hoverable.add( element );
- this._on( element, {
- mouseenter: function( event ) {
- $( event.currentTarget ).addClass( "ui-state-hover" );
- },
- mouseleave: function( event ) {
- $( event.currentTarget ).removeClass( "ui-state-hover" );
- }
- });
- },
-
- _focusable: function( element ) {
- this.focusable = this.focusable.add( element );
- this._on( element, {
- focusin: function( event ) {
- $( event.currentTarget ).addClass( "ui-state-focus" );
- },
- focusout: function( event ) {
- $( event.currentTarget ).removeClass( "ui-state-focus" );
- }
- });
- },
-
- _trigger: function( type, event, data ) {
- var prop, orig,
- callback = this.options[ type ];
-
- data = data || {};
- event = $.Event( event );
- event.type = ( type === this.widgetEventPrefix ?
- type :
- this.widgetEventPrefix + type ).toLowerCase();
- // the original event may come from any element
- // so we need to reset the target on the new event
- event.target = this.element[ 0 ];
-
- // copy original event properties over to the new event
- orig = event.originalEvent;
- if ( orig ) {
- for ( prop in orig ) {
- if ( !( prop in event ) ) {
- event[ prop ] = orig[ prop ];
- }
- }
- }
-
- this.element.trigger( event, data );
- return !( $.isFunction( callback ) &&
- callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
- event.isDefaultPrevented() );
- }
-};
-
-$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
- $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
- if ( typeof options === "string" ) {
- options = { effect: options };
- }
- var hasOptions,
- effectName = !options ?
- method :
- options === true || typeof options === "number" ?
- defaultEffect :
- options.effect || defaultEffect;
- options = options || {};
- if ( typeof options === "number" ) {
- options = { duration: options };
- }
- hasOptions = !$.isEmptyObject( options );
- options.complete = callback;
- if ( options.delay ) {
- element.delay( options.delay );
- }
- if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
- element[ method ]( options );
- } else if ( effectName !== method && element[ effectName ] ) {
- element[ effectName ]( options.duration, options.easing, callback );
- } else {
- element.queue(function( next ) {
- $( this )[ method ]();
- if ( callback ) {
- callback.call( element[ 0 ] );
- }
- next();
- });
- }
- };
-});
-
-})( jQuery );
-(function( $, undefined ) {
-
-var mouseHandled = false;
-$( document ).mouseup( function() {
- mouseHandled = false;
-});
-
-$.widget("ui.mouse", {
- version: "1.10.3",
- options: {
- cancel: "input,textarea,button,select,option",
- distance: 1,
- delay: 0
- },
- _mouseInit: function() {
- var that = this;
-
- this.element
- .bind("mousedown."+this.widgetName, function(event) {
- return that._mouseDown(event);
- })
- .bind("click."+this.widgetName, function(event) {
- if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
- $.removeData(event.target, that.widgetName + ".preventClickEvent");
- event.stopImmediatePropagation();
- return false;
- }
- });
-
- this.started = false;
- },
-
- // TODO: make sure destroying one instance of mouse doesn't mess with
- // other instances of mouse
- _mouseDestroy: function() {
- this.element.unbind("."+this.widgetName);
- if ( this._mouseMoveDelegate ) {
- $(document)
- .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
- .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
- }
- },
-
- _mouseDown: function(event) {
- // don't let more than one widget handle mouseStart
- if( mouseHandled ) { return; }
-
- // we may have missed mouseup (out of window)
- (this._mouseStarted && this._mouseUp(event));
-
- this._mouseDownEvent = event;
-
- var that = this,
- btnIsLeft = (event.which === 1),
- // event.target.nodeName works around a bug in IE 8 with
- // disabled inputs (#7620)
- elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
- if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
- return true;
- }
-
- this.mouseDelayMet = !this.options.delay;
- if (!this.mouseDelayMet) {
- this._mouseDelayTimer = setTimeout(function() {
- that.mouseDelayMet = true;
- }, this.options.delay);
- }
-
- if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
- this._mouseStarted = (this._mouseStart(event) !== false);
- if (!this._mouseStarted) {
- event.preventDefault();
- return true;
- }
- }
-
- // Click event may never have fired (Gecko & Opera)
- if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
- $.removeData(event.target, this.widgetName + ".preventClickEvent");
- }
-
- // these delegates are required to keep context
- this._mouseMoveDelegate = function(event) {
- return that._mouseMove(event);
- };
- this._mouseUpDelegate = function(event) {
- return that._mouseUp(event);
- };
- $(document)
- .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
- .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
-
- event.preventDefault();
-
- mouseHandled = true;
- return true;
- },
-
- _mouseMove: function(event) {
- // IE mouseup check - mouseup happened when mouse was out of window
- if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
- return this._mouseUp(event);
- }
-
- if (this._mouseStarted) {
- this._mouseDrag(event);
- return event.preventDefault();
- }
-
- if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
- this._mouseStarted =
- (this._mouseStart(this._mouseDownEvent, event) !== false);
- (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
- }
-
- return !this._mouseStarted;
- },
-
- _mouseUp: function(event) {
- $(document)
- .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
- .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
-
- if (this._mouseStarted) {
- this._mouseStarted = false;
-
- if (event.target === this._mouseDownEvent.target) {
- $.data(event.target, this.widgetName + ".preventClickEvent", true);
- }
-
- this._mouseStop(event);
- }
-
- return false;
- },
-
- _mouseDistanceMet: function(event) {
- return (Math.max(
- Math.abs(this._mouseDownEvent.pageX - event.pageX),
- Math.abs(this._mouseDownEvent.pageY - event.pageY)
- ) >= this.options.distance
- );
- },
-
- _mouseDelayMet: function(/* event */) {
- return this.mouseDelayMet;
- },
-
- // These are placeholder methods, to be overriden by extending plugin
- _mouseStart: function(/* event */) {},
- _mouseDrag: function(/* event */) {},
- _mouseStop: function(/* event */) {},
- _mouseCapture: function(/* event */) { return true; }
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.ui = $.ui || {};
-
-var cachedScrollbarWidth,
- max = Math.max,
- abs = Math.abs,
- round = Math.round,
- rhorizontal = /left|center|right/,
- rvertical = /top|center|bottom/,
- roffset = /[\+\-]\d+(\.[\d]+)?%?/,
- rposition = /^\w+/,
- rpercent = /%$/,
- _position = $.fn.position;
-
-function getOffsets( offsets, width, height ) {
- return [
- parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
- parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
- ];
-}
-
-function parseCss( element, property ) {
- return parseInt( $.css( element, property ), 10 ) || 0;
-}
-
-function getDimensions( elem ) {
- var raw = elem[0];
- if ( raw.nodeType === 9 ) {
- return {
- width: elem.width(),
- height: elem.height(),
- offset: { top: 0, left: 0 }
- };
- }
- if ( $.isWindow( raw ) ) {
- return {
- width: elem.width(),
- height: elem.height(),
- offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
- };
- }
- if ( raw.preventDefault ) {
- return {
- width: 0,
- height: 0,
- offset: { top: raw.pageY, left: raw.pageX }
- };
- }
- return {
- width: elem.outerWidth(),
- height: elem.outerHeight(),
- offset: elem.offset()
- };
-}
-
-$.position = {
- scrollbarWidth: function() {
- if ( cachedScrollbarWidth !== undefined ) {
- return cachedScrollbarWidth;
- }
- var w1, w2,
- div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
- innerDiv = div.children()[0];
-
- $( "body" ).append( div );
- w1 = innerDiv.offsetWidth;
- div.css( "overflow", "scroll" );
-
- w2 = innerDiv.offsetWidth;
-
- if ( w1 === w2 ) {
- w2 = div[0].clientWidth;
- }
-
- div.remove();
-
- return (cachedScrollbarWidth = w1 - w2);
- },
- getScrollInfo: function( within ) {
- var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
- overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
- hasOverflowX = overflowX === "scroll" ||
- ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
- hasOverflowY = overflowY === "scroll" ||
- ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
- return {
- width: hasOverflowY ? $.position.scrollbarWidth() : 0,
- height: hasOverflowX ? $.position.scrollbarWidth() : 0
- };
- },
- getWithinInfo: function( element ) {
- var withinElement = $( element || window ),
- isWindow = $.isWindow( withinElement[0] );
- return {
- element: withinElement,
- isWindow: isWindow,
- offset: withinElement.offset() || { left: 0, top: 0 },
- scrollLeft: withinElement.scrollLeft(),
- scrollTop: withinElement.scrollTop(),
- width: isWindow ? withinElement.width() : withinElement.outerWidth(),
- height: isWindow ? withinElement.height() : withinElement.outerHeight()
- };
- }
-};
-
-$.fn.position = function( options ) {
- if ( !options || !options.of ) {
- return _position.apply( this, arguments );
- }
-
- // make a copy, we don't want to modify arguments
- options = $.extend( {}, options );
-
- var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
- target = $( options.of ),
- within = $.position.getWithinInfo( options.within ),
- scrollInfo = $.position.getScrollInfo( within ),
- collision = ( options.collision || "flip" ).split( " " ),
- offsets = {};
-
- dimensions = getDimensions( target );
- if ( target[0].preventDefault ) {
- // force left top to allow flipping
- options.at = "left top";
- }
- targetWidth = dimensions.width;
- targetHeight = dimensions.height;
- targetOffset = dimensions.offset;
- // clone to reuse original targetOffset later
- basePosition = $.extend( {}, targetOffset );
-
- // force my and at to have valid horizontal and vertical positions
- // if a value is missing or invalid, it will be converted to center
- $.each( [ "my", "at" ], function() {
- var pos = ( options[ this ] || "" ).split( " " ),
- horizontalOffset,
- verticalOffset;
-
- if ( pos.length === 1) {
- pos = rhorizontal.test( pos[ 0 ] ) ?
- pos.concat( [ "center" ] ) :
- rvertical.test( pos[ 0 ] ) ?
- [ "center" ].concat( pos ) :
- [ "center", "center" ];
- }
- pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
- pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
-
- // calculate offsets
- horizontalOffset = roffset.exec( pos[ 0 ] );
- verticalOffset = roffset.exec( pos[ 1 ] );
- offsets[ this ] = [
- horizontalOffset ? horizontalOffset[ 0 ] : 0,
- verticalOffset ? verticalOffset[ 0 ] : 0
- ];
-
- // reduce to just the positions without the offsets
- options[ this ] = [
- rposition.exec( pos[ 0 ] )[ 0 ],
- rposition.exec( pos[ 1 ] )[ 0 ]
- ];
- });
-
- // normalize collision option
- if ( collision.length === 1 ) {
- collision[ 1 ] = collision[ 0 ];
- }
-
- if ( options.at[ 0 ] === "right" ) {
- basePosition.left += targetWidth;
- } else if ( options.at[ 0 ] === "center" ) {
- basePosition.left += targetWidth / 2;
- }
-
- if ( options.at[ 1 ] === "bottom" ) {
- basePosition.top += targetHeight;
- } else if ( options.at[ 1 ] === "center" ) {
- basePosition.top += targetHeight / 2;
- }
-
- atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
- basePosition.left += atOffset[ 0 ];
- basePosition.top += atOffset[ 1 ];
-
- return this.each(function() {
- var collisionPosition, using,
- elem = $( this ),
- elemWidth = elem.outerWidth(),
- elemHeight = elem.outerHeight(),
- marginLeft = parseCss( this, "marginLeft" ),
- marginTop = parseCss( this, "marginTop" ),
- collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
- collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
- position = $.extend( {}, basePosition ),
- myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
-
- if ( options.my[ 0 ] === "right" ) {
- position.left -= elemWidth;
- } else if ( options.my[ 0 ] === "center" ) {
- position.left -= elemWidth / 2;
- }
-
- if ( options.my[ 1 ] === "bottom" ) {
- position.top -= elemHeight;
- } else if ( options.my[ 1 ] === "center" ) {
- position.top -= elemHeight / 2;
- }
-
- position.left += myOffset[ 0 ];
- position.top += myOffset[ 1 ];
-
- // if the browser doesn't support fractions, then round for consistent results
- if ( !$.support.offsetFractions ) {
- position.left = round( position.left );
- position.top = round( position.top );
- }
-
- collisionPosition = {
- marginLeft: marginLeft,
- marginTop: marginTop
- };
-
- $.each( [ "left", "top" ], function( i, dir ) {
- if ( $.ui.position[ collision[ i ] ] ) {
- $.ui.position[ collision[ i ] ][ dir ]( position, {
- targetWidth: targetWidth,
- targetHeight: targetHeight,
- elemWidth: elemWidth,
- elemHeight: elemHeight,
- collisionPosition: collisionPosition,
- collisionWidth: collisionWidth,
- collisionHeight: collisionHeight,
- offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
- my: options.my,
- at: options.at,
- within: within,
- elem : elem
- });
- }
- });
-
- if ( options.using ) {
- // adds feedback as second argument to using callback, if present
- using = function( props ) {
- var left = targetOffset.left - position.left,
- right = left + targetWidth - elemWidth,
- top = targetOffset.top - position.top,
- bottom = top + targetHeight - elemHeight,
- feedback = {
- target: {
- element: target,
- left: targetOffset.left,
- top: targetOffset.top,
- width: targetWidth,
- height: targetHeight
- },
- element: {
- element: elem,
- left: position.left,
- top: position.top,
- width: elemWidth,
- height: elemHeight
- },
- horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
- vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
- };
- if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
- feedback.horizontal = "center";
- }
- if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
- feedback.vertical = "middle";
- }
- if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
- feedback.important = "horizontal";
- } else {
- feedback.important = "vertical";
- }
- options.using.call( this, props, feedback );
- };
- }
-
- elem.offset( $.extend( position, { using: using } ) );
- });
-};
-
-$.ui.position = {
- fit: {
- left: function( position, data ) {
- var within = data.within,
- withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
- outerWidth = within.width,
- collisionPosLeft = position.left - data.collisionPosition.marginLeft,
- overLeft = withinOffset - collisionPosLeft,
- overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
- newOverRight;
-
- // element is wider than within
- if ( data.collisionWidth > outerWidth ) {
- // element is initially over the left side of within
- if ( overLeft > 0 && overRight <= 0 ) {
- newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
- position.left += overLeft - newOverRight;
- // element is initially over right side of within
- } else if ( overRight > 0 && overLeft <= 0 ) {
- position.left = withinOffset;
- // element is initially over both left and right sides of within
- } else {
- if ( overLeft > overRight ) {
- position.left = withinOffset + outerWidth - data.collisionWidth;
- } else {
- position.left = withinOffset;
- }
- }
- // too far left -> align with left edge
- } else if ( overLeft > 0 ) {
- position.left += overLeft;
- // too far right -> align with right edge
- } else if ( overRight > 0 ) {
- position.left -= overRight;
- // adjust based on position and margin
- } else {
- position.left = max( position.left - collisionPosLeft, position.left );
- }
- },
- top: function( position, data ) {
- var within = data.within,
- withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
- outerHeight = data.within.height,
- collisionPosTop = position.top - data.collisionPosition.marginTop,
- overTop = withinOffset - collisionPosTop,
- overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
- newOverBottom;
-
- // element is taller than within
- if ( data.collisionHeight > outerHeight ) {
- // element is initially over the top of within
- if ( overTop > 0 && overBottom <= 0 ) {
- newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
- position.top += overTop - newOverBottom;
- // element is initially over bottom of within
- } else if ( overBottom > 0 && overTop <= 0 ) {
- position.top = withinOffset;
- // element is initially over both top and bottom of within
- } else {
- if ( overTop > overBottom ) {
- position.top = withinOffset + outerHeight - data.collisionHeight;
- } else {
- position.top = withinOffset;
- }
- }
- // too far up -> align with top
- } else if ( overTop > 0 ) {
- position.top += overTop;
- // too far down -> align with bottom edge
- } else if ( overBottom > 0 ) {
- position.top -= overBottom;
- // adjust based on position and margin
- } else {
- position.top = max( position.top - collisionPosTop, position.top );
- }
- }
- },
- flip: {
- left: function( position, data ) {
- var within = data.within,
- withinOffset = within.offset.left + within.scrollLeft,
- outerWidth = within.width,
- offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
- collisionPosLeft = position.left - data.collisionPosition.marginLeft,
- overLeft = collisionPosLeft - offsetLeft,
- overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
- myOffset = data.my[ 0 ] === "left" ?
- -data.elemWidth :
- data.my[ 0 ] === "right" ?
- data.elemWidth :
- 0,
- atOffset = data.at[ 0 ] === "left" ?
- data.targetWidth :
- data.at[ 0 ] === "right" ?
- -data.targetWidth :
- 0,
- offset = -2 * data.offset[ 0 ],
- newOverRight,
- newOverLeft;
-
- if ( overLeft < 0 ) {
- newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
- if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
- position.left += myOffset + atOffset + offset;
- }
- }
- else if ( overRight > 0 ) {
- newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
- if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
- position.left += myOffset + atOffset + offset;
- }
- }
- },
- top: function( position, data ) {
- var within = data.within,
- withinOffset = within.offset.top + within.scrollTop,
- outerHeight = within.height,
- offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
- collisionPosTop = position.top - data.collisionPosition.marginTop,
- overTop = collisionPosTop - offsetTop,
- overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
- top = data.my[ 1 ] === "top",
- myOffset = top ?
- -data.elemHeight :
- data.my[ 1 ] === "bottom" ?
- data.elemHeight :
- 0,
- atOffset = data.at[ 1 ] === "top" ?
- data.targetHeight :
- data.at[ 1 ] === "bottom" ?
- -data.targetHeight :
- 0,
- offset = -2 * data.offset[ 1 ],
- newOverTop,
- newOverBottom;
- if ( overTop < 0 ) {
- newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
- if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
- position.top += myOffset + atOffset + offset;
- }
- }
- else if ( overBottom > 0 ) {
- newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
- if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
- position.top += myOffset + atOffset + offset;
- }
- }
- }
- },
- flipfit: {
- left: function() {
- $.ui.position.flip.left.apply( this, arguments );
- $.ui.position.fit.left.apply( this, arguments );
- },
- top: function() {
- $.ui.position.flip.top.apply( this, arguments );
- $.ui.position.fit.top.apply( this, arguments );
- }
- }
-};
-
-// fraction support test
-(function () {
- var testElement, testElementParent, testElementStyle, offsetLeft, i,
- body = document.getElementsByTagName( "body" )[ 0 ],
- div = document.createElement( "div" );
-
- //Create a "fake body" for testing based on method used in jQuery.support
- testElement = document.createElement( body ? "div" : "body" );
- testElementStyle = {
- visibility: "hidden",
- width: 0,
- height: 0,
- border: 0,
- margin: 0,
- background: "none"
- };
- if ( body ) {
- $.extend( testElementStyle, {
- position: "absolute",
- left: "-1000px",
- top: "-1000px"
- });
- }
- for ( i in testElementStyle ) {
- testElement.style[ i ] = testElementStyle[ i ];
- }
- testElement.appendChild( div );
- testElementParent = body || document.documentElement;
- testElementParent.insertBefore( testElement, testElementParent.firstChild );
-
- div.style.cssText = "position: absolute; left: 10.7432222px;";
-
- offsetLeft = $( div ).offset().left;
- $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
-
- testElement.innerHTML = "";
- testElementParent.removeChild( testElement );
-})();
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-var lastActive, startXPos, startYPos, clickDragged,
- baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
- stateClasses = "ui-state-hover ui-state-active ",
- typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
- formResetHandler = function() {
- var form = $( this );
- setTimeout(function() {
- form.find( ":ui-button" ).button( "refresh" );
- }, 1 );
- },
- radioGroup = function( radio ) {
- var name = radio.name,
- form = radio.form,
- radios = $( [] );
- if ( name ) {
- name = name.replace( /'/g, "\\'" );
- if ( form ) {
- radios = $( form ).find( "[name='" + name + "']" );
- } else {
- radios = $( "[name='" + name + "']", radio.ownerDocument )
- .filter(function() {
- return !this.form;
- });
- }
- }
- return radios;
- };
-
-$.widget( "ui.button", {
- version: "1.10.3",
- defaultElement: "<button>",
- options: {
- disabled: null,
- text: true,
- label: null,
- icons: {
- primary: null,
- secondary: null
- }
- },
- _create: function() {
- this.element.closest( "form" )
- .unbind( "reset" + this.eventNamespace )
- .bind( "reset" + this.eventNamespace, formResetHandler );
-
- if ( typeof this.options.disabled !== "boolean" ) {
- this.options.disabled = !!this.element.prop( "disabled" );
- } else {
- this.element.prop( "disabled", this.options.disabled );
- }
-
- this._determineButtonType();
- this.hasTitle = !!this.buttonElement.attr( "title" );
-
- var that = this,
- options = this.options,
- toggleButton = this.type === "checkbox" || this.type === "radio",
- activeClass = !toggleButton ? "ui-state-active" : "",
- focusClass = "ui-state-focus";
-
- if ( options.label === null ) {
- options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
- }
-
- this._hoverable( this.buttonElement );
-
- this.buttonElement
- .addClass( baseClasses )
- .attr( "role", "button" )
- .bind( "mouseenter" + this.eventNamespace, function() {
- if ( options.disabled ) {
- return;
- }
- if ( this === lastActive ) {
- $( this ).addClass( "ui-state-active" );
- }
- })
- .bind( "mouseleave" + this.eventNamespace, function() {
- if ( options.disabled ) {
- return;
- }
- $( this ).removeClass( activeClass );
- })
- .bind( "click" + this.eventNamespace, function( event ) {
- if ( options.disabled ) {
- event.preventDefault();
- event.stopImmediatePropagation();
- }
- });
-
- this.element
- .bind( "focus" + this.eventNamespace, function() {
- // no need to check disabled, focus won't be triggered anyway
- that.buttonElement.addClass( focusClass );
- })
- .bind( "blur" + this.eventNamespace, function() {
- that.buttonElement.removeClass( focusClass );
- });
-
- if ( toggleButton ) {
- this.element.bind( "change" + this.eventNamespace, function() {
- if ( clickDragged ) {
- return;
- }
- that.refresh();
- });
- // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
- // prevents issue where button state changes but checkbox/radio checked state
- // does not in Firefox (see ticket #6970)
- this.buttonElement
- .bind( "mousedown" + this.eventNamespace, function( event ) {
- if ( options.disabled ) {
- return;
- }
- clickDragged = false;
- startXPos = event.pageX;
- startYPos = event.pageY;
- })
- .bind( "mouseup" + this.eventNamespace, function( event ) {
- if ( options.disabled ) {
- return;
- }
- if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
- clickDragged = true;
- }
- });
- }
-
- if ( this.type === "checkbox" ) {
- this.buttonElement.bind( "click" + this.eventNamespace, function() {
- if ( options.disabled || clickDragged ) {
- return false;
- }
- });
- } else if ( this.type === "radio" ) {
- this.buttonElement.bind( "click" + this.eventNamespace, function() {
- if ( options.disabled || clickDragged ) {
- return false;
- }
- $( this ).addClass( "ui-state-active" );
- that.buttonElement.attr( "aria-pressed", "true" );
-
- var radio = that.element[ 0 ];
- radioGroup( radio )
- .not( radio )
- .map(function() {
- return $( this ).button( "widget" )[ 0 ];
- })
- .removeClass( "ui-state-active" )
- .attr( "aria-pressed", "false" );
- });
- } else {
- this.buttonElement
- .bind( "mousedown" + this.eventNamespace, function() {
- if ( options.disabled ) {
- return false;
- }
- $( this ).addClass( "ui-state-active" );
- lastActive = this;
- that.document.one( "mouseup", function() {
- lastActive = null;
- });
- })
- .bind( "mouseup" + this.eventNamespace, function() {
- if ( options.disabled ) {
- return false;
- }
- $( this ).removeClass( "ui-state-active" );
- })
- .bind( "keydown" + this.eventNamespace, function(event) {
- if ( options.disabled ) {
- return false;
- }
- if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
- $( this ).addClass( "ui-state-active" );
- }
- })
- // see #8559, we bind to blur here in case the button element loses
- // focus between keydown and keyup, it would be left in an "active" state
- .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
- $( this ).removeClass( "ui-state-active" );
- });
-
- if ( this.buttonElement.is("a") ) {
- this.buttonElement.keyup(function(event) {
- if ( event.keyCode === $.ui.keyCode.SPACE ) {
- // TODO pass through original event correctly (just as 2nd argument doesn't work)
- $( this ).click();
- }
- });
- }
- }
-
- // TODO: pull out $.Widget's handling for the disabled option into
- // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
- // be overridden by individual plugins
- this._setOption( "disabled", options.disabled );
- this._resetButton();
- },
-
- _determineButtonType: function() {
- var ancestor, labelSelector, checked;
-
- if ( this.element.is("[type=checkbox]") ) {
- this.type = "checkbox";
- } else if ( this.element.is("[type=radio]") ) {
- this.type = "radio";
- } else if ( this.element.is("input") ) {
- this.type = "input";
- } else {
- this.type = "button";
- }
-
- if ( this.type === "checkbox" || this.type === "radio" ) {
- // we don't search against the document in case the element
- // is disconnected from the DOM
- ancestor = this.element.parents().last();
- labelSelector = "label[for='" + this.element.attr("id") + "']";
- this.buttonElement = ancestor.find( labelSelector );
- if ( !this.buttonElement.length ) {
- ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
- this.buttonElement = ancestor.filter( labelSelector );
- if ( !this.buttonElement.length ) {
- this.buttonElement = ancestor.find( labelSelector );
- }
- }
- this.element.addClass( "ui-helper-hidden-accessible" );
-
- checked = this.element.is( ":checked" );
- if ( checked ) {
- this.buttonElement.addClass( "ui-state-active" );
- }
- this.buttonElement.prop( "aria-pressed", checked );
- } else {
- this.buttonElement = this.element;
- }
- },
-
- widget: function() {
- return this.buttonElement;
- },
-
- _destroy: function() {
- this.element
- .removeClass( "ui-helper-hidden-accessible" );
- this.buttonElement
- .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
- .removeAttr( "role" )
- .removeAttr( "aria-pressed" )
- .html( this.buttonElement.find(".ui-button-text").html() );
-
- if ( !this.hasTitle ) {
- this.buttonElement.removeAttr( "title" );
- }
- },
-
- _setOption: function( key, value ) {
- this._super( key, value );
- if ( key === "disabled" ) {
- if ( value ) {
- this.element.prop( "disabled", true );
- } else {
- this.element.prop( "disabled", false );
- }
- return;
- }
- this._resetButton();
- },
-
- refresh: function() {
- //See #8237 & #8828
- var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
-
- if ( isDisabled !== this.options.disabled ) {
- this._setOption( "disabled", isDisabled );
- }
- if ( this.type === "radio" ) {
- radioGroup( this.element[0] ).each(function() {
- if ( $( this ).is( ":checked" ) ) {
- $( this ).button( "widget" )
- .addClass( "ui-state-active" )
- .attr( "aria-pressed", "true" );
- } else {
- $( this ).button( "widget" )
- .removeClass( "ui-state-active" )
- .attr( "aria-pressed", "false" );
- }
- });
- } else if ( this.type === "checkbox" ) {
- if ( this.element.is( ":checked" ) ) {
- this.buttonElement
- .addClass( "ui-state-active" )
- .attr( "aria-pressed", "true" );
- } else {
- this.buttonElement
- .removeClass( "ui-state-active" )
- .attr( "aria-pressed", "false" );
- }
- }
- },
-
- _resetButton: function() {
- if ( this.type === "input" ) {
- if ( this.options.label ) {
- this.element.val( this.options.label );
- }
- return;
- }
- var buttonElement = this.buttonElement.removeClass( typeClasses ),
- buttonText = $( "<span></span>", this.document[0] )
- .addClass( "ui-button-text" )
- .html( this.options.label )
- .appendTo( buttonElement.empty() )
- .text(),
- icons = this.options.icons,
- multipleIcons = icons.primary && icons.secondary,
- buttonClasses = [];
-
- if ( icons.primary || icons.secondary ) {
- if ( this.options.text ) {
- buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
- }
-
- if ( icons.primary ) {
- buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
- }
-
- if ( icons.secondary ) {
- buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
- }
-
- if ( !this.options.text ) {
- buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
-
- if ( !this.hasTitle ) {
- buttonElement.attr( "title", $.trim( buttonText ) );
- }
- }
- } else {
- buttonClasses.push( "ui-button-text-only" );
- }
- buttonElement.addClass( buttonClasses.join( " " ) );
- }
-});
-
-$.widget( "ui.buttonset", {
- version: "1.10.3",
- options: {
- items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
- },
-
- _create: function() {
- this.element.addClass( "ui-buttonset" );
- },
-
- _init: function() {
- this.refresh();
- },
-
- _setOption: function( key, value ) {
- if ( key === "disabled" ) {
- this.buttons.button( "option", key, value );
- }
-
- this._super( key, value );
- },
-
- refresh: function() {
- var rtl = this.element.css( "direction" ) === "rtl";
-
- this.buttons = this.element.find( this.options.items )
- .filter( ":ui-button" )
- .button( "refresh" )
- .end()
- .not( ":ui-button" )
- .button()
- .end()
- .map(function() {
- return $( this ).button( "widget" )[ 0 ];
- })
- .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
- .filter( ":first" )
- .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
- .end()
- .filter( ":last" )
- .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
- .end()
- .end();
- },
-
- _destroy: function() {
- this.element.removeClass( "ui-buttonset" );
- this.buttons
- .map(function() {
- return $( this ).button( "widget" )[ 0 ];
- })
- .removeClass( "ui-corner-left ui-corner-right" )
- .end()
- .button( "destroy" );
- }
-});
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-$.extend($.ui, { datepicker: { version: "1.10.3" } });
-
-var PROP_NAME = "datepicker",
- instActive;
-
-/* Date picker manager.
- Use the singleton instance of this class, $.datepicker, to interact with the date picker.
- Settings for (groups of) date pickers are maintained in an instance object,
- allowing multiple different settings on the same page. */
-
-function Datepicker() {
- this._curInst = null; // The current instance in use
- this._keyEvent = false; // If the last event was a key event
- this._disabledInputs = []; // List of date picker inputs that have been disabled
- this._datepickerShowing = false; // True if the popup picker is showing , false if not
- this._inDialog = false; // True if showing within a "dialog", false if not
- this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
- this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
- this._appendClass = "ui-datepicker-append"; // The name of the append marker class
- this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
- this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
- this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
- this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
- this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
- this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
- this.regional = []; // Available regional settings, indexed by language code
- this.regional[""] = { // Default regional settings
- closeText: "Done", // Display text for close link
- prevText: "Prev", // Display text for previous month link
- nextText: "Next", // Display text for next month link
- currentText: "Today", // Display text for current month link
- monthNames: ["January","February","March","April","May","June",
- "July","August","September","October","November","December"], // Names of months for drop-down and formatting
- monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
- dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
- dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
- dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
- weekHeader: "Wk", // Column header for week of the year
- dateFormat: "mm/dd/yy", // See format options on parseDate
- firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
- isRTL: false, // True if right-to-left language, false if left-to-right
- showMonthAfterYear: false, // True if the year select precedes month, false for month then year
- yearSuffix: "" // Additional text to append to the year in the month headers
- };
- this._defaults = { // Global defaults for all the date picker instances
- showOn: "focus", // "focus" for popup on focus,
- // "button" for trigger button, or "both" for either
- showAnim: "fadeIn", // Name of jQuery animation for popup
- showOptions: {}, // Options for enhanced animations
- defaultDate: null, // Used when field is blank: actual date,
- // +/-number for offset from today, null for today
- appendText: "", // Display text following the input box, e.g. showing the format
- buttonText: "...", // Text for trigger button
- buttonImage: "", // URL for trigger button image
- buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
- hideIfNoPrevNext: false, // True to hide next/previous month links
- // if not applicable, false to just disable them
- navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
- gotoCurrent: false, // True if today link goes back to current selection instead
- changeMonth: false, // True if month can be selected directly, false if only prev/next
- changeYear: false, // True if year can be selected directly, false if only prev/next
- yearRange: "c-10:c+10", // Range of years to display in drop-down,
- // either relative to today's year (-nn:+nn), relative to currently displayed year
- // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
- showOtherMonths: false, // True to show dates in other months, false to leave blank
- selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
- showWeek: false, // True to show week of the year, false to not show it
- calculateWeek: this.iso8601Week, // How to calculate the week of the year,
- // takes a Date and returns the number of the week for it
- shortYearCutoff: "+10", // Short year values < this are in the current century,
- // > this are in the previous century,
- // string value starting with "+" for current year + value
- minDate: null, // The earliest selectable date, or null for no limit
- maxDate: null, // The latest selectable date, or null for no limit
- duration: "fast", // Duration of display/closure
- beforeShowDay: null, // Function that takes a date and returns an array with
- // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
- // [2] = cell title (optional), e.g. $.datepicker.noWeekends
- beforeShow: null, // Function that takes an input field and
- // returns a set of custom settings for the date picker
- onSelect: null, // Define a callback function when a date is selected
- onChangeMonthYear: null, // Define a callback function when the month or year is changed
- onClose: null, // Define a callback function when the datepicker is closed
- numberOfMonths: 1, // Number of months to show at a time
- showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
- stepMonths: 1, // Number of months to step back/forward
- stepBigMonths: 12, // Number of months to step back/forward for the big links
- altField: "", // Selector for an alternate field to store selected dates into
- altFormat: "", // The date format to use for the alternate field
- constrainInput: true, // The input is constrained by the current date format
- showButtonPanel: false, // True to show button panel, false to not show it
- autoSize: false, // True to size the input for the date format, false to leave as is
- disabled: false // The initial disabled state
- };
- $.extend(this._defaults, this.regional[""]);
- this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
-}
-
-$.extend(Datepicker.prototype, {
- /* Class name added to elements to indicate already configured with a date picker. */
- markerClassName: "hasDatepicker",
-
- //Keep track of the maximum number of rows displayed (see #7043)
- maxRows: 4,
-
- // TODO rename to "widget" when switching to widget factory
- _widgetDatepicker: function() {
- return this.dpDiv;
- },
-
- /* Override the default settings for all instances of the date picker.
- * @param settings object - the new settings to use as defaults (anonymous object)
- * @return the manager object
- */
- setDefaults: function(settings) {
- extendRemove(this._defaults, settings || {});
- return this;
- },
-
- /* Attach the date picker to a jQuery selection.
- * @param target element - the target input field or division or span
- * @param settings object - the new settings to use for this date picker instance (anonymous)
- */
- _attachDatepicker: function(target, settings) {
- var nodeName, inline, inst;
- nodeName = target.nodeName.toLowerCase();
- inline = (nodeName === "div" || nodeName === "span");
- if (!target.id) {
- this.uuid += 1;
- target.id = "dp" + this.uuid;
- }
- inst = this._newInst($(target), inline);
- inst.settings = $.extend({}, settings || {});
- if (nodeName === "input") {
- this._connectDatepicker(target, inst);
- } else if (inline) {
- this._inlineDatepicker(target, inst);
- }
- },
-
- /* Create a new instance object. */
- _newInst: function(target, inline) {
- var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
- return {id: id, input: target, // associated target
- selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
- drawMonth: 0, drawYear: 0, // month being drawn
- inline: inline, // is datepicker inline or not
- dpDiv: (!inline ? this.dpDiv : // presentation div
- bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
- },
-
- /* Attach the date picker to an input field. */
- _connectDatepicker: function(target, inst) {
- var input = $(target);
- inst.append = $([]);
- inst.trigger = $([]);
- if (input.hasClass(this.markerClassName)) {
- return;
- }
- this._attachments(input, inst);
- input.addClass(this.markerClassName).keydown(this._doKeyDown).
- keypress(this._doKeyPress).keyup(this._doKeyUp);
- this._autoSize(inst);
- $.data(target, PROP_NAME, inst);
- //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
- if( inst.settings.disabled ) {
- this._disableDatepicker( target );
- }
- },
-
- /* Make attachments based on settings. */
- _attachments: function(input, inst) {
- var showOn, buttonText, buttonImage,
- appendText = this._get(inst, "appendText"),
- isRTL = this._get(inst, "isRTL");
-
- if (inst.append) {
- inst.append.remove();
- }
- if (appendText) {
- inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
- input[isRTL ? "before" : "after"](inst.append);
- }
-
- input.unbind("focus", this._showDatepicker);
-
- if (inst.trigger) {
- inst.trigger.remove();
- }
-
- showOn = this._get(inst, "showOn");
- if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
- input.focus(this._showDatepicker);
- }
- if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
- buttonText = this._get(inst, "buttonText");
- buttonImage = this._get(inst, "buttonImage");
- inst.trigger = $(this._get(inst, "buttonImageOnly") ?
- $("<img/>").addClass(this._triggerClass).
- attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
- $("<button type='button'></button>").addClass(this._triggerClass).
- html(!buttonImage ? buttonText : $("<img/>").attr(
- { src:buttonImage, alt:buttonText, title:buttonText })));
- input[isRTL ? "before" : "after"](inst.trigger);
- inst.trigger.click(function() {
- if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
- $.datepicker._hideDatepicker();
- } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
- $.datepicker._hideDatepicker();
- $.datepicker._showDatepicker(input[0]);
- } else {
- $.datepicker._showDatepicker(input[0]);
- }
- return false;
- });
- }
- },
-
- /* Apply the maximum length for the date format. */
- _autoSize: function(inst) {
- if (this._get(inst, "autoSize") && !inst.inline) {
- var findMax, max, maxI, i,
- date = new Date(2009, 12 - 1, 20), // Ensure double digits
- dateFormat = this._get(inst, "dateFormat");
-
- if (dateFormat.match(/[DM]/)) {
- findMax = function(names) {
- max = 0;
- maxI = 0;
- for (i = 0; i < names.length; i++) {
- if (names[i].length > max) {
- max = names[i].length;
- maxI = i;
- }
- }
- return maxI;
- };
- date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
- "monthNames" : "monthNamesShort"))));
- date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
- "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
- }
- inst.input.attr("size", this._formatDate(inst, date).length);
- }
- },
-
- /* Attach an inline date picker to a div. */
- _inlineDatepicker: function(target, inst) {
- var divSpan = $(target);
- if (divSpan.hasClass(this.markerClassName)) {
- return;
- }
- divSpan.addClass(this.markerClassName).append(inst.dpDiv);
- $.data(target, PROP_NAME, inst);
- this._setDate(inst, this._getDefaultDate(inst), true);
- this._updateDatepicker(inst);
- this._updateAlternate(inst);
- //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
- if( inst.settings.disabled ) {
- this._disableDatepicker( target );
- }
- // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
- // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
- inst.dpDiv.css( "display", "block" );
- },
-
- /* Pop-up the date picker in a "dialog" box.
- * @param input element - ignored
- * @param date string or Date - the initial date to display
- * @param onSelect function - the function to call when a date is selected
- * @param settings object - update the dialog date picker instance's settings (anonymous object)
- * @param pos int[2] - coordinates for the dialog's position within the screen or
- * event - with x/y coordinates or
- * leave empty for default (screen centre)
- * @return the manager object
- */
- _dialogDatepicker: function(input, date, onSelect, settings, pos) {
- var id, browserWidth, browserHeight, scrollX, scrollY,
- inst = this._dialogInst; // internal instance
-
- if (!inst) {
- this.uuid += 1;
- id = "dp" + this.uuid;
- this._dialogInput = $("<input type='text' id='" + id +
- "' style='position: absolute; top: -100px; width: 0px;'/>");
- this._dialogInput.keydown(this._doKeyDown);
- $("body").append(this._dialogInput);
- inst = this._dialogInst = this._newInst(this._dialogInput, false);
- inst.settings = {};
- $.data(this._dialogInput[0], PROP_NAME, inst);
- }
- extendRemove(inst.settings, settings || {});
- date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
- this._dialogInput.val(date);
-
- this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
- if (!this._pos) {
- browserWidth = document.documentElement.clientWidth;
- browserHeight = document.documentElement.clientHeight;
- scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
- scrollY = document.documentElement.scrollTop || document.body.scrollTop;
- this._pos = // should use actual width/height below
- [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
- }
-
- // move input on screen for focus, but hidden behind dialog
- this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
- inst.settings.onSelect = onSelect;
- this._inDialog = true;
- this.dpDiv.addClass(this._dialogClass);
- this._showDatepicker(this._dialogInput[0]);
- if ($.blockUI) {
- $.blockUI(this.dpDiv);
- }
- $.data(this._dialogInput[0], PROP_NAME, inst);
- return this;
- },
-
- /* Detach a datepicker from its control.
- * @param target element - the target input field or division or span
- */
- _destroyDatepicker: function(target) {
- var nodeName,
- $target = $(target),
- inst = $.data(target, PROP_NAME);
-
- if (!$target.hasClass(this.markerClassName)) {
- return;
- }
-
- nodeName = target.nodeName.toLowerCase();
- $.removeData(target, PROP_NAME);
- if (nodeName === "input") {
- inst.append.remove();
- inst.trigger.remove();
- $target.removeClass(this.markerClassName).
- unbind("focus", this._showDatepicker).
- unbind("keydown", this._doKeyDown).
- unbind("keypress", this._doKeyPress).
- unbind("keyup", this._doKeyUp);
- } else if (nodeName === "div" || nodeName === "span") {
- $target.removeClass(this.markerClassName).empty();
- }
- },
-
- /* Enable the date picker to a jQuery selection.
- * @param target element - the target input field or division or span
- */
- _enableDatepicker: function(target) {
- var nodeName, inline,
- $target = $(target),
- inst = $.data(target, PROP_NAME);
-
- if (!$target.hasClass(this.markerClassName)) {
- return;
- }
-
- nodeName = target.nodeName.toLowerCase();
- if (nodeName === "input") {
- target.disabled = false;
- inst.trigger.filter("button").
- each(function() { this.disabled = false; }).end().
- filter("img").css({opacity: "1.0", cursor: ""});
- } else if (nodeName === "div" || nodeName === "span") {
- inline = $target.children("." + this._inlineClass);
- inline.children().removeClass("ui-state-disabled");
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
- prop("disabled", false);
- }
- this._disabledInputs = $.map(this._disabledInputs,
- function(value) { return (value === target ? null : value); }); // delete entry
- },
-
- /* Disable the date picker to a jQuery selection.
- * @param target element - the target input field or division or span
- */
- _disableDatepicker: function(target) {
- var nodeName, inline,
- $target = $(target),
- inst = $.data(target, PROP_NAME);
-
- if (!$target.hasClass(this.markerClassName)) {
- return;
- }
-
- nodeName = target.nodeName.toLowerCase();
- if (nodeName === "input") {
- target.disabled = true;
- inst.trigger.filter("button").
- each(function() { this.disabled = true; }).end().
- filter("img").css({opacity: "0.5", cursor: "default"});
- } else if (nodeName === "div" || nodeName === "span") {
- inline = $target.children("." + this._inlineClass);
- inline.children().addClass("ui-state-disabled");
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
- prop("disabled", true);
- }
- this._disabledInputs = $.map(this._disabledInputs,
- function(value) { return (value === target ? null : value); }); // delete entry
- this._disabledInputs[this._disabledInputs.length] = target;
- },
-
- /* Is the first field in a jQuery collection disabled as a datepicker?
- * @param target element - the target input field or division or span
- * @return boolean - true if disabled, false if enabled
- */
- _isDisabledDatepicker: function(target) {
- if (!target) {
- return false;
- }
- for (var i = 0; i < this._disabledInputs.length; i++) {
- if (this._disabledInputs[i] === target) {
- return true;
- }
- }
- return false;
- },
-
- /* Retrieve the instance data for the target control.
- * @param target element - the target input field or division or span
- * @return object - the associated instance data
- * @throws error if a jQuery problem getting data
- */
- _getInst: function(target) {
- try {
- return $.data(target, PROP_NAME);
- }
- catch (err) {
- throw "Missing instance data for this datepicker";
- }
- },
-
- /* Update or retrieve the settings for a date picker attached to an input field or division.
- * @param target element - the target input field or division or span
- * @param name object - the new settings to update or
- * string - the name of the setting to change or retrieve,
- * when retrieving also "all" for all instance settings or
- * "defaults" for all global defaults
- * @param value any - the new value for the setting
- * (omit if above is an object or to retrieve a value)
- */
- _optionDatepicker: function(target, name, value) {
- var settings, date, minDate, maxDate,
- inst = this._getInst(target);
-
- if (arguments.length === 2 && typeof name === "string") {
- return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
- (inst ? (name === "all" ? $.extend({}, inst.settings) :
- this._get(inst, name)) : null));
- }
-
- settings = name || {};
- if (typeof name === "string") {
- settings = {};
- settings[name] = value;
- }
-
- if (inst) {
- if (this._curInst === inst) {
- this._hideDatepicker();
- }
-
- date = this._getDateDatepicker(target, true);
- minDate = this._getMinMaxDate(inst, "min");
- maxDate = this._getMinMaxDate(inst, "max");
- extendRemove(inst.settings, settings);
- // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
- if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
- inst.settings.minDate = this._formatDate(inst, minDate);
- }
- if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
- inst.settings.maxDate = this._formatDate(inst, maxDate);
- }
- if ( "disabled" in settings ) {
- if ( settings.disabled ) {
- this._disableDatepicker(target);
- } else {
- this._enableDatepicker(target);
- }
- }
- this._attachments($(target), inst);
- this._autoSize(inst);
- this._setDate(inst, date);
- this._updateAlternate(inst);
- this._updateDatepicker(inst);
- }
- },
-
- // change method deprecated
- _changeDatepicker: function(target, name, value) {
- this._optionDatepicker(target, name, value);
- },
-
- /* Redraw the date picker attached to an input field or division.
- * @param target element - the target input field or division or span
- */
- _refreshDatepicker: function(target) {
- var inst = this._getInst(target);
- if (inst) {
- this._updateDatepicker(inst);
- }
- },
-
- /* Set the dates for a jQuery selection.
- * @param target element - the target input field or division or span
- * @param date Date - the new date
- */
- _setDateDatepicker: function(target, date) {
- var inst = this._getInst(target);
- if (inst) {
- this._setDate(inst, date);
- this._updateDatepicker(inst);
- this._updateAlternate(inst);
- }
- },
-
- /* Get the date(s) for the first entry in a jQuery selection.
- * @param target element - the target input field or division or span
- * @param noDefault boolean - true if no default date is to be used
- * @return Date - the current date
- */
- _getDateDatepicker: function(target, noDefault) {
- var inst = this._getInst(target);
- if (inst && !inst.inline) {
- this._setDateFromField(inst, noDefault);
- }
- return (inst ? this._getDate(inst) : null);
- },
-
- /* Handle keystrokes. */
- _doKeyDown: function(event) {
- var onSelect, dateStr, sel,
- inst = $.datepicker._getInst(event.target),
- handled = true,
- isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
-
- inst._keyEvent = true;
- if ($.datepicker._datepickerShowing) {
- switch (event.keyCode) {
- case 9: $.datepicker._hideDatepicker();
- handled = false;
- break; // hide on tab out
- case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
- $.datepicker._currentClass + ")", inst.dpDiv);
- if (sel[0]) {
- $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
- }
-
- onSelect = $.datepicker._get(inst, "onSelect");
- if (onSelect) {
- dateStr = $.datepicker._formatDate(inst);
-
- // trigger custom callback
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
- } else {
- $.datepicker._hideDatepicker();
- }
-
- return false; // don't submit the form
- case 27: $.datepicker._hideDatepicker();
- break; // hide on escape
- case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- -$.datepicker._get(inst, "stepBigMonths") :
- -$.datepicker._get(inst, "stepMonths")), "M");
- break; // previous month/year on page up/+ ctrl
- case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- +$.datepicker._get(inst, "stepBigMonths") :
- +$.datepicker._get(inst, "stepMonths")), "M");
- break; // next month/year on page down/+ ctrl
- case 35: if (event.ctrlKey || event.metaKey) {
- $.datepicker._clearDate(event.target);
- }
- handled = event.ctrlKey || event.metaKey;
- break; // clear on ctrl or command +end
- case 36: if (event.ctrlKey || event.metaKey) {
- $.datepicker._gotoToday(event.target);
- }
- handled = event.ctrlKey || event.metaKey;
- break; // current on ctrl or command +home
- case 37: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
- }
- handled = event.ctrlKey || event.metaKey;
- // -1 day on ctrl or command +left
- if (event.originalEvent.altKey) {
- $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- -$.datepicker._get(inst, "stepBigMonths") :
- -$.datepicker._get(inst, "stepMonths")), "M");
- }
- // next month/year on alt +left on Mac
- break;
- case 38: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, -7, "D");
- }
- handled = event.ctrlKey || event.metaKey;
- break; // -1 week on ctrl or command +up
- case 39: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
- }
- handled = event.ctrlKey || event.metaKey;
- // +1 day on ctrl or command +right
- if (event.originalEvent.altKey) {
- $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- +$.datepicker._get(inst, "stepBigMonths") :
- +$.datepicker._get(inst, "stepMonths")), "M");
- }
- // next month/year on alt +right
- break;
- case 40: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, +7, "D");
- }
- handled = event.ctrlKey || event.metaKey;
- break; // +1 week on ctrl or command +down
- default: handled = false;
- }
- } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
- $.datepicker._showDatepicker(this);
- } else {
- handled = false;
- }
-
- if (handled) {
- event.preventDefault();
- event.stopPropagation();
- }
- },
-
- /* Filter entered characters - based on date format. */
- _doKeyPress: function(event) {
- var chars, chr,
- inst = $.datepicker._getInst(event.target);
-
- if ($.datepicker._get(inst, "constrainInput")) {
- chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
- chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
- return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
- }
- },
-
- /* Synchronise manual entry and field/alternate field. */
- _doKeyUp: function(event) {
- var date,
- inst = $.datepicker._getInst(event.target);
-
- if (inst.input.val() !== inst.lastVal) {
- try {
- date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
- (inst.input ? inst.input.val() : null),
- $.datepicker._getFormatConfig(inst));
-
- if (date) { // only if valid
- $.datepicker._setDateFromField(inst);
- $.datepicker._updateAlternate(inst);
- $.datepicker._updateDatepicker(inst);
- }
- }
- catch (err) {
- }
- }
- return true;
- },
-
- /* Pop-up the date picker for a given input field.
- * If false returned from beforeShow event handler do not show.
- * @param input element - the input field attached to the date picker or
- * event - if triggered by focus
- */
- _showDatepicker: function(input) {
- input = input.target || input;
- if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
- input = $("input", input.parentNode)[0];
- }
-
- if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
- return;
- }
-
- var inst, beforeShow, beforeShowSettings, isFixed,
- offset, showAnim, duration;
-
- inst = $.datepicker._getInst(input);
- if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
- $.datepicker._curInst.dpDiv.stop(true, true);
- if ( inst && $.datepicker._datepickerShowing ) {
- $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
- }
- }
-
- beforeShow = $.datepicker._get(inst, "beforeShow");
- beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
- if(beforeShowSettings === false){
- return;
- }
- extendRemove(inst.settings, beforeShowSettings);
-
- inst.lastVal = null;
- $.datepicker._lastInput = input;
- $.datepicker._setDateFromField(inst);
-
- if ($.datepicker._inDialog) { // hide cursor
- input.value = "";
- }
- if (!$.datepicker._pos) { // position below input
- $.datepicker._pos = $.datepicker._findPos(input);
- $.datepicker._pos[1] += input.offsetHeight; // add the height
- }
-
- isFixed = false;
- $(input).parents().each(function() {
- isFixed |= $(this).css("position") === "fixed";
- return !isFixed;
- });
-
- offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
- $.datepicker._pos = null;
- //to avoid flashes on Firefox
- inst.dpDiv.empty();
- // determine sizing offscreen
- inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
- $.datepicker._updateDatepicker(inst);
- // fix width for dynamic number of date pickers
- // and adjust position before showing
- offset = $.datepicker._checkOffset(inst, offset, isFixed);
- inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
- "static" : (isFixed ? "fixed" : "absolute")), display: "none",
- left: offset.left + "px", top: offset.top + "px"});
-
- if (!inst.inline) {
- showAnim = $.datepicker._get(inst, "showAnim");
- duration = $.datepicker._get(inst, "duration");
- inst.dpDiv.zIndex($(input).zIndex()+1);
- $.datepicker._datepickerShowing = true;
-
- if ( $.effects && $.effects.effect[ showAnim ] ) {
- inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
- } else {
- inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
- }
-
- if ( $.datepicker._shouldFocusInput( inst ) ) {
- inst.input.focus();
- }
-
- $.datepicker._curInst = inst;
- }
- },
-
- /* Generate the date picker content. */
- _updateDatepicker: function(inst) {
- this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
- instActive = inst; // for delegate hover events
- inst.dpDiv.empty().append(this._generateHTML(inst));
- this._attachHandlers(inst);
- inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
-
- var origyearshtml,
- numMonths = this._getNumberOfMonths(inst),
- cols = numMonths[1],
- width = 17;
-
- inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
- if (cols > 1) {
- inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
- }
- inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
- "Class"]("ui-datepicker-multi");
- inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
- "Class"]("ui-datepicker-rtl");
-
- if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
- inst.input.focus();
- }
-
- // deffered render of the years select (to avoid flashes on Firefox)
- if( inst.yearshtml ){
- origyearshtml = inst.yearshtml;
- setTimeout(function(){
- //assure that inst.yearshtml didn't change.
- if( origyearshtml === inst.yearshtml && inst.yearshtml ){
- inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
- }
- origyearshtml = inst.yearshtml = null;
- }, 0);
- }
- },
-
- // #6694 - don't focus the input if it's already focused
- // this breaks the change event in IE
- // Support: IE and jQuery <1.9
- _shouldFocusInput: function( inst ) {
- return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
- },
-
- /* Check positioning to remain on screen. */
- _checkOffset: function(inst, offset, isFixed) {
- var dpWidth = inst.dpDiv.outerWidth(),
- dpHeight = inst.dpDiv.outerHeight(),
- inputWidth = inst.input ? inst.input.outerWidth() : 0,
- inputHeight = inst.input ? inst.input.outerHeight() : 0,
- viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
- viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
-
- offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
- offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
- offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
-
- // now check if datepicker is showing outside window viewport - move to a better place if so.
- offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
- Math.abs(offset.left + dpWidth - viewWidth) : 0);
- offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
- Math.abs(dpHeight + inputHeight) : 0);
-
- return offset;
- },
-
- /* Find an object's position on the screen. */
- _findPos: function(obj) {
- var position,
- inst = this._getInst(obj),
- isRTL = this._get(inst, "isRTL");
-
- while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
- obj = obj[isRTL ? "previousSibling" : "nextSibling"];
- }
-
- position = $(obj).offset();
- return [position.left, position.top];
- },
-
- /* Hide the date picker from view.
- * @param input element - the input field attached to the date picker
- */
- _hideDatepicker: function(input) {
- var showAnim, duration, postProcess, onClose,
- inst = this._curInst;
-
- if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
- return;
- }
-
- if (this._datepickerShowing) {
- showAnim = this._get(inst, "showAnim");
- duration = this._get(inst, "duration");
- postProcess = function() {
- $.datepicker._tidyDialog(inst);
- };
-
- // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
- if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
- inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
- } else {
- inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
- (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
- }
-
- if (!showAnim) {
- postProcess();
- }
- this._datepickerShowing = false;
-
- onClose = this._get(inst, "onClose");
- if (onClose) {
- onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
- }
-
- this._lastInput = null;
- if (this._inDialog) {
- this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
- if ($.blockUI) {
- $.unblockUI();
- $("body").append(this.dpDiv);
- }
- }
- this._inDialog = false;
- }
- },
-
- /* Tidy up after a dialog display. */
- _tidyDialog: function(inst) {
- inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
- },
-
- /* Close date picker if clicked elsewhere. */
- _checkExternalClick: function(event) {
- if (!$.datepicker._curInst) {
- return;
- }
-
- var $target = $(event.target),
- inst = $.datepicker._getInst($target[0]);
-
- if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
- $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
- !$target.hasClass($.datepicker.markerClassName) &&
- !$target.closest("." + $.datepicker._triggerClass).length &&
- $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
- ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
- $.datepicker._hideDatepicker();
- }
- },
-
- /* Adjust one of the date sub-fields. */
- _adjustDate: function(id, offset, period) {
- var target = $(id),
- inst = this._getInst(target[0]);
-
- if (this._isDisabledDatepicker(target[0])) {
- return;
- }
- this._adjustInstDate(inst, offset +
- (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
- period);
- this._updateDatepicker(inst);
- },
-
- /* Action for current link. */
- _gotoToday: function(id) {
- var date,
- target = $(id),
- inst = this._getInst(target[0]);
-
- if (this._get(inst, "gotoCurrent") && inst.currentDay) {
- inst.selectedDay = inst.currentDay;
- inst.drawMonth = inst.selectedMonth = inst.currentMonth;
- inst.drawYear = inst.selectedYear = inst.currentYear;
- } else {
- date = new Date();
- inst.selectedDay = date.getDate();
- inst.drawMonth = inst.selectedMonth = date.getMonth();
- inst.drawYear = inst.selectedYear = date.getFullYear();
- }
- this._notifyChange(inst);
- this._adjustDate(target);
- },
-
- /* Action for selecting a new month/year. */
- _selectMonthYear: function(id, select, period) {
- var target = $(id),
- inst = this._getInst(target[0]);
-
- inst["selected" + (period === "M" ? "Month" : "Year")] =
- inst["draw" + (period === "M" ? "Month" : "Year")] =
- parseInt(select.options[select.selectedIndex].value,10);
-
- this._notifyChange(inst);
- this._adjustDate(target);
- },
-
- /* Action for selecting a day. */
- _selectDay: function(id, month, year, td) {
- var inst,
- target = $(id);
-
- if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
- return;
- }
-
- inst = this._getInst(target[0]);
- inst.selectedDay = inst.currentDay = $("a", td).html();
- inst.selectedMonth = inst.currentMonth = month;
- inst.selectedYear = inst.currentYear = year;
- this._selectDate(id, this._formatDate(inst,
- inst.currentDay, inst.currentMonth, inst.currentYear));
- },
-
- /* Erase the input field and hide the date picker. */
- _clearDate: function(id) {
- var target = $(id);
- this._selectDate(target, "");
- },
-
- /* Update the input field with the selected date. */
- _selectDate: function(id, dateStr) {
- var onSelect,
- target = $(id),
- inst = this._getInst(target[0]);
-
- dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
- if (inst.input) {
- inst.input.val(dateStr);
- }
- this._updateAlternate(inst);
-
- onSelect = this._get(inst, "onSelect");
- if (onSelect) {
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
- } else if (inst.input) {
- inst.input.trigger("change"); // fire the change event
- }
-
- if (inst.inline){
- this._updateDatepicker(inst);
- } else {
- this._hideDatepicker();
- this._lastInput = inst.input[0];
- if (typeof(inst.input[0]) !== "object") {
- inst.input.focus(); // restore focus
- }
- this._lastInput = null;
- }
- },
-
- /* Update any alternate field to synchronise with the main field. */
- _updateAlternate: function(inst) {
- var altFormat, date, dateStr,
- altField = this._get(inst, "altField");
-
- if (altField) { // update alternate field too
- altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
- date = this._getDate(inst);
- dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
- $(altField).each(function() { $(this).val(dateStr); });
- }
- },
-
- /* Set as beforeShowDay function to prevent selection of weekends.
- * @param date Date - the date to customise
- * @return [boolean, string] - is this date selectable?, what is its CSS class?
- */
- noWeekends: function(date) {
- var day = date.getDay();
- return [(day > 0 && day < 6), ""];
- },
-
- /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
- * @param date Date - the date to get the week for
- * @return number - the number of the week within the year that contains this date
- */
- iso8601Week: function(date) {
- var time,
- checkDate = new Date(date.getTime());
-
- // Find Thursday of this week starting on Monday
- checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
-
- time = checkDate.getTime();
- checkDate.setMonth(0); // Compare with Jan 1
- checkDate.setDate(1);
- return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
- },
-
- /* Parse a string value into a date object.
- * See formatDate below for the possible formats.
- *
- * @param format string - the expected format of the date
- * @param value string - the date in the above format
- * @param settings Object - attributes include:
- * shortYearCutoff number - the cutoff year for determining the century (optional)
- * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
- * dayNames string[7] - names of the days from Sunday (optional)
- * monthNamesShort string[12] - abbreviated names of the months (optional)
- * monthNames string[12] - names of the months (optional)
- * @return Date - the extracted date value or null if value is blank
- */
- parseDate: function (format, value, settings) {
- if (format == null || value == null) {
- throw "Invalid arguments";
- }
-
- value = (typeof value === "object" ? value.toString() : value + "");
- if (value === "") {
- return null;
- }
-
- var iFormat, dim, extra,
- iValue = 0,
- shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
- shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
- new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
- dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
- dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
- monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
- monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
- year = -1,
- month = -1,
- day = -1,
- doy = -1,
- literal = false,
- date,
- // Check whether a format character is doubled
- lookAhead = function(match) {
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
- if (matches) {
- iFormat++;
- }
- return matches;
- },
- // Extract a number from the string value
- getNumber = function(match) {
- var isDoubled = lookAhead(match),
- size = (match === "@" ? 14 : (match === "!" ? 20 :
- (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
- digits = new RegExp("^\\d{1," + size + "}"),
- num = value.substring(iValue).match(digits);
- if (!num) {
- throw "Missing number at position " + iValue;
- }
- iValue += num[0].length;
- return parseInt(num[0], 10);
- },
- // Extract a name from the string value and convert to an index
- getName = function(match, shortNames, longNames) {
- var index = -1,
- names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
- return [ [k, v] ];
- }).sort(function (a, b) {
- return -(a[1].length - b[1].length);
- });
-
- $.each(names, function (i, pair) {
- var name = pair[1];
- if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
- index = pair[0];
- iValue += name.length;
- return false;
- }
- });
- if (index !== -1) {
- return index + 1;
- } else {
- throw "Unknown name at position " + iValue;
- }
- },
- // Confirm that a literal character matches the string value
- checkLiteral = function() {
- if (value.charAt(iValue) !== format.charAt(iFormat)) {
- throw "Unexpected literal at position " + iValue;
- }
- iValue++;
- };
-
- for (iFormat = 0; iFormat < format.length; iFormat++) {
- if (literal) {
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
- literal = false;
- } else {
- checkLiteral();
- }
- } else {
- switch (format.charAt(iFormat)) {
- case "d":
- day = getNumber("d");
- break;
- case "D":
- getName("D", dayNamesShort, dayNames);
- break;
- case "o":
- doy = getNumber("o");
- break;
- case "m":
- month = getNumber("m");
- break;
- case "M":
- month = getName("M", monthNamesShort, monthNames);
- break;
- case "y":
- year = getNumber("y");
- break;
- case "@":
- date = new Date(getNumber("@"));
- year = date.getFullYear();
- month = date.getMonth() + 1;
- day = date.getDate();
- break;
- case "!":
- date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
- year = date.getFullYear();
- month = date.getMonth() + 1;
- day = date.getDate();
- break;
- case "'":
- if (lookAhead("'")){
- checkLiteral();
- } else {
- literal = true;
- }
- break;
- default:
- checkLiteral();
- }
- }
- }
-
- if (iValue < value.length){
- extra = value.substr(iValue);
- if (!/^\s+/.test(extra)) {
- throw "Extra/unparsed characters found in date: " + extra;
- }
- }
-
- if (year === -1) {
- year = new Date().getFullYear();
- } else if (year < 100) {
- year += new Date().getFullYear() - new Date().getFullYear() % 100 +
- (year <= shortYearCutoff ? 0 : -100);
- }
-
- if (doy > -1) {
- month = 1;
- day = doy;
- do {
- dim = this._getDaysInMonth(year, month - 1);
- if (day <= dim) {
- break;
- }
- month++;
- day -= dim;
- } while (true);
- }
-
- date = this._daylightSavingAdjust(new Date(year, month - 1, day));
- if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
- throw "Invalid date"; // E.g. 31/02/00
- }
- return date;
- },
-
- /* Standard date formats. */
- ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
- COOKIE: "D, dd M yy",
- ISO_8601: "yy-mm-dd",
- RFC_822: "D, d M y",
- RFC_850: "DD, dd-M-y",
- RFC_1036: "D, d M y",
- RFC_1123: "D, d M yy",
- RFC_2822: "D, d M yy",
- RSS: "D, d M y", // RFC 822
- TICKS: "!",
- TIMESTAMP: "@",
- W3C: "yy-mm-dd", // ISO 8601
-
- _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
- Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
-
- /* Format a date object into a string value.
- * The format can be combinations of the following:
- * d - day of month (no leading zero)
- * dd - day of month (two digit)
- * o - day of year (no leading zeros)
- * oo - day of year (three digit)
- * D - day name short
- * DD - day name long
- * m - month of year (no leading zero)
- * mm - month of year (two digit)
- * M - month name short
- * MM - month name long
- * y - year (two digit)
- * yy - year (four digit)
- * @ - Unix timestamp (ms since 01/01/1970)
- * ! - Windows ticks (100ns since 01/01/0001)
- * "..." - literal text
- * '' - single quote
- *
- * @param format string - the desired format of the date
- * @param date Date - the date value to format
- * @param settings Object - attributes include:
- * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
- * dayNames string[7] - names of the days from Sunday (optional)
- * monthNamesShort string[12] - abbreviated names of the months (optional)
- * monthNames string[12] - names of the months (optional)
- * @return string - the date in the above format
- */
- formatDate: function (format, date, settings) {
- if (!date) {
- return "";
- }
-
- var iFormat,
- dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
- dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
- monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
- monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
- // Check whether a format character is doubled
- lookAhead = function(match) {
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
- if (matches) {
- iFormat++;
- }
- return matches;
- },
- // Format a number, with leading zero if necessary
- formatNumber = function(match, value, len) {
- var num = "" + value;
- if (lookAhead(match)) {
- while (num.length < len) {
- num = "0" + num;
- }
- }
- return num;
- },
- // Format a name, short or long as requested
- formatName = function(match, value, shortNames, longNames) {
- return (lookAhead(match) ? longNames[value] : shortNames[value]);
- },
- output = "",
- literal = false;
-
- if (date) {
- for (iFormat = 0; iFormat < format.length; iFormat++) {
- if (literal) {
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
- literal = false;
- } else {
- output += format.charAt(iFormat);
- }
- } else {
- switch (format.charAt(iFormat)) {
- case "d":
- output += formatNumber("d", date.getDate(), 2);
- break;
- case "D":
- output += formatName("D", date.getDay(), dayNamesShort, dayNames);
- break;
- case "o":
- output += formatNumber("o",
- Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
- break;
- case "m":
- output += formatNumber("m", date.getMonth() + 1, 2);
- break;
- case "M":
- output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
- break;
- case "y":
- output += (lookAhead("y") ? date.getFullYear() :
- (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
- break;
- case "@":
- output += date.getTime();
- break;
- case "!":
- output += date.getTime() * 10000 + this._ticksTo1970;
- break;
- case "'":
- if (lookAhead("'")) {
- output += "'";
- } else {
- literal = true;
- }
- break;
- default:
- output += format.charAt(iFormat);
- }
- }
- }
- }
- return output;
- },
-
- /* Extract all possible characters from the date format. */
- _possibleChars: function (format) {
- var iFormat,
- chars = "",
- literal = false,
- // Check whether a format character is doubled
- lookAhead = function(match) {
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
- if (matches) {
- iFormat++;
- }
- return matches;
- };
-
- for (iFormat = 0; iFormat < format.length; iFormat++) {
- if (literal) {
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
- literal = false;
- } else {
- chars += format.charAt(iFormat);
- }
- } else {
- switch (format.charAt(iFormat)) {
- case "d": case "m": case "y": case "@":
- chars += "0123456789";
- break;
- case "D": case "M":
- return null; // Accept anything
- case "'":
- if (lookAhead("'")) {
- chars += "'";
- } else {
- literal = true;
- }
- break;
- default:
- chars += format.charAt(iFormat);
- }
- }
- }
- return chars;
- },
-
- /* Get a setting value, defaulting if necessary. */
- _get: function(inst, name) {
- return inst.settings[name] !== undefined ?
- inst.settings[name] : this._defaults[name];
- },
-
- /* Parse existing date and initialise date picker. */
- _setDateFromField: function(inst, noDefault) {
- if (inst.input.val() === inst.lastVal) {
- return;
- }
-
- var dateFormat = this._get(inst, "dateFormat"),
- dates = inst.lastVal = inst.input ? inst.input.val() : null,
- defaultDate = this._getDefaultDate(inst),
- date = defaultDate,
- settings = this._getFormatConfig(inst);
-
- try {
- date = this.parseDate(dateFormat, dates, settings) || defaultDate;
- } catch (event) {
- dates = (noDefault ? "" : dates);
- }
- inst.selectedDay = date.getDate();
- inst.drawMonth = inst.selectedMonth = date.getMonth();
- inst.drawYear = inst.selectedYear = date.getFullYear();
- inst.currentDay = (dates ? date.getDate() : 0);
- inst.currentMonth = (dates ? date.getMonth() : 0);
- inst.currentYear = (dates ? date.getFullYear() : 0);
- this._adjustInstDate(inst);
- },
-
- /* Retrieve the default date shown on opening. */
- _getDefaultDate: function(inst) {
- return this._restrictMinMax(inst,
- this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
- },
-
- /* A date may be specified as an exact value or a relative one. */
- _determineDate: function(inst, date, defaultDate) {
- var offsetNumeric = function(offset) {
- var date = new Date();
- date.setDate(date.getDate() + offset);
- return date;
- },
- offsetString = function(offset) {
- try {
- return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
- offset, $.datepicker._getFormatConfig(inst));
- }
- catch (e) {
- // Ignore
- }
-
- var date = (offset.toLowerCase().match(/^c/) ?
- $.datepicker._getDate(inst) : null) || new Date(),
- year = date.getFullYear(),
- month = date.getMonth(),
- day = date.getDate(),
- pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
- matches = pattern.exec(offset);
-
- while (matches) {
- switch (matches[2] || "d") {
- case "d" : case "D" :
- day += parseInt(matches[1],10); break;
- case "w" : case "W" :
- day += parseInt(matches[1],10) * 7; break;
- case "m" : case "M" :
- month += parseInt(matches[1],10);
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
- break;
- case "y": case "Y" :
- year += parseInt(matches[1],10);
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
- break;
- }
- matches = pattern.exec(offset);
- }
- return new Date(year, month, day);
- },
- newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
- (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
-
- newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
- if (newDate) {
- newDate.setHours(0);
- newDate.setMinutes(0);
- newDate.setSeconds(0);
- newDate.setMilliseconds(0);
- }
- return this._daylightSavingAdjust(newDate);
- },
-
- /* Handle switch to/from daylight saving.
- * Hours may be non-zero on daylight saving cut-over:
- * > 12 when midnight changeover, but then cannot generate
- * midnight datetime, so jump to 1AM, otherwise reset.
- * @param date (Date) the date to check
- * @return (Date) the corrected date
- */
- _daylightSavingAdjust: function(date) {
- if (!date) {
- return null;
- }
- date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
- return date;
- },
-
- /* Set the date(s) directly. */
- _setDate: function(inst, date, noChange) {
- var clear = !date,
- origMonth = inst.selectedMonth,
- origYear = inst.selectedYear,
- newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
-
- inst.selectedDay = inst.currentDay = newDate.getDate();
- inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
- inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
- if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
- this._notifyChange(inst);
- }
- this._adjustInstDate(inst);
- if (inst.input) {
- inst.input.val(clear ? "" : this._formatDate(inst));
- }
- },
-
- /* Retrieve the date(s) directly. */
- _getDate: function(inst) {
- var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
- this._daylightSavingAdjust(new Date(
- inst.currentYear, inst.currentMonth, inst.currentDay)));
- return startDate;
- },
-
- /* Attach the onxxx handlers. These are declared statically so
- * they work with static code transformers like Caja.
- */
- _attachHandlers: function(inst) {
- var stepMonths = this._get(inst, "stepMonths"),
- id = "#" + inst.id.replace( /\\\\/g, "\\" );
- inst.dpDiv.find("[data-handler]").map(function () {
- var handler = {
- prev: function () {
- $.datepicker._adjustDate(id, -stepMonths, "M");
- },
- next: function () {
- $.datepicker._adjustDate(id, +stepMonths, "M");
- },
- hide: function () {
- $.datepicker._hideDatepicker();
- },
- today: function () {
- $.datepicker._gotoToday(id);
- },
- selectDay: function () {
- $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
- return false;
- },
- selectMonth: function () {
- $.datepicker._selectMonthYear(id, this, "M");
- return false;
- },
- selectYear: function () {
- $.datepicker._selectMonthYear(id, this, "Y");
- return false;
- }
- };
- $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
- });
- },
-
- /* Generate the HTML for the current state of the date picker. */
- _generateHTML: function(inst) {
- var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
- controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
- monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
- selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
- cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
- printDate, dRow, tbody, daySettings, otherMonth, unselectable,
- tempDate = new Date(),
- today = this._daylightSavingAdjust(
- new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
- isRTL = this._get(inst, "isRTL"),
- showButtonPanel = this._get(inst, "showButtonPanel"),
- hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
- navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
- numMonths = this._getNumberOfMonths(inst),
- showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
- stepMonths = this._get(inst, "stepMonths"),
- isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
- currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
- new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
- minDate = this._getMinMaxDate(inst, "min"),
- maxDate = this._getMinMaxDate(inst, "max"),
- drawMonth = inst.drawMonth - showCurrentAtPos,
- drawYear = inst.drawYear;
-
- if (drawMonth < 0) {
- drawMonth += 12;
- drawYear--;
- }
- if (maxDate) {
- maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
- maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
- maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
- while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
- drawMonth--;
- if (drawMonth < 0) {
- drawMonth = 11;
- drawYear--;
- }
- }
- }
- inst.drawMonth = drawMonth;
- inst.drawYear = drawYear;
-
- prevText = this._get(inst, "prevText");
- prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
- this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
- this._getFormatConfig(inst)));
-
- prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
- "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
- " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
- (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
-
- nextText = this._get(inst, "nextText");
- nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
- this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
- this._getFormatConfig(inst)));
-
- next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
- "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
- " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
- (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
-
- currentText = this._get(inst, "currentText");
- gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
- currentText = (!navigationAsDateFormat ? currentText :
- this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
-
- controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
- this._get(inst, "closeText") + "</button>" : "");
-
- buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
- (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
- ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
-
- firstDay = parseInt(this._get(inst, "firstDay"),10);
- firstDay = (isNaN(firstDay) ? 0 : firstDay);
-
- showWeek = this._get(inst, "showWeek");
- dayNames = this._get(inst, "dayNames");
- dayNamesMin = this._get(inst, "dayNamesMin");
- monthNames = this._get(inst, "monthNames");
- monthNamesShort = this._get(inst, "monthNamesShort");
- beforeShowDay = this._get(inst, "beforeShowDay");
- showOtherMonths = this._get(inst, "showOtherMonths");
- selectOtherMonths = this._get(inst, "selectOtherMonths");
- defaultDate = this._getDefaultDate(inst);
- html = "";
- dow;
- for (row = 0; row < numMonths[0]; row++) {
- group = "";
- this.maxRows = 4;
- for (col = 0; col < numMonths[1]; col++) {
- selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
- cornerClass = " ui-corner-all";
- calender = "";
- if (isMultiMonth) {
- calender += "<div class='ui-datepicker-group";
- if (numMonths[1] > 1) {
- switch (col) {
- case 0: calender += " ui-datepicker-group-first";
- cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
- case numMonths[1]-1: calender += " ui-datepicker-group-last";
- cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
- default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
- }
- }
- calender += "'>";
- }
- calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
- (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
- (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
- this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
- row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
- "</div><table class='ui-datepicker-calendar'><thead>" +
- "<tr>";
- thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
- for (dow = 0; dow < 7; dow++) { // days of the week
- day = (dow + firstDay) % 7;
- thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
- "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
- }
- calender += thead + "</tr></thead><tbody>";
- daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
- if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
- inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
- }
- leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
- curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
- numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
- this.maxRows = numRows;
- printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
- for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
- calender += "<tr>";
- tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
- this._get(inst, "calculateWeek")(printDate) + "</td>");
- for (dow = 0; dow < 7; dow++) { // create date picker days
- daySettings = (beforeShowDay ?
- beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
- otherMonth = (printDate.getMonth() !== drawMonth);
- unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
- (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
- tbody += "<td class='" +
- ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
- (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
- ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
- (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
- // or defaultDate is current printedDate and defaultDate is selectedDate
- " " + this._dayOverClass : "") + // highlight selected day
- (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
- (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
- (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
- (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
- ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title
- (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
- (otherMonth && !showOtherMonths ? " " : // display for other months
- (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
- (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
- (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
- (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
- "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
- printDate.setDate(printDate.getDate() + 1);
- printDate = this._daylightSavingAdjust(printDate);
- }
- calender += tbody + "</tr>";
- }
- drawMonth++;
- if (drawMonth > 11) {
- drawMonth = 0;
- drawYear++;
- }
- calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
- ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
- group += calender;
- }
- html += group;
- }
- html += buttonPanel;
- inst._keyEvent = false;
- return html;
- },
-
- /* Generate the month and year header. */
- _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
- secondary, monthNames, monthNamesShort) {
-
- var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
- changeMonth = this._get(inst, "changeMonth"),
- changeYear = this._get(inst, "changeYear"),
- showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
- html = "<div class='ui-datepicker-title'>",
- monthHtml = "";
-
- // month selection
- if (secondary || !changeMonth) {
- monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
- } else {
- inMinYear = (minDate && minDate.getFullYear() === drawYear);
- inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
- monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
- for ( month = 0; month < 12; month++) {
- if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
- monthHtml += "<option value='" + month + "'" +
- (month === drawMonth ? " selected='selected'" : "") +
- ">" + monthNamesShort[month] + "</option>";
- }
- }
- monthHtml += "</select>";
- }
-
- if (!showMonthAfterYear) {
- html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
- }
-
- // year selection
- if ( !inst.yearshtml ) {
- inst.yearshtml = "";
- if (secondary || !changeYear) {
- html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
- } else {
- // determine range of years to display
- years = this._get(inst, "yearRange").split(":");
- thisYear = new Date().getFullYear();
- determineYear = function(value) {
- var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
- (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
- parseInt(value, 10)));
- return (isNaN(year) ? thisYear : year);
- };
- year = determineYear(years[0]);
- endYear = Math.max(year, determineYear(years[1] || ""));
- year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
- endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
- inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
- for (; year <= endYear; year++) {
- inst.yearshtml += "<option value='" + year + "'" +
- (year === drawYear ? " selected='selected'" : "") +
- ">" + year + "</option>";
- }
- inst.yearshtml += "</select>";
-
- html += inst.yearshtml;
- inst.yearshtml = null;
- }
- }
-
- html += this._get(inst, "yearSuffix");
- if (showMonthAfterYear) {
- html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
- }
- html += "</div>"; // Close datepicker_header
- return html;
- },
-
- /* Adjust one of the date sub-fields. */
- _adjustInstDate: function(inst, offset, period) {
- var year = inst.drawYear + (period === "Y" ? offset : 0),
- month = inst.drawMonth + (period === "M" ? offset : 0),
- day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
- date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
-
- inst.selectedDay = date.getDate();
- inst.drawMonth = inst.selectedMonth = date.getMonth();
- inst.drawYear = inst.selectedYear = date.getFullYear();
- if (period === "M" || period === "Y") {
- this._notifyChange(inst);
- }
- },
-
- /* Ensure a date is within any min/max bounds. */
- _restrictMinMax: function(inst, date) {
- var minDate = this._getMinMaxDate(inst, "min"),
- maxDate = this._getMinMaxDate(inst, "max"),
- newDate = (minDate && date < minDate ? minDate : date);
- return (maxDate && newDate > maxDate ? maxDate : newDate);
- },
-
- /* Notify change of month/year. */
- _notifyChange: function(inst) {
- var onChange = this._get(inst, "onChangeMonthYear");
- if (onChange) {
- onChange.apply((inst.input ? inst.input[0] : null),
- [inst.selectedYear, inst.selectedMonth + 1, inst]);
- }
- },
-
- /* Determine the number of months to show. */
- _getNumberOfMonths: function(inst) {
- var numMonths = this._get(inst, "numberOfMonths");
- return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
- },
-
- /* Determine the current maximum date - ensure no time components are set. */
- _getMinMaxDate: function(inst, minMax) {
- return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
- },
-
- /* Find the number of days in a given month. */
- _getDaysInMonth: function(year, month) {
- return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
- },
-
- /* Find the day of the week of the first of a month. */
- _getFirstDayOfMonth: function(year, month) {
- return new Date(year, month, 1).getDay();
- },
-
- /* Determines if we should allow a "next/prev" month display change. */
- _canAdjustMonth: function(inst, offset, curYear, curMonth) {
- var numMonths = this._getNumberOfMonths(inst),
- date = this._daylightSavingAdjust(new Date(curYear,
- curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
-
- if (offset < 0) {
- date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
- }
- return this._isInRange(inst, date);
- },
-
- /* Is the given date in the accepted range? */
- _isInRange: function(inst, date) {
- var yearSplit, currentYear,
- minDate = this._getMinMaxDate(inst, "min"),
- maxDate = this._getMinMaxDate(inst, "max"),
- minYear = null,
- maxYear = null,
- years = this._get(inst, "yearRange");
- if (years){
- yearSplit = years.split(":");
- currentYear = new Date().getFullYear();
- minYear = parseInt(yearSplit[0], 10);
- maxYear = parseInt(yearSplit[1], 10);
- if ( yearSplit[0].match(/[+\-].*/) ) {
- minYear += currentYear;
- }
- if ( yearSplit[1].match(/[+\-].*/) ) {
- maxYear += currentYear;
- }
- }
-
- return ((!minDate || date.getTime() >= minDate.getTime()) &&
- (!maxDate || date.getTime() <= maxDate.getTime()) &&
- (!minYear || date.getFullYear() >= minYear) &&
- (!maxYear || date.getFullYear() <= maxYear));
- },
-
- /* Provide the configuration settings for formatting/parsing. */
- _getFormatConfig: function(inst) {
- var shortYearCutoff = this._get(inst, "shortYearCutoff");
- shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
- new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
- return {shortYearCutoff: shortYearCutoff,
- dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
- monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
- },
-
- /* Format the given date for display. */
- _formatDate: function(inst, day, month, year) {
- if (!day) {
- inst.currentDay = inst.selectedDay;
- inst.currentMonth = inst.selectedMonth;
- inst.currentYear = inst.selectedYear;
- }
- var date = (day ? (typeof day === "object" ? day :
- this._daylightSavingAdjust(new Date(year, month, day))) :
- this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
- return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
- }
-});
-
-/*
- * Bind hover events for datepicker elements.
- * Done via delegate so the binding only occurs once in the lifetime of the parent div.
- * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
- */
-function bindHover(dpDiv) {
- var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
- return dpDiv.delegate(selector, "mouseout", function() {
- $(this).removeClass("ui-state-hover");
- if (this.className.indexOf("ui-datepicker-prev") !== -1) {
- $(this).removeClass("ui-datepicker-prev-hover");
- }
- if (this.className.indexOf("ui-datepicker-next") !== -1) {
- $(this).removeClass("ui-datepicker-next-hover");
- }
- })
- .delegate(selector, "mouseover", function(){
- if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
- $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
- $(this).addClass("ui-state-hover");
- if (this.className.indexOf("ui-datepicker-prev") !== -1) {
- $(this).addClass("ui-datepicker-prev-hover");
- }
- if (this.className.indexOf("ui-datepicker-next") !== -1) {
- $(this).addClass("ui-datepicker-next-hover");
- }
- }
- });
-}
-
-/* jQuery extend now ignores nulls! */
-function extendRemove(target, props) {
- $.extend(target, props);
- for (var name in props) {
- if (props[name] == null) {
- target[name] = props[name];
- }
- }
- return target;
-}
-
-/* Invoke the datepicker functionality.
- @param options string - a command, optionally followed by additional parameters or
- Object - settings for attaching new datepicker functionality
- @return jQuery object */
-$.fn.datepicker = function(options){
-
- /* Verify an empty collection wasn't passed - Fixes #6976 */
- if ( !this.length ) {
- return this;
- }
-
- /* Initialise the date picker. */
- if (!$.datepicker.initialized) {
- $(document).mousedown($.datepicker._checkExternalClick);
- $.datepicker.initialized = true;
- }
-
- /* Append datepicker main container to body if not exist. */
- if ($("#"+$.datepicker._mainDivId).length === 0) {
- $("body").append($.datepicker.dpDiv);
- }
-
- var otherArgs = Array.prototype.slice.call(arguments, 1);
- if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
- return $.datepicker["_" + options + "Datepicker"].
- apply($.datepicker, [this[0]].concat(otherArgs));
- }
- if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
- return $.datepicker["_" + options + "Datepicker"].
- apply($.datepicker, [this[0]].concat(otherArgs));
- }
- return this.each(function() {
- typeof options === "string" ?
- $.datepicker["_" + options + "Datepicker"].
- apply($.datepicker, [this].concat(otherArgs)) :
- $.datepicker._attachDatepicker(this, options);
- });
-};
-
-$.datepicker = new Datepicker(); // singleton instance
-$.datepicker.initialized = false;
-$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "1.10.3";
-
-})(jQuery);
-(function( $, undefined ) {
-
-// number of pages in a slider
-// (how many times can you page up/down to go through the whole range)
-var numPages = 5;
-
-$.widget( "ui.slider", $.ui.mouse, {
- version: "1.10.3",
- widgetEventPrefix: "slide",
-
- options: {
- animate: false,
- distance: 0,
- max: 100,
- min: 0,
- orientation: "horizontal",
- range: false,
- step: 1,
- value: 0,
- values: null,
-
- // callbacks
- change: null,
- slide: null,
- start: null,
- stop: null
- },
-
- _create: function() {
- this._keySliding = false;
- this._mouseSliding = false;
- this._animateOff = true;
- this._handleIndex = null;
- this._detectOrientation();
- this._mouseInit();
-
- this.element
- .addClass( "ui-slider" +
- " ui-slider-" + this.orientation +
- " ui-widget" +
- " ui-widget-content" +
- " ui-corner-all");
-
- this._refresh();
- this._setOption( "disabled", this.options.disabled );
-
- this._animateOff = false;
- },
-
- _refresh: function() {
- this._createRange();
- this._createHandles();
- this._setupEvents();
- this._refreshValue();
- },
-
- _createHandles: function() {
- var i, handleCount,
- options = this.options,
- existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
- handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
- handles = [];
-
- handleCount = ( options.values && options.values.length ) || 1;
-
- if ( existingHandles.length > handleCount ) {
- existingHandles.slice( handleCount ).remove();
- existingHandles = existingHandles.slice( 0, handleCount );
- }
-
- for ( i = existingHandles.length; i < handleCount; i++ ) {
- handles.push( handle );
- }
-
- this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
-
- this.handle = this.handles.eq( 0 );
-
- this.handles.each(function( i ) {
- $( this ).data( "ui-slider-handle-index", i );
- });
- },
-
- _createRange: function() {
- var options = this.options,
- classes = "";
-
- if ( options.range ) {
- if ( options.range === true ) {
- if ( !options.values ) {
- options.values = [ this._valueMin(), this._valueMin() ];
- } else if ( options.values.length && options.values.length !== 2 ) {
- options.values = [ options.values[0], options.values[0] ];
- } else if ( $.isArray( options.values ) ) {
- options.values = options.values.slice(0);
- }
- }
-
- if ( !this.range || !this.range.length ) {
- this.range = $( "<div></div>" )
- .appendTo( this.element );
-
- classes = "ui-slider-range" +
- // note: this isn't the most fittingly semantic framework class for this element,
- // but worked best visually with a variety of themes
- " ui-widget-header ui-corner-all";
- } else {
- this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
- // Handle range switching from true to min/max
- .css({
- "left": "",
- "bottom": ""
- });
- }
-
- this.range.addClass( classes +
- ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
- } else {
- this.range = $([]);
- }
- },
-
- _setupEvents: function() {
- var elements = this.handles.add( this.range ).filter( "a" );
- this._off( elements );
- this._on( elements, this._handleEvents );
- this._hoverable( elements );
- this._focusable( elements );
- },
-
- _destroy: function() {
- this.handles.remove();
- this.range.remove();
-
- this.element
- .removeClass( "ui-slider" +
- " ui-slider-horizontal" +
- " ui-slider-vertical" +
- " ui-widget" +
- " ui-widget-content" +
- " ui-corner-all" );
-
- this._mouseDestroy();
- },
-
- _mouseCapture: function( event ) {
- var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
- that = this,
- o = this.options;
-
- if ( o.disabled ) {
- return false;
- }
-
- this.elementSize = {
- width: this.element.outerWidth(),
- height: this.element.outerHeight()
- };
- this.elementOffset = this.element.offset();
-
- position = { x: event.pageX, y: event.pageY };
- normValue = this._normValueFromMouse( position );
- distance = this._valueMax() - this._valueMin() + 1;
- this.handles.each(function( i ) {
- var thisDistance = Math.abs( normValue - that.values(i) );
- if (( distance > thisDistance ) ||
- ( distance === thisDistance &&
- (i === that._lastChangedValue || that.values(i) === o.min ))) {
- distance = thisDistance;
- closestHandle = $( this );
- index = i;
- }
- });
-
- allowed = this._start( event, index );
- if ( allowed === false ) {
- return false;
- }
- this._mouseSliding = true;
-
- this._handleIndex = index;
-
- closestHandle
- .addClass( "ui-state-active" )
- .focus();
-
- offset = closestHandle.offset();
- mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
- this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
- left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
- top: event.pageY - offset.top -
- ( closestHandle.height() / 2 ) -
- ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
- ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
- ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
- };
-
- if ( !this.handles.hasClass( "ui-state-hover" ) ) {
- this._slide( event, index, normValue );
- }
- this._animateOff = true;
- return true;
- },
-
- _mouseStart: function() {
- return true;
- },
-
- _mouseDrag: function( event ) {
- var position = { x: event.pageX, y: event.pageY },
- normValue = this._normValueFromMouse( position );
-
- this._slide( event, this._handleIndex, normValue );
-
- return false;
- },
-
- _mouseStop: function( event ) {
- this.handles.removeClass( "ui-state-active" );
- this._mouseSliding = false;
-
- this._stop( event, this._handleIndex );
- this._change( event, this._handleIndex );
-
- this._handleIndex = null;
- this._clickOffset = null;
- this._animateOff = false;
-
- return false;
- },
-
- _detectOrientation: function() {
- this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
- },
-
- _normValueFromMouse: function( position ) {
- var pixelTotal,
- pixelMouse,
- percentMouse,
- valueTotal,
- valueMouse;
-
- if ( this.orientation === "horizontal" ) {
- pixelTotal = this.elementSize.width;
- pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
- } else {
- pixelTotal = this.elementSize.height;
- pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
- }
-
- percentMouse = ( pixelMouse / pixelTotal );
- if ( percentMouse > 1 ) {
- percentMouse = 1;
- }
- if ( percentMouse < 0 ) {
- percentMouse = 0;
- }
- if ( this.orientation === "vertical" ) {
- percentMouse = 1 - percentMouse;
- }
-
- valueTotal = this._valueMax() - this._valueMin();
- valueMouse = this._valueMin() + percentMouse * valueTotal;
-
- return this._trimAlignValue( valueMouse );
- },
-
- _start: function( event, index ) {
- var uiHash = {
- handle: this.handles[ index ],
- value: this.value()
- };
- if ( this.options.values && this.options.values.length ) {
- uiHash.value = this.values( index );
- uiHash.values = this.values();
- }
- return this._trigger( "start", event, uiHash );
- },
-
- _slide: function( event, index, newVal ) {
- var otherVal,
- newValues,
- allowed;
-
- if ( this.options.values && this.options.values.length ) {
- otherVal = this.values( index ? 0 : 1 );
-
- if ( ( this.options.values.length === 2 && this.options.range === true ) &&
- ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
- ) {
- newVal = otherVal;
- }
-
- if ( newVal !== this.values( index ) ) {
- newValues = this.values();
- newValues[ index ] = newVal;
- // A slide can be canceled by returning false from the slide callback
- allowed = this._trigger( "slide", event, {
- handle: this.handles[ index ],
- value: newVal,
- values: newValues
- } );
- otherVal = this.values( index ? 0 : 1 );
- if ( allowed !== false ) {
- this.values( index, newVal, true );
- }
- }
- } else {
- if ( newVal !== this.value() ) {
- // A slide can be canceled by returning false from the slide callback
- allowed = this._trigger( "slide", event, {
- handle: this.handles[ index ],
- value: newVal
- } );
- if ( allowed !== false ) {
- this.value( newVal );
- }
- }
- }
- },
-
- _stop: function( event, index ) {
- var uiHash = {
- handle: this.handles[ index ],
- value: this.value()
- };
- if ( this.options.values && this.options.values.length ) {
- uiHash.value = this.values( index );
- uiHash.values = this.values();
- }
-
- this._trigger( "stop", event, uiHash );
- },
-
- _change: function( event, index ) {
- if ( !this._keySliding && !this._mouseSliding ) {
- var uiHash = {
- handle: this.handles[ index ],
- value: this.value()
- };
- if ( this.options.values && this.options.values.length ) {
- uiHash.value = this.values( index );
- uiHash.values = this.values();
- }
-
- //store the last changed value index for reference when handles overlap
- this._lastChangedValue = index;
-
- this._trigger( "change", event, uiHash );
- }
- },
-
- value: function( newValue ) {
- if ( arguments.length ) {
- this.options.value = this._trimAlignValue( newValue );
- this._refreshValue();
- this._change( null, 0 );
- return;
- }
-
- return this._value();
- },
-
- values: function( index, newValue ) {
- var vals,
- newValues,
- i;
-
- if ( arguments.length > 1 ) {
- this.options.values[ index ] = this._trimAlignValue( newValue );
- this._refreshValue();
- this._change( null, index );
- return;
- }
-
- if ( arguments.length ) {
- if ( $.isArray( arguments[ 0 ] ) ) {
- vals = this.options.values;
- newValues = arguments[ 0 ];
- for ( i = 0; i < vals.length; i += 1 ) {
- vals[ i ] = this._trimAlignValue( newValues[ i ] );
- this._change( null, i );
- }
- this._refreshValue();
- } else {
- if ( this.options.values && this.options.values.length ) {
- return this._values( index );
- } else {
- return this.value();
- }
- }
- } else {
- return this._values();
- }
- },
-
- _setOption: function( key, value ) {
- var i,
- valsLength = 0;
-
- if ( key === "range" && this.options.range === true ) {
- if ( value === "min" ) {
- this.options.value = this._values( 0 );
- this.options.values = null;
- } else if ( value === "max" ) {
- this.options.value = this._values( this.options.values.length-1 );
- this.options.values = null;
- }
- }
-
- if ( $.isArray( this.options.values ) ) {
- valsLength = this.options.values.length;
- }
-
- $.Widget.prototype._setOption.apply( this, arguments );
-
- switch ( key ) {
- case "orientation":
- this._detectOrientation();
- this.element
- .removeClass( "ui-slider-horizontal ui-slider-vertical" )
- .addClass( "ui-slider-" + this.orientation );
- this._refreshValue();
- break;
- case "value":
- this._animateOff = true;
- this._refreshValue();
- this._change( null, 0 );
- this._animateOff = false;
- break;
- case "values":
- this._animateOff = true;
- this._refreshValue();
- for ( i = 0; i < valsLength; i += 1 ) {
- this._change( null, i );
- }
- this._animateOff = false;
- break;
- case "min":
- case "max":
- this._animateOff = true;
- this._refreshValue();
- this._animateOff = false;
- break;
- case "range":
- this._animateOff = true;
- this._refresh();
- this._animateOff = false;
- break;
- }
- },
-
- //internal value getter
- // _value() returns value trimmed by min and max, aligned by step
- _value: function() {
- var val = this.options.value;
- val = this._trimAlignValue( val );
-
- return val;
- },
-
- //internal values getter
- // _values() returns array of values trimmed by min and max, aligned by step
- // _values( index ) returns single value trimmed by min and max, aligned by step
- _values: function( index ) {
- var val,
- vals,
- i;
-
- if ( arguments.length ) {
- val = this.options.values[ index ];
- val = this._trimAlignValue( val );
-
- return val;
- } else if ( this.options.values && this.options.values.length ) {
- // .slice() creates a copy of the array
- // this copy gets trimmed by min and max and then returned
- vals = this.options.values.slice();
- for ( i = 0; i < vals.length; i+= 1) {
- vals[ i ] = this._trimAlignValue( vals[ i ] );
- }
-
- return vals;
- } else {
- return [];
- }
- },
-
- // returns the step-aligned value that val is closest to, between (inclusive) min and max
- _trimAlignValue: function( val ) {
- if ( val <= this._valueMin() ) {
- return this._valueMin();
- }
- if ( val >= this._valueMax() ) {
- return this._valueMax();
- }
- var step = ( this.options.step > 0 ) ? this.options.step : 1,
- valModStep = (val - this._valueMin()) % step,
- alignValue = val - valModStep;
-
- if ( Math.abs(valModStep) * 2 >= step ) {
- alignValue += ( valModStep > 0 ) ? step : ( -step );
- }
-
- // Since JavaScript has problems with large floats, round
- // the final value to 5 digits after the decimal point (see #4124)
- return parseFloat( alignValue.toFixed(5) );
- },
-
- _valueMin: function() {
- return this.options.min;
- },
-
- _valueMax: function() {
- return this.options.max;
- },
-
- _refreshValue: function() {
- var lastValPercent, valPercent, value, valueMin, valueMax,
- oRange = this.options.range,
- o = this.options,
- that = this,
- animate = ( !this._animateOff ) ? o.animate : false,
- _set = {};
-
- if ( this.options.values && this.options.values.length ) {
- this.handles.each(function( i ) {
- valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
- _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
- $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
- if ( that.options.range === true ) {
- if ( that.orientation === "horizontal" ) {
- if ( i === 0 ) {
- that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
- }
- if ( i === 1 ) {
- that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
- }
- } else {
- if ( i === 0 ) {
- that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
- }
- if ( i === 1 ) {
- that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
- }
- }
- }
- lastValPercent = valPercent;
- });
- } else {
- value = this.value();
- valueMin = this._valueMin();
- valueMax = this._valueMax();
- valPercent = ( valueMax !== valueMin ) ?
- ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
- 0;
- _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
- this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
-
- if ( oRange === "min" && this.orientation === "horizontal" ) {
- this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
- }
- if ( oRange === "max" && this.orientation === "horizontal" ) {
- this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
- }
- if ( oRange === "min" && this.orientation === "vertical" ) {
- this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
- }
- if ( oRange === "max" && this.orientation === "vertical" ) {
- this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
- }
- }
- },
-
- _handleEvents: {
- keydown: function( event ) {
- /*jshint maxcomplexity:25*/
- var allowed, curVal, newVal, step,
- index = $( event.target ).data( "ui-slider-handle-index" );
-
- switch ( event.keyCode ) {
- case $.ui.keyCode.HOME:
- case $.ui.keyCode.END:
- case $.ui.keyCode.PAGE_UP:
- case $.ui.keyCode.PAGE_DOWN:
- case $.ui.keyCode.UP:
- case $.ui.keyCode.RIGHT:
- case $.ui.keyCode.DOWN:
- case $.ui.keyCode.LEFT:
- event.preventDefault();
- if ( !this._keySliding ) {
- this._keySliding = true;
- $( event.target ).addClass( "ui-state-active" );
- allowed = this._start( event, index );
- if ( allowed === false ) {
- return;
- }
- }
- break;
- }
-
- step = this.options.step;
- if ( this.options.values && this.options.values.length ) {
- curVal = newVal = this.values( index );
- } else {
- curVal = newVal = this.value();
- }
-
- switch ( event.keyCode ) {
- case $.ui.keyCode.HOME:
- newVal = this._valueMin();
- break;
- case $.ui.keyCode.END:
- newVal = this._valueMax();
- break;
- case $.ui.keyCode.PAGE_UP:
- newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
- break;
- case $.ui.keyCode.PAGE_DOWN:
- newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
- break;
- case $.ui.keyCode.UP:
- case $.ui.keyCode.RIGHT:
- if ( curVal === this._valueMax() ) {
- return;
- }
- newVal = this._trimAlignValue( curVal + step );
- break;
- case $.ui.keyCode.DOWN:
- case $.ui.keyCode.LEFT:
- if ( curVal === this._valueMin() ) {
- return;
- }
- newVal = this._trimAlignValue( curVal - step );
- break;
- }
-
- this._slide( event, index, newVal );
- },
- click: function( event ) {
- event.preventDefault();
- },
- keyup: function( event ) {
- var index = $( event.target ).data( "ui-slider-handle-index" );
-
- if ( this._keySliding ) {
- this._keySliding = false;
- this._stop( event, index );
- this._change( event, index );
- $( event.target ).removeClass( "ui-state-active" );
- }
- }
- }
-
-});
-
-}(jQuery));
-(function( $ ) {
-
-function modifier( fn ) {
- return function() {
- var previous = this.element.val();
- fn.apply( this, arguments );
- this._refresh();
- if ( previous !== this.element.val() ) {
- this._trigger( "change" );
- }
- };
-}
-
-$.widget( "ui.spinner", {
- version: "1.10.3",
- defaultElement: "<input>",
- widgetEventPrefix: "spin",
- options: {
- culture: null,
- icons: {
- down: "ui-icon-triangle-1-s",
- up: "ui-icon-triangle-1-n"
- },
- incremental: true,
- max: null,
- min: null,
- numberFormat: null,
- page: 10,
- step: 1,
-
- change: null,
- spin: null,
- start: null,
- stop: null
- },
-
- _create: function() {
- // handle string values that need to be parsed
- this._setOption( "max", this.options.max );
- this._setOption( "min", this.options.min );
- this._setOption( "step", this.options.step );
-
- // format the value, but don't constrain
- this._value( this.element.val(), true );
-
- this._draw();
- this._on( this._events );
- this._refresh();
-
- // turning off autocomplete prevents the browser from remembering the
- // value when navigating through history, so we re-enable autocomplete
- // if the page is unloaded before the widget is destroyed. #7790
- this._on( this.window, {
- beforeunload: function() {
- this.element.removeAttr( "autocomplete" );
- }
- });
- },
-
- _getCreateOptions: function() {
- var options = {},
- element = this.element;
-
- $.each( [ "min", "max", "step" ], function( i, option ) {
- var value = element.attr( option );
- if ( value !== undefined && value.length ) {
- options[ option ] = value;
- }
- });
-
- return options;
- },
-
- _events: {
- keydown: function( event ) {
- if ( this._start( event ) && this._keydown( event ) ) {
- event.preventDefault();
- }
- },
- keyup: "_stop",
- focus: function() {
- this.previous = this.element.val();
- },
- blur: function( event ) {
- if ( this.cancelBlur ) {
- delete this.cancelBlur;
- return;
- }
-
- this._stop();
- this._refresh();
- if ( this.previous !== this.element.val() ) {
- this._trigger( "change", event );
- }
- },
- mousewheel: function( event, delta ) {
- if ( !delta ) {
- return;
- }
- if ( !this.spinning && !this._start( event ) ) {
- return false;
- }
-
- this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
- clearTimeout( this.mousewheelTimer );
- this.mousewheelTimer = this._delay(function() {
- if ( this.spinning ) {
- this._stop( event );
- }
- }, 100 );
- event.preventDefault();
- },
- "mousedown .ui-spinner-button": function( event ) {
- var previous;
-
- // We never want the buttons to have focus; whenever the user is
- // interacting with the spinner, the focus should be on the input.
- // If the input is focused then this.previous is properly set from
- // when the input first received focus. If the input is not focused
- // then we need to set this.previous based on the value before spinning.
- previous = this.element[0] === this.document[0].activeElement ?
- this.previous : this.element.val();
- function checkFocus() {
- var isActive = this.element[0] === this.document[0].activeElement;
- if ( !isActive ) {
- this.element.focus();
- this.previous = previous;
- // support: IE
- // IE sets focus asynchronously, so we need to check if focus
- // moved off of the input because the user clicked on the button.
- this._delay(function() {
- this.previous = previous;
- });
- }
- }
-
- // ensure focus is on (or stays on) the text field
- event.preventDefault();
- checkFocus.call( this );
-
- // support: IE
- // IE doesn't prevent moving focus even with event.preventDefault()
- // so we set a flag to know when we should ignore the blur event
- // and check (again) if focus moved off of the input.
- this.cancelBlur = true;
- this._delay(function() {
- delete this.cancelBlur;
- checkFocus.call( this );
- });
-
- if ( this._start( event ) === false ) {
- return;
- }
-
- this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
- },
- "mouseup .ui-spinner-button": "_stop",
- "mouseenter .ui-spinner-button": function( event ) {
- // button will add ui-state-active if mouse was down while mouseleave and kept down
- if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
- return;
- }
-
- if ( this._start( event ) === false ) {
- return false;
- }
- this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
- },
- // TODO: do we really want to consider this a stop?
- // shouldn't we just stop the repeater and wait until mouseup before
- // we trigger the stop event?
- "mouseleave .ui-spinner-button": "_stop"
- },
-
- _draw: function() {
- var uiSpinner = this.uiSpinner = this.element
- .addClass( "ui-spinner-input" )
- .attr( "autocomplete", "off" )
- .wrap( this._uiSpinnerHtml() )
- .parent()
- // add buttons
- .append( this._buttonHtml() );
-
- this.element.attr( "role", "spinbutton" );
-
- // button bindings
- this.buttons = uiSpinner.find( ".ui-spinner-button" )
- .attr( "tabIndex", -1 )
- .button()
- .removeClass( "ui-corner-all" );
-
- // IE 6 doesn't understand height: 50% for the buttons
- // unless the wrapper has an explicit height
- if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
- uiSpinner.height() > 0 ) {
- uiSpinner.height( uiSpinner.height() );
- }
-
- // disable spinner if element was already disabled
- if ( this.options.disabled ) {
- this.disable();
- }
- },
-
- _keydown: function( event ) {
- var options = this.options,
- keyCode = $.ui.keyCode;
-
- switch ( event.keyCode ) {
- case keyCode.UP:
- this._repeat( null, 1, event );
- return true;
- case keyCode.DOWN:
- this._repeat( null, -1, event );
- return true;
- case keyCode.PAGE_UP:
- this._repeat( null, options.page, event );
- return true;
- case keyCode.PAGE_DOWN:
- this._repeat( null, -options.page, event );
- return true;
- }
-
- return false;
- },
-
- _uiSpinnerHtml: function() {
- return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
- },
-
- _buttonHtml: function() {
- return "" +
- "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
- "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" +
- "</a>" +
- "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
- "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" +
- "</a>";
- },
-
- _start: function( event ) {
- if ( !this.spinning && this._trigger( "start", event ) === false ) {
- return false;
- }
-
- if ( !this.counter ) {
- this.counter = 1;
- }
- this.spinning = true;
- return true;
- },
-
- _repeat: function( i, steps, event ) {
- i = i || 500;
-
- clearTimeout( this.timer );
- this.timer = this._delay(function() {
- this._repeat( 40, steps, event );
- }, i );
-
- this._spin( steps * this.options.step, event );
- },
-
- _spin: function( step, event ) {
- var value = this.value() || 0;
-
- if ( !this.counter ) {
- this.counter = 1;
- }
-
- value = this._adjustValue( value + step * this._increment( this.counter ) );
-
- if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
- this._value( value );
- this.counter++;
- }
- },
-
- _increment: function( i ) {
- var incremental = this.options.incremental;
-
- if ( incremental ) {
- return $.isFunction( incremental ) ?
- incremental( i ) :
- Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
- }
-
- return 1;
- },
-
- _precision: function() {
- var precision = this._precisionOf( this.options.step );
- if ( this.options.min !== null ) {
- precision = Math.max( precision, this._precisionOf( this.options.min ) );
- }
- return precision;
- },
-
- _precisionOf: function( num ) {
- var str = num.toString(),
- decimal = str.indexOf( "." );
- return decimal === -1 ? 0 : str.length - decimal - 1;
- },
-
- _adjustValue: function( value ) {
- var base, aboveMin,
- options = this.options;
-
- // make sure we're at a valid step
- // - find out where we are relative to the base (min or 0)
- base = options.min !== null ? options.min : 0;
- aboveMin = value - base;
- // - round to the nearest step
- aboveMin = Math.round(aboveMin / options.step) * options.step;
- // - rounding is based on 0, so adjust back to our base
- value = base + aboveMin;
-
- // fix precision from bad JS floating point math
- value = parseFloat( value.toFixed( this._precision() ) );
-
- // clamp the value
- if ( options.max !== null && value > options.max) {
- return options.max;
- }
- if ( options.min !== null && value < options.min ) {
- return options.min;
- }
-
- return value;
- },
-
- _stop: function( event ) {
- if ( !this.spinning ) {
- return;
- }
-
- clearTimeout( this.timer );
- clearTimeout( this.mousewheelTimer );
- this.counter = 0;
- this.spinning = false;
- this._trigger( "stop", event );
- },
-
- _setOption: function( key, value ) {
- if ( key === "culture" || key === "numberFormat" ) {
- var prevValue = this._parse( this.element.val() );
- this.options[ key ] = value;
- this.element.val( this._format( prevValue ) );
- return;
- }
-
- if ( key === "max" || key === "min" || key === "step" ) {
- if ( typeof value === "string" ) {
- value = this._parse( value );
- }
- }
- if ( key === "icons" ) {
- this.buttons.first().find( ".ui-icon" )
- .removeClass( this.options.icons.up )
- .addClass( value.up );
- this.buttons.last().find( ".ui-icon" )
- .removeClass( this.options.icons.down )
- .addClass( value.down );
- }
-
- this._super( key, value );
-
- if ( key === "disabled" ) {
- if ( value ) {
- this.element.prop( "disabled", true );
- this.buttons.button( "disable" );
- } else {
- this.element.prop( "disabled", false );
- this.buttons.button( "enable" );
- }
- }
- },
-
- _setOptions: modifier(function( options ) {
- this._super( options );
- this._value( this.element.val() );
- }),
-
- _parse: function( val ) {
- if ( typeof val === "string" && val !== "" ) {
- val = window.Globalize && this.options.numberFormat ?
- Globalize.parseFloat( val, 10, this.options.culture ) : +val;
- }
- return val === "" || isNaN( val ) ? null : val;
- },
-
- _format: function( value ) {
- if ( value === "" ) {
- return "";
- }
- return window.Globalize && this.options.numberFormat ?
- Globalize.format( value, this.options.numberFormat, this.options.culture ) :
- value;
- },
-
- _refresh: function() {
- this.element.attr({
- "aria-valuemin": this.options.min,
- "aria-valuemax": this.options.max,
- // TODO: what should we do with values that can't be parsed?
- "aria-valuenow": this._parse( this.element.val() )
- });
- },
-
- // update the value without triggering change
- _value: function( value, allowAny ) {
- var parsed;
- if ( value !== "" ) {
- parsed = this._parse( value );
- if ( parsed !== null ) {
- if ( !allowAny ) {
- parsed = this._adjustValue( parsed );
- }
- value = this._format( parsed );
- }
- }
- this.element.val( value );
- this._refresh();
- },
-
- _destroy: function() {
- this.element
- .removeClass( "ui-spinner-input" )
- .prop( "disabled", false )
- .removeAttr( "autocomplete" )
- .removeAttr( "role" )
- .removeAttr( "aria-valuemin" )
- .removeAttr( "aria-valuemax" )
- .removeAttr( "aria-valuenow" );
- this.uiSpinner.replaceWith( this.element );
- },
-
- stepUp: modifier(function( steps ) {
- this._stepUp( steps );
- }),
- _stepUp: function( steps ) {
- if ( this._start() ) {
- this._spin( (steps || 1) * this.options.step );
- this._stop();
- }
- },
-
- stepDown: modifier(function( steps ) {
- this._stepDown( steps );
- }),
- _stepDown: function( steps ) {
- if ( this._start() ) {
- this._spin( (steps || 1) * -this.options.step );
- this._stop();
- }
- },
-
- pageUp: modifier(function( pages ) {
- this._stepUp( (pages || 1) * this.options.page );
- }),
-
- pageDown: modifier(function( pages ) {
- this._stepDown( (pages || 1) * this.options.page );
- }),
-
- value: function( newVal ) {
- if ( !arguments.length ) {
- return this._parse( this.element.val() );
- }
- modifier( this._value ).call( this, newVal );
- },
-
- widget: function() {
- return this.uiSpinner;
- }
-});
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-var tabId = 0,
- rhash = /#.*$/;
-
-function getNextTabId() {
- return ++tabId;
-}
-
-function isLocal( anchor ) {
- return anchor.hash.length > 1 &&
- decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
- decodeURIComponent( location.href.replace( rhash, "" ) );
-}
-
-$.widget( "ui.tabs", {
- version: "1.10.3",
- delay: 300,
- options: {
- active: null,
- collapsible: false,
- event: "click",
- heightStyle: "content",
- hide: null,
- show: null,
-
- // callbacks
- activate: null,
- beforeActivate: null,
- beforeLoad: null,
- load: null
- },
-
- _create: function() {
- var that = this,
- options = this.options;
-
- this.running = false;
-
- this.element
- .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
- .toggleClass( "ui-tabs-collapsible", options.collapsible )
- // Prevent users from focusing disabled tabs via click
- .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
- if ( $( this ).is( ".ui-state-disabled" ) ) {
- event.preventDefault();
- }
- })
- // support: IE <9
- // Preventing the default action in mousedown doesn't prevent IE
- // from focusing the element, so if the anchor gets focused, blur.
- // We don't have to worry about focusing the previously focused
- // element since clicking on a non-focusable element should focus
- // the body anyway.
- .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
- if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
- this.blur();
- }
- });
-
- this._processTabs();
- options.active = this._initialActive();
-
- // Take disabling tabs via class attribute from HTML
- // into account and update option properly.
- if ( $.isArray( options.disabled ) ) {
- options.disabled = $.unique( options.disabled.concat(
- $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
- return that.tabs.index( li );
- })
- ) ).sort();
- }
-
- // check for length avoids error when initializing empty list
- if ( this.options.active !== false && this.anchors.length ) {
- this.active = this._findActive( options.active );
- } else {
- this.active = $();
- }
-
- this._refresh();
-
- if ( this.active.length ) {
- this.load( options.active );
- }
- },
-
- _initialActive: function() {
- var active = this.options.active,
- collapsible = this.options.collapsible,
- locationHash = location.hash.substring( 1 );
-
- if ( active === null ) {
- // check the fragment identifier in the URL
- if ( locationHash ) {
- this.tabs.each(function( i, tab ) {
- if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
- active = i;
- return false;
- }
- });
- }
-
- // check for a tab marked active via a class
- if ( active === null ) {
- active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
- }
-
- // no active tab, set to false
- if ( active === null || active === -1 ) {
- active = this.tabs.length ? 0 : false;
- }
- }
-
- // handle numbers: negative, out of range
- if ( active !== false ) {
- active = this.tabs.index( this.tabs.eq( active ) );
- if ( active === -1 ) {
- active = collapsible ? false : 0;
- }
- }
-
- // don't allow collapsible: false and active: false
- if ( !collapsible && active === false && this.anchors.length ) {
- active = 0;
- }
-
- return active;
- },
-
- _getCreateEventData: function() {
- return {
- tab: this.active,
- panel: !this.active.length ? $() : this._getPanelForTab( this.active )
- };
- },
-
- _tabKeydown: function( event ) {
- /*jshint maxcomplexity:15*/
- var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
- selectedIndex = this.tabs.index( focusedTab ),
- goingForward = true;
-
- if ( this._handlePageNav( event ) ) {
- return;
- }
-
- switch ( event.keyCode ) {
- case $.ui.keyCode.RIGHT:
- case $.ui.keyCode.DOWN:
- selectedIndex++;
- break;
- case $.ui.keyCode.UP:
- case $.ui.keyCode.LEFT:
- goingForward = false;
- selectedIndex--;
- break;
- case $.ui.keyCode.END:
- selectedIndex = this.anchors.length - 1;
- break;
- case $.ui.keyCode.HOME:
- selectedIndex = 0;
- break;
- case $.ui.keyCode.SPACE:
- // Activate only, no collapsing
- event.preventDefault();
- clearTimeout( this.activating );
- this._activate( selectedIndex );
- return;
- case $.ui.keyCode.ENTER:
- // Toggle (cancel delayed activation, allow collapsing)
- event.preventDefault();
- clearTimeout( this.activating );
- // Determine if we should collapse or activate
- this._activate( selectedIndex === this.options.active ? false : selectedIndex );
- return;
- default:
- return;
- }
-
- // Focus the appropriate tab, based on which key was pressed
- event.preventDefault();
- clearTimeout( this.activating );
- selectedIndex = this._focusNextTab( selectedIndex, goingForward );
-
- // Navigating with control key will prevent automatic activation
- if ( !event.ctrlKey ) {
- // Update aria-selected immediately so that AT think the tab is already selected.
- // Otherwise AT may confuse the user by stating that they need to activate the tab,
- // but the tab will already be activated by the time the announcement finishes.
- focusedTab.attr( "aria-selected", "false" );
- this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
-
- this.activating = this._delay(function() {
- this.option( "active", selectedIndex );
- }, this.delay );
- }
- },
-
- _panelKeydown: function( event ) {
- if ( this._handlePageNav( event ) ) {
- return;
- }
-
- // Ctrl+up moves focus to the current tab
- if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
- event.preventDefault();
- this.active.focus();
- }
- },
-
- // Alt+page up/down moves focus to the previous/next tab (and activates)
- _handlePageNav: function( event ) {
- if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
- this._activate( this._focusNextTab( this.options.active - 1, false ) );
- return true;
- }
- if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
- this._activate( this._focusNextTab( this.options.active + 1, true ) );
- return true;
- }
- },
-
- _findNextTab: function( index, goingForward ) {
- var lastTabIndex = this.tabs.length - 1;
-
- function constrain() {
- if ( index > lastTabIndex ) {
- index = 0;
- }
- if ( index < 0 ) {
- index = lastTabIndex;
- }
- return index;
- }
-
- while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
- index = goingForward ? index + 1 : index - 1;
- }
-
- return index;
- },
-
- _focusNextTab: function( index, goingForward ) {
- index = this._findNextTab( index, goingForward );
- this.tabs.eq( index ).focus();
- return index;
- },
-
- _setOption: function( key, value ) {
- if ( key === "active" ) {
- // _activate() will handle invalid values and update this.options
- this._activate( value );
- return;
- }
-
- if ( key === "disabled" ) {
- // don't use the widget factory's disabled handling
- this._setupDisabled( value );
- return;
- }
-
- this._super( key, value);
-
- if ( key === "collapsible" ) {
- this.element.toggleClass( "ui-tabs-collapsible", value );
- // Setting collapsible: false while collapsed; open first panel
- if ( !value && this.options.active === false ) {
- this._activate( 0 );
- }
- }
-
- if ( key === "event" ) {
- this._setupEvents( value );
- }
-
- if ( key === "heightStyle" ) {
- this._setupHeightStyle( value );
- }
- },
-
- _tabId: function( tab ) {
- return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
- },
-
- _sanitizeSelector: function( hash ) {
- return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
- },
-
- refresh: function() {
- var options = this.options,
- lis = this.tablist.children( ":has(a[href])" );
-
- // get disabled tabs from class attribute from HTML
- // this will get converted to a boolean if needed in _refresh()
- options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
- return lis.index( tab );
- });
-
- this._processTabs();
-
- // was collapsed or no tabs
- if ( options.active === false || !this.anchors.length ) {
- options.active = false;
- this.active = $();
- // was active, but active tab is gone
- } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
- // all remaining tabs are disabled
- if ( this.tabs.length === options.disabled.length ) {
- options.active = false;
- this.active = $();
- // activate previous tab
- } else {
- this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
- }
- // was active, active tab still exists
- } else {
- // make sure active index is correct
- options.active = this.tabs.index( this.active );
- }
-
- this._refresh();
- },
-
- _refresh: function() {
- this._setupDisabled( this.options.disabled );
- this._setupEvents( this.options.event );
- this._setupHeightStyle( this.options.heightStyle );
-
- this.tabs.not( this.active ).attr({
- "aria-selected": "false",
- tabIndex: -1
- });
- this.panels.not( this._getPanelForTab( this.active ) )
- .hide()
- .attr({
- "aria-expanded": "false",
- "aria-hidden": "true"
- });
-
- // Make sure one tab is in the tab order
- if ( !this.active.length ) {
- this.tabs.eq( 0 ).attr( "tabIndex", 0 );
- } else {
- this.active
- .addClass( "ui-tabs-active ui-state-active" )
- .attr({
- "aria-selected": "true",
- tabIndex: 0
- });
- this._getPanelForTab( this.active )
- .show()
- .attr({
- "aria-expanded": "true",
- "aria-hidden": "false"
- });
- }
- },
-
- _processTabs: function() {
- var that = this;
-
- this.tablist = this._getList()
- .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
- .attr( "role", "tablist" );
-
- this.tabs = this.tablist.find( "> li:has(a[href])" )
- .addClass( "ui-state-default ui-corner-top" )
- .attr({
- role: "tab",
- tabIndex: -1
- });
-
- this.anchors = this.tabs.map(function() {
- return $( "a", this )[ 0 ];
- })
- .addClass( "ui-tabs-anchor" )
- .attr({
- role: "presentation",
- tabIndex: -1
- });
-
- this.panels = $();
-
- this.anchors.each(function( i, anchor ) {
- var selector, panel, panelId,
- anchorId = $( anchor ).uniqueId().attr( "id" ),
- tab = $( anchor ).closest( "li" ),
- originalAriaControls = tab.attr( "aria-controls" );
-
- // inline tab
- if ( isLocal( anchor ) ) {
- selector = anchor.hash;
- panel = that.element.find( that._sanitizeSelector( selector ) );
- // remote tab
- } else {
- panelId = that._tabId( tab );
- selector = "#" + panelId;
- panel = that.element.find( selector );
- if ( !panel.length ) {
- panel = that._createPanel( panelId );
- panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
- }
- panel.attr( "aria-live", "polite" );
- }
-
- if ( panel.length) {
- that.panels = that.panels.add( panel );
- }
- if ( originalAriaControls ) {
- tab.data( "ui-tabs-aria-controls", originalAriaControls );
- }
- tab.attr({
- "aria-controls": selector.substring( 1 ),
- "aria-labelledby": anchorId
- });
- panel.attr( "aria-labelledby", anchorId );
- });
-
- this.panels
- .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
- .attr( "role", "tabpanel" );
- },
-
- // allow overriding how to find the list for rare usage scenarios (#7715)
- _getList: function() {
- return this.element.find( "ol,ul" ).eq( 0 );
- },
-
- _createPanel: function( id ) {
- return $( "<div>" )
- .attr( "id", id )
- .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
- .data( "ui-tabs-destroy", true );
- },
-
- _setupDisabled: function( disabled ) {
- if ( $.isArray( disabled ) ) {
- if ( !disabled.length ) {
- disabled = false;
- } else if ( disabled.length === this.anchors.length ) {
- disabled = true;
- }
- }
-
- // disable tabs
- for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
- if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
- $( li )
- .addClass( "ui-state-disabled" )
- .attr( "aria-disabled", "true" );
- } else {
- $( li )
- .removeClass( "ui-state-disabled" )
- .removeAttr( "aria-disabled" );
- }
- }
-
- this.options.disabled = disabled;
- },
-
- _setupEvents: function( event ) {
- var events = {
- click: function( event ) {
- event.preventDefault();
- }
- };
- if ( event ) {
- $.each( event.split(" "), function( index, eventName ) {
- events[ eventName ] = "_eventHandler";
- });
- }
-
- this._off( this.anchors.add( this.tabs ).add( this.panels ) );
- this._on( this.anchors, events );
- this._on( this.tabs, { keydown: "_tabKeydown" } );
- this._on( this.panels, { keydown: "_panelKeydown" } );
-
- this._focusable( this.tabs );
- this._hoverable( this.tabs );
- },
-
- _setupHeightStyle: function( heightStyle ) {
- var maxHeight,
- parent = this.element.parent();
-
- if ( heightStyle === "fill" ) {
- maxHeight = parent.height();
- maxHeight -= this.element.outerHeight() - this.element.height();
-
- this.element.siblings( ":visible" ).each(function() {
- var elem = $( this ),
- position = elem.css( "position" );
-
- if ( position === "absolute" || position === "fixed" ) {
- return;
- }
- maxHeight -= elem.outerHeight( true );
- });
-
- this.element.children().not( this.panels ).each(function() {
- maxHeight -= $( this ).outerHeight( true );
- });
-
- this.panels.each(function() {
- $( this ).height( Math.max( 0, maxHeight -
- $( this ).innerHeight() + $( this ).height() ) );
- })
- .css( "overflow", "auto" );
- } else if ( heightStyle === "auto" ) {
- maxHeight = 0;
- this.panels.each(function() {
- maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
- }).height( maxHeight );
- }
- },
-
- _eventHandler: function( event ) {
- var options = this.options,
- active = this.active,
- anchor = $( event.currentTarget ),
- tab = anchor.closest( "li" ),
- clickedIsActive = tab[ 0 ] === active[ 0 ],
- collapsing = clickedIsActive && options.collapsible,
- toShow = collapsing ? $() : this._getPanelForTab( tab ),
- toHide = !active.length ? $() : this._getPanelForTab( active ),
- eventData = {
- oldTab: active,
- oldPanel: toHide,
- newTab: collapsing ? $() : tab,
- newPanel: toShow
- };
-
- event.preventDefault();
-
- if ( tab.hasClass( "ui-state-disabled" ) ||
- // tab is already loading
- tab.hasClass( "ui-tabs-loading" ) ||
- // can't switch durning an animation
- this.running ||
- // click on active header, but not collapsible
- ( clickedIsActive && !options.collapsible ) ||
- // allow canceling activation
- ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
- return;
- }
-
- options.active = collapsing ? false : this.tabs.index( tab );
-
- this.active = clickedIsActive ? $() : tab;
- if ( this.xhr ) {
- this.xhr.abort();
- }
-
- if ( !toHide.length && !toShow.length ) {
- $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
- }
-
- if ( toShow.length ) {
- this.load( this.tabs.index( tab ), event );
- }
- this._toggle( event, eventData );
- },
-
- // handles show/hide for selecting tabs
- _toggle: function( event, eventData ) {
- var that = this,
- toShow = eventData.newPanel,
- toHide = eventData.oldPanel;
-
- this.running = true;
-
- function complete() {
- that.running = false;
- that._trigger( "activate", event, eventData );
- }
-
- function show() {
- eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
-
- if ( toShow.length && that.options.show ) {
- that._show( toShow, that.options.show, complete );
- } else {
- toShow.show();
- complete();
- }
- }
-
- // start out by hiding, then showing, then completing
- if ( toHide.length && this.options.hide ) {
- this._hide( toHide, this.options.hide, function() {
- eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
- show();
- });
- } else {
- eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
- toHide.hide();
- show();
- }
-
- toHide.attr({
- "aria-expanded": "false",
- "aria-hidden": "true"
- });
- eventData.oldTab.attr( "aria-selected", "false" );
- // If we're switching tabs, remove the old tab from the tab order.
- // If we're opening from collapsed state, remove the previous tab from the tab order.
- // If we're collapsing, then keep the collapsing tab in the tab order.
- if ( toShow.length && toHide.length ) {
- eventData.oldTab.attr( "tabIndex", -1 );
- } else if ( toShow.length ) {
- this.tabs.filter(function() {
- return $( this ).attr( "tabIndex" ) === 0;
- })
- .attr( "tabIndex", -1 );
- }
-
- toShow.attr({
- "aria-expanded": "true",
- "aria-hidden": "false"
- });
- eventData.newTab.attr({
- "aria-selected": "true",
- tabIndex: 0
- });
- },
-
- _activate: function( index ) {
- var anchor,
- active = this._findActive( index );
-
- // trying to activate the already active panel
- if ( active[ 0 ] === this.active[ 0 ] ) {
- return;
- }
-
- // trying to collapse, simulate a click on the current active header
- if ( !active.length ) {
- active = this.active;
- }
-
- anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
- this._eventHandler({
- target: anchor,
- currentTarget: anchor,
- preventDefault: $.noop
- });
- },
-
- _findActive: function( index ) {
- return index === false ? $() : this.tabs.eq( index );
- },
-
- _getIndex: function( index ) {
- // meta-function to give users option to provide a href string instead of a numerical index.
- if ( typeof index === "string" ) {
- index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
- }
-
- return index;
- },
-
- _destroy: function() {
- if ( this.xhr ) {
- this.xhr.abort();
- }
-
- this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
-
- this.tablist
- .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
- .removeAttr( "role" );
-
- this.anchors
- .removeClass( "ui-tabs-anchor" )
- .removeAttr( "role" )
- .removeAttr( "tabIndex" )
- .removeUniqueId();
-
- this.tabs.add( this.panels ).each(function() {
- if ( $.data( this, "ui-tabs-destroy" ) ) {
- $( this ).remove();
- } else {
- $( this )
- .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
- "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
- .removeAttr( "tabIndex" )
- .removeAttr( "aria-live" )
- .removeAttr( "aria-busy" )
- .removeAttr( "aria-selected" )
- .removeAttr( "aria-labelledby" )
- .removeAttr( "aria-hidden" )
- .removeAttr( "aria-expanded" )
- .removeAttr( "role" );
- }
- });
-
- this.tabs.each(function() {
- var li = $( this ),
- prev = li.data( "ui-tabs-aria-controls" );
- if ( prev ) {
- li
- .attr( "aria-controls", prev )
- .removeData( "ui-tabs-aria-controls" );
- } else {
- li.removeAttr( "aria-controls" );
- }
- });
-
- this.panels.show();
-
- if ( this.options.heightStyle !== "content" ) {
- this.panels.css( "height", "" );
- }
- },
-
- enable: function( index ) {
- var disabled = this.options.disabled;
- if ( disabled === false ) {
- return;
- }
-
- if ( index === undefined ) {
- disabled = false;
- } else {
- index = this._getIndex( index );
- if ( $.isArray( disabled ) ) {
- disabled = $.map( disabled, function( num ) {
- return num !== index ? num : null;
- });
- } else {
- disabled = $.map( this.tabs, function( li, num ) {
- return num !== index ? num : null;
- });
- }
- }
- this._setupDisabled( disabled );
- },
-
- disable: function( index ) {
- var disabled = this.options.disabled;
- if ( disabled === true ) {
- return;
- }
-
- if ( index === undefined ) {
- disabled = true;
- } else {
- index = this._getIndex( index );
- if ( $.inArray( index, disabled ) !== -1 ) {
- return;
- }
- if ( $.isArray( disabled ) ) {
- disabled = $.merge( [ index ], disabled ).sort();
- } else {
- disabled = [ index ];
- }
- }
- this._setupDisabled( disabled );
- },
-
- load: function( index, event ) {
- index = this._getIndex( index );
- var that = this,
- tab = this.tabs.eq( index ),
- anchor = tab.find( ".ui-tabs-anchor" ),
- panel = this._getPanelForTab( tab ),
- eventData = {
- tab: tab,
- panel: panel
- };
-
- // not remote
- if ( isLocal( anchor[ 0 ] ) ) {
- return;
- }
-
- this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
-
- // support: jQuery <1.8
- // jQuery <1.8 returns false if the request is canceled in beforeSend,
- // but as of 1.8, $.ajax() always returns a jqXHR object.
- if ( this.xhr && this.xhr.statusText !== "canceled" ) {
- tab.addClass( "ui-tabs-loading" );
- panel.attr( "aria-busy", "true" );
-
- this.xhr
- .success(function( response ) {
- // support: jQuery <1.8
- // http://bugs.jquery.com/ticket/11778
- setTimeout(function() {
- panel.html( response );
- that._trigger( "load", event, eventData );
- }, 1 );
- })
- .complete(function( jqXHR, status ) {
- // support: jQuery <1.8
- // http://bugs.jquery.com/ticket/11778
- setTimeout(function() {
- if ( status === "abort" ) {
- that.panels.stop( false, true );
- }
-
- tab.removeClass( "ui-tabs-loading" );
- panel.removeAttr( "aria-busy" );
-
- if ( jqXHR === that.xhr ) {
- delete that.xhr;
- }
- }, 1 );
- });
- }
- },
-
- _ajaxSettings: function( anchor, event, eventData ) {
- var that = this;
- return {
- url: anchor.attr( "href" ),
- beforeSend: function( jqXHR, settings ) {
- return that._trigger( "beforeLoad", event,
- $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
- }
- };
- },
-
- _getPanelForTab: function( tab ) {
- var id = $( tab ).attr( "aria-controls" );
- return this.element.find( this._sanitizeSelector( "#" + id ) );
- }
-});
-
-})( jQuery );
-(function( $ ) {
-
-var increments = 0;
-
-function addDescribedBy( elem, id ) {
- var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
- describedby.push( id );
- elem
- .data( "ui-tooltip-id", id )
- .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
-}
-
-function removeDescribedBy( elem ) {
- var id = elem.data( "ui-tooltip-id" ),
- describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
- index = $.inArray( id, describedby );
- if ( index !== -1 ) {
- describedby.splice( index, 1 );
- }
-
- elem.removeData( "ui-tooltip-id" );
- describedby = $.trim( describedby.join( " " ) );
- if ( describedby ) {
- elem.attr( "aria-describedby", describedby );
- } else {
- elem.removeAttr( "aria-describedby" );
- }
-}
-
-$.widget( "ui.tooltip", {
- version: "1.10.3",
- options: {
- content: function() {
- // support: IE<9, Opera in jQuery <1.7
- // .text() can't accept undefined, so coerce to a string
- var title = $( this ).attr( "title" ) || "";
- // Escape title, since we're going from an attribute to raw HTML
- return $( "<a>" ).text( title ).html();
- },
- hide: true,
- // Disabled elements have inconsistent behavior across browsers (#8661)
- items: "[title]:not([disabled])",
- position: {
- my: "left top+15",
- at: "left bottom",
- collision: "flipfit flip"
- },
- show: true,
- tooltipClass: null,
- track: false,
-
- // callbacks
- close: null,
- open: null
- },
-
- _create: function() {
- this._on({
- mouseover: "open",
- focusin: "open"
- });
-
- // IDs of generated tooltips, needed for destroy
- this.tooltips = {};
- // IDs of parent tooltips where we removed the title attribute
- this.parents = {};
-
- if ( this.options.disabled ) {
- this._disable();
- }
- },
-
- _setOption: function( key, value ) {
- var that = this;
-
- if ( key === "disabled" ) {
- this[ value ? "_disable" : "_enable" ]();
- this.options[ key ] = value;
- // disable element style changes
- return;
- }
-
- this._super( key, value );
-
- if ( key === "content" ) {
- $.each( this.tooltips, function( id, element ) {
- that._updateContent( element );
- });
- }
- },
-
- _disable: function() {
- var that = this;
-
- // close open tooltips
- $.each( this.tooltips, function( id, element ) {
- var event = $.Event( "blur" );
- event.target = event.currentTarget = element[0];
- that.close( event, true );
- });
-
- // remove title attributes to prevent native tooltips
- this.element.find( this.options.items ).addBack().each(function() {
- var element = $( this );
- if ( element.is( "[title]" ) ) {
- element
- .data( "ui-tooltip-title", element.attr( "title" ) )
- .attr( "title", "" );
- }
- });
- },
-
- _enable: function() {
- // restore title attributes
- this.element.find( this.options.items ).addBack().each(function() {
- var element = $( this );
- if ( element.data( "ui-tooltip-title" ) ) {
- element.attr( "title", element.data( "ui-tooltip-title" ) );
- }
- });
- },
-
- open: function( event ) {
- var that = this,
- target = $( event ? event.target : this.element )
- // we need closest here due to mouseover bubbling,
- // but always pointing at the same event target
- .closest( this.options.items );
-
- // No element to show a tooltip for or the tooltip is already open
- if ( !target.length || target.data( "ui-tooltip-id" ) ) {
- return;
- }
-
- if ( target.attr( "title" ) ) {
- target.data( "ui-tooltip-title", target.attr( "title" ) );
- }
-
- target.data( "ui-tooltip-open", true );
-
- // kill parent tooltips, custom or native, for hover
- if ( event && event.type === "mouseover" ) {
- target.parents().each(function() {
- var parent = $( this ),
- blurEvent;
- if ( parent.data( "ui-tooltip-open" ) ) {
- blurEvent = $.Event( "blur" );
- blurEvent.target = blurEvent.currentTarget = this;
- that.close( blurEvent, true );
- }
- if ( parent.attr( "title" ) ) {
- parent.uniqueId();
- that.parents[ this.id ] = {
- element: this,
- title: parent.attr( "title" )
- };
- parent.attr( "title", "" );
- }
- });
- }
-
- this._updateContent( target, event );
- },
-
- _updateContent: function( target, event ) {
- var content,
- contentOption = this.options.content,
- that = this,
- eventType = event ? event.type : null;
-
- if ( typeof contentOption === "string" ) {
- return this._open( event, target, contentOption );
- }
-
- content = contentOption.call( target[0], function( response ) {
- // ignore async response if tooltip was closed already
- if ( !target.data( "ui-tooltip-open" ) ) {
- return;
- }
- // IE may instantly serve a cached response for ajax requests
- // delay this call to _open so the other call to _open runs first
- that._delay(function() {
- // jQuery creates a special event for focusin when it doesn't
- // exist natively. To improve performance, the native event
- // object is reused and the type is changed. Therefore, we can't
- // rely on the type being correct after the event finished
- // bubbling, so we set it back to the previous value. (#8740)
- if ( event ) {
- event.type = eventType;
- }
- this._open( event, target, response );
- });
- });
- if ( content ) {
- this._open( event, target, content );
- }
- },
-
- _open: function( event, target, content ) {
- var tooltip, events, delayedShow,
- positionOption = $.extend( {}, this.options.position );
-
- if ( !content ) {
- return;
- }
-
- // Content can be updated multiple times. If the tooltip already
- // exists, then just update the content and bail.
- tooltip = this._find( target );
- if ( tooltip.length ) {
- tooltip.find( ".ui-tooltip-content" ).html( content );
- return;
- }
-
- // if we have a title, clear it to prevent the native tooltip
- // we have to check first to avoid defining a title if none exists
- // (we don't want to cause an element to start matching [title])
- //
- // We use removeAttr only for key events, to allow IE to export the correct
- // accessible attributes. For mouse events, set to empty string to avoid
- // native tooltip showing up (happens only when removing inside mouseover).
- if ( target.is( "[title]" ) ) {
- if ( event && event.type === "mouseover" ) {
- target.attr( "title", "" );
- } else {
- target.removeAttr( "title" );
- }
- }
-
- tooltip = this._tooltip( target );
- addDescribedBy( target, tooltip.attr( "id" ) );
- tooltip.find( ".ui-tooltip-content" ).html( content );
-
- function position( event ) {
- positionOption.of = event;
- if ( tooltip.is( ":hidden" ) ) {
- return;
- }
- tooltip.position( positionOption );
- }
- if ( this.options.track && event && /^mouse/.test( event.type ) ) {
- this._on( this.document, {
- mousemove: position
- });
- // trigger once to override element-relative positioning
- position( event );
- } else {
- tooltip.position( $.extend({
- of: target
- }, this.options.position ) );
- }
-
- tooltip.hide();
-
- this._show( tooltip, this.options.show );
- // Handle tracking tooltips that are shown with a delay (#8644). As soon
- // as the tooltip is visible, position the tooltip using the most recent
- // event.
- if ( this.options.show && this.options.show.delay ) {
- delayedShow = this.delayedShow = setInterval(function() {
- if ( tooltip.is( ":visible" ) ) {
- position( positionOption.of );
- clearInterval( delayedShow );
- }
- }, $.fx.interval );
- }
-
- this._trigger( "open", event, { tooltip: tooltip } );
-
- events = {
- keyup: function( event ) {
- if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
- var fakeEvent = $.Event(event);
- fakeEvent.currentTarget = target[0];
- this.close( fakeEvent, true );
- }
- },
- remove: function() {
- this._removeTooltip( tooltip );
- }
- };
- if ( !event || event.type === "mouseover" ) {
- events.mouseleave = "close";
- }
- if ( !event || event.type === "focusin" ) {
- events.focusout = "close";
- }
- this._on( true, target, events );
- },
-
- close: function( event ) {
- var that = this,
- target = $( event ? event.currentTarget : this.element ),
- tooltip = this._find( target );
-
- // disabling closes the tooltip, so we need to track when we're closing
- // to avoid an infinite loop in case the tooltip becomes disabled on close
- if ( this.closing ) {
- return;
- }
-
- // Clear the interval for delayed tracking tooltips
- clearInterval( this.delayedShow );
-
- // only set title if we had one before (see comment in _open())
- if ( target.data( "ui-tooltip-title" ) ) {
- target.attr( "title", target.data( "ui-tooltip-title" ) );
- }
-
- removeDescribedBy( target );
-
- tooltip.stop( true );
- this._hide( tooltip, this.options.hide, function() {
- that._removeTooltip( $( this ) );
- });
-
- target.removeData( "ui-tooltip-open" );
- this._off( target, "mouseleave focusout keyup" );
- // Remove 'remove' binding only on delegated targets
- if ( target[0] !== this.element[0] ) {
- this._off( target, "remove" );
- }
- this._off( this.document, "mousemove" );
-
- if ( event && event.type === "mouseleave" ) {
- $.each( this.parents, function( id, parent ) {
- $( parent.element ).attr( "title", parent.title );
- delete that.parents[ id ];
- });
- }
-
- this.closing = true;
- this._trigger( "close", event, { tooltip: tooltip } );
- this.closing = false;
- },
-
- _tooltip: function( element ) {
- var id = "ui-tooltip-" + increments++,
- tooltip = $( "<div>" )
- .attr({
- id: id,
- role: "tooltip"
- })
- .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
- ( this.options.tooltipClass || "" ) );
- $( "<div>" )
- .addClass( "ui-tooltip-content" )
- .appendTo( tooltip );
- tooltip.appendTo( this.document[0].body );
- this.tooltips[ id ] = element;
- return tooltip;
- },
-
- _find: function( target ) {
- var id = target.data( "ui-tooltip-id" );
- return id ? $( "#" + id ) : $();
- },
-
- _removeTooltip: function( tooltip ) {
- tooltip.remove();
- delete this.tooltips[ tooltip.attr( "id" ) ];
- },
-
- _destroy: function() {
- var that = this;
-
- // close open tooltips
- $.each( this.tooltips, function( id, element ) {
- // Delegate to close method to handle common cleanup
- var event = $.Event( "blur" );
- event.target = event.currentTarget = element[0];
- that.close( event, true );
-
- // Remove immediately; destroying an open tooltip doesn't use the
- // hide animation
- $( "#" + id ).remove();
-
- // Restore the title
- if ( element.data( "ui-tooltip-title" ) ) {
- element.attr( "title", element.data( "ui-tooltip-title" ) );
- element.removeData( "ui-tooltip-title" );
- }
- });
- }
-});
-
-}( jQuery ) );
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.min.js
deleted file mode 100755
index 8ececa0..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*! jQuery UI - v1.10.3 - 2013-05-11
-* http://jqueryui.com
-* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
-
-(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(
){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.ex
pr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(thi
s,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][
1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){
var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a
);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.o
wnerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=
0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=t
ypeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.el
ement[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName
+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.t
arget,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0)
,this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?
/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow?"":e.element.css("overflow-x"),s=e.isWindow?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]);return{element:i,isWindow:s,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)r
eturn f.apply(this,arguments);e=t.extend({},e);var a,p,m,g,v,b,_=t(e.of),y=t.position.getWithinInfo(e.within),w=t.position.getScrollInfo(y),x=(e.collision||"flip").split(" "),k={};return b=n(_),_[0].preventDefault&&(e.at="left top"),p=b.width,m=b.height,g=b.offset,v=t.extend({},g),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=l.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=l.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),k[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===x.length&&(x[1]=x[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=m:"center"===e.at[1]&&(v.top+=m/2),a=i(k.at,p,m),v.left+=a[0],v.top+=a[1],this.each(function(){var n,l,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),b=s(this,"marginTop"),D=u+f+s(this,"marginRight")+w.width,T=d+b+s(this,"marginBottom"
)+w.height,C=t.extend({},v),M=i(k.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?C.left-=u:"center"===e.my[0]&&(C.left-=u/2),"bottom"===e.my[1]?C.top-=d:"center"===e.my[1]&&(C.top-=d/2),C.left+=M[0],C.top+=M[1],t.support.offsetFractions||(C.left=h(C.left),C.top=h(C.top)),n={marginLeft:f,marginTop:b},t.each(["left","top"],function(i,s){t.ui.position[x[i]]&&t.ui.position[x[i]][s](C,{targetWidth:p,targetHeight:m,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:D,collisionHeight:T,offset:[a[0]+M[0],a[1]+M[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(l=function(t){var i=g.left-C.left,s=i+p-u,n=g.top-C.top,a=n+m-d,h={target:{element:_,left:g.left,top:g.top,width:p,height:m},element:{element:c,left:C.left,top:C.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(h.horizontal="center"),d>m&&m>r(n+a)&&(h.vertical="middle"),h.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.
call(this,t,h)}),c.offset(t.extend(C,{using:l}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-o-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemW
idth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-o-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-o-a,t.top+p+f+m>c&&(0>s||r(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,t.top+p+f+m>u&&(i>0||u>r(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,
arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(t){var e,i,s,n,a="ui-button ui-widget ui-state-default ui-corner-all",o="ui-state-hover ui-state-active ",r="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",h=function(){var e=t(this);setTimeout(function(){e.find(":ui-button").button("refresh")},1)},l=function(e){var i=e.name,s=e.form,n=t([]);return i&&(i=i.replace(/'/g,
"\\'"),n=s?t(s).find("[name='"+i+"']"):t("[name='"+i+"']",e.ownerDocument).filter(function(){return!this.form})),n};t.widget("ui.button",{version:"1.10.3",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,h),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var o=this,r=this.options,c="checkbox"===this.type||"radio"===this.type,u=c?"":"ui-state-active",d="ui-state-focus";null===r.label&&(r.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(a).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){r.disabled||this===e&&t(this).addCl
ass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){r.disabled||t(this).removeClass(u)}).bind("click"+this.eventNamespace,function(t){r.disabled&&(t.preventDefault(),t.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){o.buttonElement.addClass(d)}).bind("blur"+this.eventNamespace,function(){o.buttonElement.removeClass(d)}),c&&(this.element.bind("change"+this.eventNamespace,function(){n||o.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(t){r.disabled||(n=!1,i=t.pageX,s=t.pageY)}).bind("mouseup"+this.eventNamespace,function(t){r.disabled||(i!==t.pageX||s!==t.pageY)&&(n=!0)})),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return r.disabled||n?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(r.disabled||n)return!1;t(this).addClass("ui-state-active"),o.buttonElement.attr("aria-pressed","true");var e=o.el
ement[0];l(e).not(e).map(function(){return t(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return r.disabled?!1:(t(this).addClass("ui-state-active"),e=this,o.document.one("mouseup",function(){e=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return r.disabled?!1:(t(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(e){return r.disabled?!1:((e.keyCode===t.ui.keyCode.SPACE||e.keyCode===t.ui.keyCode.ENTER)&&t(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){t(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(e){e.keyCode===t.ui.keyCode.SPACE&&t(this).click()})),this._setOption("disabled",r.disabled),this._resetButton()},_determineButtonType:function(){var t,e,i;this.type=this.element.is("[
type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(t=this.element.parents().last(),e="label[for='"+this.element.attr("id")+"']",this.buttonElement=t.find(e),this.buttonElement.length||(t=t.length?t.siblings():this.element.siblings(),this.buttonElement=t.filter(e),this.buttonElement.length||(this.buttonElement=t.find(e))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(a+" "+o+" "+r).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(t,e){retu
rn this._super(t,e),"disabled"===t?(e?this.element.prop("disabled",!0):this.element.prop("disabled",!1),undefined):(this._resetButton(),undefined)},refresh:function(){var e=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");e!==this.options.disabled&&this._setOption("disabled",e),"radio"===this.type?l(this.element[0]).each(function(){t(this).is(":checked")?t(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):t(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var e=this.buttonElement.removeClass(r),i=t("<span></span>",this.document[0])
.addClass("ui-button-text").html(this.options.label).appendTo(e.empty()).text(),s=this.options.icons,n=s.primary&&s.secondary,a=[];s.primary||s.secondary?(this.options.text&&a.push("ui-button-text-icon"+(n?"s":s.primary?"-primary":"-secondary")),s.primary&&e.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&e.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(a.push(n?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||e.attr("title",t.trim(i)))):a.push("ui-button-text-only"),e.addClass(a.join(" "))}}),t.widget("ui.buttonset",{version:"1.10.3",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(t,e){"disabled"===t&&this.buttons.button("option",t,e),this._super(t,e)},refresh:f
unction(){var e="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(e?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(e?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(t,e){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",thi
s._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,goto
Current:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.dpDiv=s(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function s(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(i,"mouseout",function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datep
icker-next-hover")}).delegate(i,"mouseover",function(){t.datepicker._isDisabledDatepicker(a.inline?e.parent()[0]:a.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))})}function n(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}t.extend(t.ui,{datepicker:{version:"1.10.3"}});var a,r="datepicker";t.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return n(this._defaults,t||{}),this},_attachDatepicker:function(e,i){var s,n,a;s=e.nodeName.toLowerCase(),n="div"===s||"span"===s,e.id||(this.uuid+=1,e.id="dp"+this.uuid),a=this._newInst(t(e),n),a.settings=t.extend({},i||{}),"input"===s?this._connectDatepicker(e,a):n
&&this._inlineDatepicker(e,a)},_newInst:function(e,i){var n=e[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?s(t("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(e,i){var s=t(e);i.append=t([]),i.trigger=t([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),t.data(e,r,i),i.settings.disabled&&this._disableDatepicker(e))},_attachments:function(e,i){var s,n,a,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=t("<span class='"+this._appendClass+"'>"+r+"</span>"),e[o?"before":"after"](i.append)),e.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"=
==s||"both"===s)&&e.focus(this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),a=this._get(i,"buttonImage"),i.trigger=t(this._get(i,"buttonImageOnly")?t("<img/>").addClass(this._triggerClass).attr({src:a,alt:n,title:n}):t("<button type='button'></button>").addClass(this._triggerClass).html(a?t("<img/>").attr({src:a,alt:n,title:n}):n)),e[o?"before":"after"](i.trigger),i.trigger.click(function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,a=new Date(2009,11,20),r=this._get(t,"dateFormat");r.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},a.setMonth(e(this._get(t,r.match(/MM/)?"monthNames":"month
NamesShort"))),a.setDate(e(this._get(t,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),t.input.attr("size",this._formatDate(t,a).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,a,o){var h,l,c,u,d,p=this._dialogInst;return p||(this.uuid+=1,h="dp"+this.uuid,this._dialogInput=t("<input type='text' id='"+h+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),t("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},t.data(this._dialogInput[0],r,p)),n(p.settings,a||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o
.pageX,o.pageY]:null,this._pos||(l=document.documentElement.clientWidth,c=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[l/2-100+u,c/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,r);s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,r),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty())},_enableDate
picker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),t
his._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,s,a){var r,o,h,l,c=this._getInst(i);return 2===arguments.length&&"string"==typeof s?"defaults"===s?t.extend({},t.datepicker._defaults):c?"all"===s?t.extend({},c.settings):this._get(c,s):null:(r=s||{},"string"==typeof s&&(r={},r[s]=a),c&&(this._curInst===c&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),h=this._getMinMaxDate(c,"min"),l=this._getMinMaxDate(c,"max"),n(c.settings,r),null!==h&&r.dateFormat!==e&&r.minDate===e&&(c.settings.minDate=this._formatDate(c,h)),null!==l&&r.dateFormat!==e&&r.maxDate===e&&(c.settings.maxDate=this._formatDate(c,l)),"disabled"in r
&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(t(i),c),this._autoSize(c),this._setDate(c,o),this._updateAlternate(c),this._updateDatepicker(c)),e)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,a=t.datepicker._getInst(e.target),r=!0,o=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),r=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",a.dpDiv),n[0]&&t.datepicker._selectDay(e.target,a.selectedMonth,a.selectedY
ear,n[0]),i=t.datepicker._get(a,"onSelect"),i?(s=t.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),r=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),r=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?1:-1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),r=e.
ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?-1:1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),r=e.ctrlKey||e.metaKey;break;default:r=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):r=!1;r&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(i){var s,n,a=t.datepicker._getInst(i.target);return t.datepicker._get(a,"constrainInput")?(s=t.datepicker._possibleChars(t.datepicker._get(a,"dateFormat")),n=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">n||!s||s.indexOf(n)>-1):e},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepic
ker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var i,s,a,r,o,h,l;i=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==i&&(t.datepicker._curInst.dpDiv.stop(!0,!0),i&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),s=t.datepicker._get(i,"beforeShow"),a=s?s.apply(e,[e,i]):{},a!==!1&&(n(i.settings,a),i.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(i),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),r=!1,t(e).parents().each(function(){return r|="fixed"===t(this).css("position"),!r}),o={left:t.datepicker._pos[0],top:t.datep
icker._pos[1]},t.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(i),o=t.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(h=t.datepicker._get(i,"showAnim"),l=t.datepicker._get(i,"duration"),i.dpDiv.zIndex(t(e).zIndex()+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[h]?i.dpDiv.show(h,t.datepicker._get(i,"showOptions"),l):i.dpDiv[h||"show"](h?l:null),t.datepicker._shouldFocusInput(i)&&i.input.focus(),t.datepicker._curInst=i))}},_updateDatepicker:function(e){this.maxRows=4,a=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,s=this._getNumberOfMonths(e),n=s[1],r=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dp
Div.addClass("ui-datepicker-multi-"+n).css("width",r*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.focus(),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),a=e.dpDiv.outerHeight(),r=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-r:0,i.left-=s&&i.left===e.input.offset().le
ft?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+o?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+o):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,a,o=this._curInst;!o||e&&o!==t.data(e,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){t.datepicker._tidyDialog(o)},t.effects&&(t.effects.effect[i]||t.effects[i])?o.dpDiv.hide(i,t.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogI
nput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.
selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(e,i,s,n){var a,r=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(a=this._getInst(r[0]),a.selectedDay=a.currentDay=t("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(e,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.inp
ut&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,a=this._get(e,"altField");a&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(a).each(function(){t(this).val(n)}))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(i,s,n){if(null==i||null==s)throw"Invalid arguments";if(s="object"==typeof s?""+s:s+"",""===s)return null;var a,r,o,h,l=0,c=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=t
ypeof c?c:(new Date).getFullYear()%100+parseInt(c,10),d=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,p=(n?n.dayNames:null)||this._defaults.dayNames,f=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,m=(n?n.monthNames:null)||this._defaults.monthNames,g=-1,v=-1,_=-1,b=-1,y=!1,x=function(t){var e=i.length>a+1&&i.charAt(a+1)===t;return e&&a++,e},k=function(t){var e=x(t),i="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n=RegExp("^\\d{1,"+i+"}"),a=s.substring(l).match(n);if(!a)throw"Missing number at position "+l;return l+=a[0].length,parseInt(a[0],10)},w=function(i,n,a){var r=-1,o=t.map(x(i)?a:n,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(o,function(t,i){var n=i[1];return s.substr(l,n.length).toLowerCase()===n.toLowerCase()?(r=i[0],l+=n.length,!1):e}),-1!==r)return r+1;throw"Unknown name at position "+l},D=function(){if(s.charAt(l)!==i.charAt(a))throw"Unexpected literal at position "+l;l++};for(a=0;i.length>a;a
++)if(y)"'"!==i.charAt(a)||x("'")?D():y=!1;else switch(i.charAt(a)){case"d":_=k("d");break;case"D":w("D",d,p);break;case"o":b=k("o");break;case"m":v=k("m");break;case"M":v=w("M",f,m);break;case"y":g=k("y");break;case"@":h=new Date(k("@")),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"!":h=new Date((k("!")-this._ticksTo1970)/1e4),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"'":x("'")?D():y=!0;break;default:D()}if(s.length>l&&(o=s.substr(l),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===g?g=(new Date).getFullYear():100>g&&(g+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=g?0:-100)),b>-1)for(v=1,_=b;;){if(r=this._getDaysInMonth(g,v-1),r>=_)break;v++,_-=r}if(h=this._daylightSavingAdjust(new Date(g,v-1,_)),h.getFullYear()!==g||h.getMonth()+1!==v||h.getDate()!==_)throw"Invalid date";return h},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1
123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,a);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMo
nth()+1,2);break;case"M":u+=c("M",e.getMonth(),r,o);break;case"y":u+=h("y")?e.getFullYear():(10>e.getYear()%100?"0":"")+e.getYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,i){return t.settings[i]!==e?t.settings[i]:this._defaults[i]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),a=n,r=this._getFormatConfig(t);try{a=this.parseDate(i,s,r)||n}catch(o){s=e?"":s}t.selectedDay=a.getDate(),
t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),t.currentDay=s?a.getDate():0,t.currentMonth=s?a.getMonth():0,t.currentYear=s?a.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},a=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,a=n.getFullYear(),r=n.getMonth(),o=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":o+=parseInt(l[1],10);break;case"w":case"W":o+=7*parseInt(l[1],10);break;case"m":case"M":r+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r));break;case"y":case"Y":a+=parseInt(l[1],10),o=Math.min(o,t.datepi
cker._getDaysInMonth(a,r))}l=h.exec(i)}return new Date(a,r,o)},r=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?s:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,a=t.selectedYear,r=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=r.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=r.getMonth(),t.drawYear=t.selectedYear=t.currentYear=r.getFullYear(),n===t.selectedMonth&&a===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_at
tachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,a,r,o,h,l,c,u,d,p,f,m,g,v,_,b,y,x,k,w,D,T,C,M,S,N,I,P,A,z,H,E,F,O,W,j,R=new Date,L=this._daylightSavingAdjust(new Date(R.getFullYear(),R.getMonth(),R.getDate())),Y=this._get(t,"isRTL"),B=this._get(t,"showButtonPanel"),J=this._get(t,"hideIfNoPre
vNext"),K=this._get(t,"navigationAsDateFormat"),Q=this._getNumberOfMonths(t),V=this._get(t,"showCurrentAtPos"),U=this._get(t,"stepMonths"),q=1!==Q[0]||1!==Q[1],X=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(t,"min"),$=this._getMinMaxDate(t,"max"),Z=t.drawMonth-V,te=t.drawYear;if(0>Z&&(Z+=12,te--),$)for(e=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-Q[0]*Q[1]+1,$.getDate())),e=G&&G>e?G:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-U,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":J?"":"<a class='ui-datepicker-prev ui-corner-all ui-st
ate-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+U,1)),this._getFormatConfig(t)):n,a=this._canAdjustMonth(t,1,te,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":J?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",r=this._get(t,"currentText"),o=this._get(t,"gotoCurrent")&&t.currentDay?X:L,r=K?this.formatDate(r,o,this._getFormatConfig(t)):r,h=t.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(t,"closeText")+"</button>",l=B?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+
(Y?h:"")+(this._isInRange(t,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(Y?"":h)+"</div>":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),m=this._get(t,"monthNamesShort"),g=this._get(t,"beforeShowDay"),v=this._get(t,"showOtherMonths"),_=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",k=0;Q[0]>k;k++){for(w="",this.maxRows=4,D=0;Q[1]>D;D++){if(T=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),C=" ui-corner-all",M="",q){if(M+="<div class='ui-datepicker-group",Q[1]>1)switch(D){case 0:M+=" ui-datepicker-group-first",C=" ui-corner-"+(Y?"right":"left");break;case Q[1]-1:M+=" ui-datepicker-group-last",C=" ui-corner-"+(Y?"left":"right");break;default:M+=" ui-datepicker-group-middle",C=""}M+="'>"}for(M+="<div class='ui-da
tepicker-header ui-widget-header ui-helper-clearfix"+C+"'>"+(/all|left/.test(C)&&0===k?Y?a:s:"")+(/all|right/.test(C)&&0===k?Y?s:a:"")+this._generateMonthYearHeader(t,Z,te,G,$,k>0||D>0,f,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",S=u?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",x=0;7>x;x++)N=(x+c)%7,S+="<th"+((x+c+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[N]+"'>"+p[N]+"</span></th>";for(M+=S+"</tr></thead><tbody>",I=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,I)),P=(this._getFirstDayOfMonth(te,Z)-c+7)%7,A=Math.ceil((P+I)/7),z=q?this.maxRows>A?this.maxRows:A:A,this.maxRows=z,H=this._daylightSavingAdjust(new Date(te,Z,1-P)),E=0;z>E;E++){for(M+="<tr>",F=u?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(H)+"</td>":"",x=0;7>x;x++)O=g?g.apply(t.input?t.input[0]:null,[H]):[!0,""],W=H.getMonth()!==Z,j=W&&!_||!O[0]||G&&G>H||$&&
H>$,F+="<td class='"+((x+c+6)%7>=5?" ui-datepicker-week-end":"")+(W?" ui-datepicker-other-month":"")+(H.getTime()===T.getTime()&&Z===t.selectedMonth&&t._keyEvent||b.getTime()===H.getTime()&&b.getTime()===T.getTime()?" "+this._dayOverClass:"")+(j?" "+this._unselectableClass+" ui-state-disabled":"")+(W&&!v?"":" "+O[1]+(H.getTime()===X.getTime()?" "+this._currentClass:"")+(H.getTime()===L.getTime()?" ui-datepicker-today":""))+"'"+(W&&!v||!O[2]?"":" title='"+O[2].replace(/'/g,"'")+"'")+(j?"":" data-handler='selectDay' data-event='click' data-month='"+H.getMonth()+"' data-year='"+H.getFullYear()+"'")+">"+(W&&!v?" ":j?"<span class='ui-state-default'>"+H.getDate()+"</span>":"<a class='ui-state-default"+(H.getTime()===L.getTime()?" ui-state-highlight":"")+(H.getTime()===X.getTime()?" ui-state-active":"")+(W?" ui-priority-secondary":"")+"' href='#'>"+H.getDate()+"</a>")+"</td>",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);M+=F+"</tr>"}Z++,Z>11&&(Z=0,te++),M+="</t
body></table>"+(q?"</div>"+(Q[0]>0&&D===Q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=M}y+=w}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,a,r,o){var h,l,c,u,d,p,f,m,g=this._get(t,"changeMonth"),v=this._get(t,"changeYear"),_=this._get(t,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",y="";if(a||!g)y+="<span class='ui-datepicker-month'>"+r[e]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",c=0;12>c;c++)(!h||c>=s.getMonth())&&(!l||n.getMonth()>=c)&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+o[c]+"</option>");y+="</select>"}if(_||(b+=y+(!a&&g&&v?"":" ")),!t.yearshtml)if(t.yearshtml="",a||!v)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.m
atch(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10);
-return isNaN(e)?d:e},f=p(u[0]),m=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,t.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=f;f++)t.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),_&&(b+=(!a&&g&&v?"":" ")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.drawYear+("Y"===i?e:0),n=t.drawMonth+("M"===i?e:0),a=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),r=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,a)));t.selectedDay=r.getDate(),t.drawMonth=t.selectedMonth=r.getMonth(),t.drawYear=t.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(
t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),a=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(t,a)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),a=this._getMinMaxDate(t,"max"),r=null,o=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=s),i[1].match(/[+\-].*/)
&&(o+=s)),(!n||e.getTime()>=n.getTime())&&(!a||e.getTime()<=a.getTime())&&(!r||e.getFullYear()>=r)&&(!o||o>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).mousedown(t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepic
ker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new i,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.10.3"})(jQuery);(function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._anima
teOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)o.push(a);this.handles=n.add(t(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?
e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):this.range=t([])},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,o,r,h,l,u=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHe
ight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-u.values(e));(n>i||n===i&&(e===u._lastChangedValue||u.values(e)===c.min))&&(n=i,a=t(this),o=e)}),r=this._start(e,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),h=a.offset(),l=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:e.pageX-h.left-a.width()/2,top:e.pageY-h.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeCla
ss("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,a;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,a;this.options.values&&this
.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,a=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),a!==!1&&this.values(e,i,!0))):i!==this.value()&&(a=this._trigger("slide",t,{handle:this.handles[e],value:i}),a!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0)
,undefined):this._value()},values:function(e,i){var s,n,a;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.o
rientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e
:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,a,o=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),u["horizontal"===h.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[l?"animate":"css"](u,r.animate),h.options.range===!0&&("horizontal"===h.orientation?(0===s&&h.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+
"%",this.handle.stop(1,1)[l?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[l?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[l?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,a,o,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(o=this.options.step,n=a=
this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:a=this._valueMin();break;case t.ui.keyCode.END:a=this._valueMax();break;case t.ui.keyCode.PAGE_UP:a=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:a=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;a=this._trimAlignValue(n+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;a=this._trimAlignValue(n-o)}this._slide(i,r,a)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})})(jQuery);(function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._tr
igger("change")}}t.widget("ui.spinner",{version:"1.10.3",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void
0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._s
tart(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(
){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>▲</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>▼</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.m
in&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(t
his.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-val
uemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.3",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activa
te:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.eac
h(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;defau
lt:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDi
sabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event)
,this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr
("id"),l=t(n).closest("li"),u=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),u&&l.data("ui-tabs-aria-controls",u),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").remov
eAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i)
)},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),u={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,u))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab
.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner
-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.o
ptions.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return
{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.3",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this.
_on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip
-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,a=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=a),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function a(t){l.of=t,o.is(":hidden")||o.position(l)}var o,r,h,l=t.extend({},this.options.position);if(n){if(o=this._find(s),o.length)return o.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),o=this._tooltip(s),e(s,o.attr("id")),o.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._
on(this.document,{mousemove:a}),a(i)):o.position(t.extend({of:s},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){o.is(":visible")&&(a(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:o}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(o)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),a=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),a.stop(!0),this._hide(a,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),th
is._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:a}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.1.1.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.1.1.min.js
deleted file mode 100644
index 02c6970..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.1.1.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/* jquery.sparkline 2.1 - http://omnipotent.net/jquery.sparkline/
-** Licensed under the New BSD License - see above site for details */
-
-(function(a){typeof define=="function"&&define.amd?define(["jquery"],a):a(jQuery)})(function(a){"use strict";var b={},c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I=0;c=function(){return{common:{type:"line",lineColor:"#00f",fillColor:"#cdf",defaultPixelsPerValue:3,width:"auto",height:"auto",composite:!1,tagValuesAttribute:"values",tagOptionsPrefix:"spark",enableTagOptions:!1,enableHighlight:!0,highlightLighten:1.4,tooltipSkipNull:!0,tooltipPrefix:"",tooltipSuffix:"",disableHiddenCheck:!1,numberFormatter:!1,numberDigitGroupCount:3,numberDigitGroupSep:",",numberDecimalMark:".",disableTooltips:!1,disableInteraction:!1},line:{spotColor:"#f80",highlightSpotColor:"#5f5",highlightLineColor:"#f22",spotRadius:1.5,minSpotColor:"#f80",maxSpotColor:"#f80",lineWidth:1,normalRangeMin:undefined,normalRangeMax:undefined,normalRangeColor:"#ccc",drawNormalOnTop:!1,chartRangeMin:undefined,chartRangeMax:undefined,chartRangeMinX:undefined,chartRangeMaxX:undefined,tooltipFormat
:new e('<span style="color: {{color}}">●</span> {{prefix}}{{y}}{{suffix}}')},bar:{barColor:"#3366cc",negBarColor:"#f44",stackedBarColor:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],zeroColor:undefined,nullColor:undefined,zeroAxis:!0,barWidth:4,barSpacing:1,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,colorMap:undefined,tooltipFormat:new e('<span style="color: {{color}}">●</span> {{prefix}}{{value}}{{suffix}}')},tristate:{barWidth:4,barSpacing:1,posBarColor:"#6f6",negBarColor:"#f44",zeroBarColor:"#999",colorMap:{},tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value:map}}'),tooltipValueLookups:{map:{"-1":"Loss",0:"Draw",1:"Win"}}},discrete:{lineHeight:"auto",thresholdColor:undefined,thresholdValue:0,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,tooltipFormat:new e("{{prefix}}{{value}}{{suffix}}")},bullet:{targetColor:"#f33",targetWidth:3,performanceColor:"#33f",rang
eColors:["#d3dafe","#a8b6ff","#7f94ff"],base:undefined,tooltipFormat:new e("{{fieldkey:fields}} - {{value}}"),tooltipValueLookups:{fields:{r:"Range",p:"Performance",t:"Target"}}},pie:{offset:0,sliceColors:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],borderWidth:0,borderColor:"#000",tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value}} ({{percent.1}}%)')},box:{raw:!1,boxLineColor:"#000",boxFillColor:"#cdf",whiskerColor:"#000",outlierLineColor:"#333",outlierFillColor:"#fff",medianColor:"#f00",showOutliers:!0,outlierIQR:1.5,spotRadius:1.5,target:undefined,targetColor:"#4a2",chartRangeMax:undefined,chartRangeMin:undefined,tooltipFormat:new e("{{field:fields}}: {{value}}"),tooltipFormatFieldlistKey:"field",tooltipValueLookups:{fields:{lq:"Lower Quartile",med:"Median",uq:"Upper Quartile",lo:"Left Outlier",ro:"Right Outlier",lw:"Left Whisker",rw:"Right Whisker"}}}}},B='.jqstooltip { position: absolute;left: 0px;top: 0px;vi
sibility: hidden;background: rgb(0, 0, 0) transparent;background-color: rgba(0,0,0,0.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";color: white;font: 10px arial, san serif;text-align: left;white-space: nowrap;padding: 5px;border: 1px solid white;z-index: 10000;}.jqsfield { color: white;font: 10px arial, san serif;text-align: left;}',d=function(){var b,c;return b=function(){this.init.apply(this,arguments)},arguments.length>1?(arguments[0]?(b.prototype=a.extend(new arguments[0],arguments[arguments.length-1]),b._super=arguments[0].prototype):b.prototype=arguments[arguments.length-1],arguments.length>2&&(c=Array.prototype.slice.call(arguments,1,-1),c.unshift(b.prototype),a.extend.apply(a,c))):b.prototype=arguments[0],b.prototype.cls=b,b},a.SPFormatClass=e=d({fre:/\{\{([\w.]+?)(:(.+?))?\}\}/g,precre:/(\w+)\.(\d+)/,init:fun
ction(a,b){this.format=a,this.fclass=b},render:function(a,b,c){var d=this,e=a,f,g,h,i,j;return this.format.replace(this.fre,function(){var a;return g=arguments[1],h=arguments[3],f=d.precre.exec(g),f?(j=f[2],g=f[1]):j=!1,i=e[g],i===undefined?"":h&&b&&b[h]?(a=b[h],a.get?b[h].get(i)||i:b[h][i]||i):(k(i)&&(c.get("numberFormatter")?i=c.get("numberFormatter")(i):i=p(i,j,c.get("numberDigitGroupCount"),c.get("numberDigitGroupSep"),c.get("numberDecimalMark"))),i)})}}),a.spformat=function(a,b){return new e(a,b)},f=function(a,b,c){return a<b?b:a>c?c:a},g=function(a,b){var c;return b===2?(c=Math.floor(a.length/2),a.length%2?a[c]:(a[c-1]+a[c])/2):a.length%2?(c=(a.length*b+b)/4,c%1?(a[Math.floor(c)]+a[Math.floor(c)-1])/2:a[c-1]):(c=(a.length*b+2)/4,c%1?(a[Math.floor(c)]+a[Math.floor(c)-1])/2:a[c-1])},h=function(a){var b;switch(a){case"undefined":a=undefined;break;case"null":a=null;break;case"true":a=!0;break;case"false":a=!1;break;default:b=parseFloat(a),a==b&&(a=b)}return a},i=function(a
){var b,c=[];for(b=a.length;b--;)c[b]=h(a[b]);return c},j=function(a,b){var c,d,e=[];for(c=0,d=a.length;c<d;c++)a[c]!==b&&e.push(a[c]);return e},k=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},p=function(b,c,d,e,f){var g,h;b=(c===!1?parseFloat(b).toString():b.toFixed(c)).split(""),g=(g=a.inArray(".",b))<0?b.length:g,g<b.length&&(b[g]=f);for(h=g-d;h>0;h-=d)b.splice(h,0,e);return b.join("")},l=function(a,b,c){var d;for(d=b.length;d--;){if(c&&b[d]===null)continue;if(b[d]!==a)return!1}return!0},m=function(a){var b=0,c;for(c=a.length;c--;)b+=typeof a[c]=="number"?a[c]:0;return b},o=function(b){return a.isArray(b)?b:[b]},n=function(a){var b;document.createStyleSheet?document.createStyleSheet().cssText=a:(b=document.createElement("style"),b.type="text/css",document.getElementsByTagName("head")[0].appendChild(b),b[typeof document.body.style.WebkitAppearance=="string"?"innerText":"innerHTML"]=a)},a.fn.simpledraw=function(b,c,d,e){var f,g;if(d&&(f=this.data("_jqs_vcanvas")))re
turn f;b===undefined&&(b=a(this).innerWidth()),c===undefined&&(c=a(this).innerHeight());if(a.browser.hasCanvas)f=new F(b,c,this,e);else{if(!a.browser.msie)return!1;f=new G(b,c,this)}return g=a(this).data("_jqs_mhandler"),g&&g.registerCanvas(f),f},a.fn.cleardraw=function(){var a=this.data("_jqs_vcanvas");a&&a.reset()},a.RangeMapClass=q=d({init:function(a){var b,c,d=[];for(b in a)a.hasOwnProperty(b)&&typeof b=="string"&&b.indexOf(":")>-1&&(c=b.split(":"),c[0]=c[0].length===0?-Infinity:parseFloat(c[0]),c[1]=c[1].length===0?Infinity:parseFloat(c[1]),c[2]=a[b],d.push(c));this.map=a,this.rangelist=d||!1},get:function(a){var b=this.rangelist,c,d,e;if((e=this.map[a])!==undefined)return e;if(b)for(c=b.length;c--;){d=b[c];if(d[0]<=a&&d[1]>=a)return d[2]}return undefined}}),a.range_map=function(a){return new q(a)},r=d({init:function(b,c){var d=a(b);this.$el=d,this.options=c,this.currentPageX=0,this.currentPageY=0,this.el=b,this.splist=[],this.tooltip=null,this.over=!1,this.displayToolt
ips=!c.get("disableTooltips"),this.highlightEnabled=!c.get("disableHighlight")},registerSparkline:function(a){this.splist.push(a),this.over&&this.updateDisplay()},registerCanvas:function(b){var c=a(b.canvas);this.canvas=b,this.$canvas=c,c.mouseenter(a.proxy(this.mouseenter,this)),c.mouseleave(a.proxy(this.mouseleave,this)),c.click(a.proxy(this.mouseclick,this))},reset:function(a){this.splist=[],this.tooltip&&a&&(this.tooltip.remove(),this.tooltip=undefined)},mouseclick:function(b){var c=a.Event("sparklineClick");c.originalEvent=b,c.sparklines=this.splist,this.$el.trigger(c)},mouseenter:function(b){a(document.body).unbind("mousemove.jqs"),a(document.body).bind("mousemove.jqs",a.proxy(this.mousemove,this)),this.over=!0,this.currentPageX=b.pageX,this.currentPageY=b.pageY,this.currentEl=b.target,!this.tooltip&&this.displayTooltips&&(this.tooltip=new s(this.options),this.tooltip.updatePosition(b.pageX,b.pageY)),this.updateDisplay()},mouseleave:function(){a(document.body).unbind("
mousemove.jqs");var b=this.splist,c=b.length,d=!1,e,f;this.over=!1,this.currentEl=null,this.tooltip&&(this.tooltip.remove(),this.tooltip=null);for(f=0;f<c;f++)e=b[f],e.clearRegionHighlight()&&(d=!0);d&&this.canvas.render()},mousemove:function(a){this.currentPageX=a.pageX,this.currentPageY=a.pageY,this.currentEl=a.target,this.tooltip&&this.tooltip.updatePosition(a.pageX,a.pageY),this.updateDisplay()},updateDisplay:function(){var b=this.splist,c=b.length,d=!1,e=this.$canvas.offset(),f=this.currentPageX-e.left,g=this.currentPageY-e.top,h,i,j,k,l;if(!this.over)return;for(j=0;j<c;j++)i=b[j],k=i.setRegionHighlight(this.currentEl,f,g),k&&(d=!0);if(d){l=a.Event("sparklineRegionChange"),l.sparklines=this.splist,this.$el.trigger(l);if(this.tooltip){h="";for(j=0;j<c;j++)i=b[j],h+=i.getCurrentRegionTooltip();this.tooltip.setContent(h)}this.disableHighlight||this.canvas.render()}k===null&&this.mouseleave()}}),s=d({sizeStyle:"position: static !important;display: block !important;visibilit
y: hidden !important;float: left !important;",init:function(b){var c=b.get("tooltipClassname","jqstooltip"),d=this.sizeStyle,e;this.container=b.get("tooltipContainer")||document.body,this.tooltipOffsetX=b.get("tooltipOffsetX",10),this.tooltipOffsetY=b.get("tooltipOffsetY",12),a("#jqssizetip").remove(),a("#jqstooltip").remove(),this.sizetip=a("<div/>",{id:"jqssizetip",style:d,"class":c}),this.tooltip=a("<div/>",{id:"jqstooltip","class":c}).appendTo(this.container),e=this.tooltip.offset(),this.offsetLeft=e.left,this.offsetTop=e.top,this.hidden=!0,a(window).unbind("resize.jqs scroll.jqs"),a(window).bind("resize.jqs scroll.jqs",a.proxy(this.updateWindowDims,this)),this.updateWindowDims()},updateWindowDims:function(){this.scrollTop=a(window).scrollTop(),this.scrollLeft=a(window).scrollLeft(),this.scrollRight=this.scrollLeft+a(window).width(),this.updatePosition()},getSize:function(a){this.sizetip.html(a).appendTo(this.container),this.width=this.sizetip.width()+1,this.height=this.
sizetip.height(),this.sizetip.remove()},setContent:function(a){if(!a){this.tooltip.css("visibility","hidden"),this.hidden=!0;return}this.getSize(a),this.tooltip.html(a).css({width:this.width,height:this.height,visibility:"visible"}),this.hidden&&(this.hidden=!1,this.updatePosition())},updatePosition:function(a,b){if(a===undefined){if(this.mousex===undefined)return;a=this.mousex-this.offsetLeft,b=this.mousey-this.offsetTop}else this.mousex=a-=this.offsetLeft,this.mousey=b-=this.offsetTop;if(!this.height||!this.width||this.hidden)return;b-=this.height+this.tooltipOffsetY,a+=this.tooltipOffsetX,b<this.scrollTop&&(b=this.scrollTop),a<this.scrollLeft?a=this.scrollLeft:a+this.width>this.scrollRight&&(a=this.scrollRight-this.width),this.tooltip.css({left:a,top:b})},remove:function(){this.tooltip.remove(),this.sizetip.remove(),this.sizetip=this.tooltip=undefined,a(window).unbind("resize.jqs scroll.jqs")}}),C=function(){n(B)},a(C),H=[],a.fn.sparkline=function(b,c){return this.each(fu
nction(){var d=new a.fn.sparkline.options(this,c),e=a(this),f,g;f=function(){var c,f,g,h,i,j,k;if(b==="html"||b===undefined){k=this.getAttribute(d.get("tagValuesAttribute"));if(k===undefined||k===null)k=e.html();c=k.replace(/(^\s*<!--)|(-->\s*$)|\s+/g,"").split(",")}else c=b;f=d.get("width")==="auto"?c.length*d.get("defaultPixelsPerValue"):d.get("width");if(d.get("height")==="auto"){if(!d.get("composite")||!a.data(this,"_jqs_vcanvas"))h=document.createElement("span"),h.innerHTML="a",e.html(h),g=a(h).innerHeight()||a(h).height(),a(h).remove(),h=null}else g=d.get("height");d.get("disableInteraction")?i=!1:(i=a.data(this,"_jqs_mhandler"),i?d.get("composite")||i.reset():(i=new r(this,d),a.data(this,"_jqs_mhandler",i)));if(d.get("composite")&&!a.data(this,"_jqs_vcanvas")){a.data(this,"_jqs_errnotify")||(alert("Attempted to attach a composite sparkline to an element with no existing sparkline"),a.data(this,"_jqs_errnotify",!0));return}j=new(a.fn.sparkline[d.get("type")])(this,c,d,
f,g),j.render(),i&&i.registerSparkline(j)};if(a(this).html()&&!d.get("disableHiddenCheck")&&a(this).is(":hidden")||a.fn.jquery<"1.3.0"&&a(this).parents().is(":hidden")||!a(this).parents("body").length){if(!d.get("composite")&&a.data(this,"_jqs_pending"))for(g=H.length;g;g--)H[g-1][0]==this&&H.splice(g-1,1);H.push([this,f]),a.data(this,"_jqs_pending",!0)}else f.call(this)})},a.fn.sparkline.defaults=c(),a.sparkline_display_visible=function(){var b,c,d,e=[];for(c=0,d=H.length;c<d;c++)b=H[c][0],a(b).is(":visible")&&!a(b).parents().is(":hidden")?(H[c][1].call(b),a.data(H[c][0],"_jqs_pending",!1),e.push(c)):!a(b).closest("html").length&&!a.data(b,"_jqs_pending")&&(a.data(H[c][0],"_jqs_pending",!1),e.push(c));for(c=e.length;c;c--)H.splice(e[c-1],1)},a.fn.sparkline.options=d({init:function(c,d){var e,f,g,h;this.userOptions=d=d||{},this.tag=c,this.tagValCache={},f=a.fn.sparkline.defaults,g=f.common,this.tagOptionsPrefix=d.enableTagOptions&&(d.tagOptionsPrefix||g.tagOptionsPrefix),h=t
his.getTagSetting("type"),h===b?e=f[d.type||g.type]:e=f[h],this.mergedOptions=a.extend({},g,e,d)},getTagSetting:function(a){var c=this.tagOptionsPrefix,d,e,f,g;if(c===!1||c===undefined)return b;if(this.tagValCache.hasOwnProperty(a))d=this.tagValCache.key;else{d=this.tag.getAttribute(c+a);if(d===undefined||d===null)d=b;else if(d.substr(0,1)==="["){d=d.substr(1,d.length-2).split(",");for(e=d.length;e--;)d[e]=h(d[e].replace(/(^\s*)|(\s*$)/g,""))}else if(d.substr(0,1)==="{"){f=d.substr(1,d.length-2).split(","),d={};for(e=f.length;e--;)g=f[e].split(":",2),d[g[0].replace(/(^\s*)|(\s*$)/g,"")]=h(g[1].replace(/(^\s*)|(\s*$)/g,""))}else d=h(d);this.tagValCache.key=d}return d},get:function(a,c){var d=this.getTagSetting(a),e;return d!==b?d:(e=this.mergedOptions[a])===undefined?c:e}}),a.fn.sparkline._base=d({disabled:!1,init:function(b,c,d,e,f){this.el=b,this.$el=a(b),this.values=c,this.options=d,this.width=e,this.height=f,this.currentRegion=undefined},initTarget:function(){var a=!this.
options.get("disableInteraction");(this.target=this.$el.simpledraw(this.width,this.height,this.options.get("composite"),a))?(this.canvasWidth=this.target.pixelWidth,this.canvasHeight=this.target.pixelHeight):this.disabled=!0},render:function(){return this.disabled?(this.el.innerHTML="",!1):!0},getRegion:function(a,b){},setRegionHighlight:function(a,b,c){var d=this.currentRegion,e=!this.options.get("disableHighlight"),f;return b>this.canvasWidth||c>this.canvasHeight||b<0||c<0?null:(f=this.getRegion(a,b,c),d!==f?(d!==undefined&&e&&this.removeHighlight(),this.currentRegion=f,f!==undefined&&e&&this.renderHighlight(),!0):!1)},clearRegionHighlight:function(){return this.currentRegion!==undefined?(this.removeHighlight(),this.currentRegion=undefined,!0):!1},renderHighlight:function(){this.changeHighlight(!0)},removeHighlight:function(){this.changeHighlight(!1)},changeHighlight:function(a){},getCurrentRegionTooltip:function(){var b=this.options,c="",d=[],f,g,h,i,j,k,l,m,n,o,p,q,r,s;i
f(this.currentRegion===undefined)return"";f=this.getCurrentRegionFields(),p=b.get("tooltipFormatter");if(p)return p(this,b,f);b.get("tooltipChartTitle")&&(c+='<div class="jqs jqstitle">'+b.get("tooltipChartTitle")+"</div>\n"),g=this.options.get("tooltipFormat");if(!g)return"";a.isArray(g)||(g=[g]),a.isArray(f)||(f=[f]),l=this.options.get("tooltipFormatFieldlist"),m=this.options.get("tooltipFormatFieldlistKey");if(l&&m){n=[];for(k=f.length;k--;)o=f[k][m],(s=a.inArray(o,l))!=-1&&(n[s]=f[k]);f=n}h=g.length,r=f.length;for(k=0;k<h;k++){q=g[k],typeof q=="string"&&(q=new e(q)),i=q.fclass||"jqsfield";for(s=0;s<r;s++)if(!f[s].isNull||!b.get("tooltipSkipNull"))a.extend(f[s],{prefix:b.get("tooltipPrefix"),suffix:b.get("tooltipSuffix")}),j=q.render(f[s],b.get("tooltipValueLookups"),b),d.push('<div class="'+i+'">'+j+"</div>")}return d.length?c+d.join("\n"):""},getCurrentRegionFields:function(){},calcHighlightColor:function(a,b){var c=b.get("highlightColor"),d=b.get("highlightLighten"),e,
g,h,i;if(c)return c;if(d){e=/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a)||/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(a);if(e){h=[],g=a.length===4?16:1;for(i=0;i<3;i++)h[i]=f(Math.round(parseInt(e[i+1],16)*g*d),0,255);return"rgb("+h.join(",")+")"}}return a}}),t={changeHighlight:function(b){var c=this.currentRegion,d=this.target,e=this.regionShapes[c],f;e&&(f=this.renderRegion(c,b),a.isArray(f)||a.isArray(e)?(d.replaceWithShapes(e,f),this.regionShapes[c]=a.map(f,function(a){return a.id})):(d.replaceWithShape(e,f),this.regionShapes[c]=f.id))},render:function(){var b=this.values,c=this.target,d=this.regionShapes,e,f,g,h;if(!this.cls._super.render.call(this))return;for(g=b.length;g--;){e=this.renderRegion(g);if(e)if(a.isArray(e)){f=[];for(h=e.length;h--;)e[h].append(),f.push(e[h].id);d[g]=f}else e.append(),d[g]=e.id;else d[g]=null}c.render()}},a.fn.sparkline.line=u=d(a.fn.sparkline._base,{type:"line",init:function(a,b,c,d,e){u._super.init.call(this,a,b,c,d,e),this.vertice
s=[],this.regionMap=[],this.xvalues=[],this.yvalues=[],this.yminmax=[],this.hightlightSpotId=null,this.lastShapeId=null,this.initTarget()},getRegion:function(a,b,c){var d,e=this.regionMap;for(d=e.length;d--;)if(e[d]!==null&&b>=e[d][0]&&b<=e[d][1])return e[d][2];return undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.yvalues[a]===null,x:this.xvalues[a],y:this.yvalues[a],color:this.options.get("lineColor"),fillColor:this.options.get("fillColor"),offset:a}},renderHighlight:function(){var a=this.currentRegion,b=this.target,c=this.vertices[a],d=this.options,e=d.get("spotRadius"),f=d.get("highlightSpotColor"),g=d.get("highlightLineColor"),h,i;if(!c)return;e&&f&&(h=b.drawCircle(c[0],c[1],e,undefined,f),this.highlightSpotId=h.id,b.insertAfterShape(this.lastShapeId,h)),g&&(i=b.drawLine(c[0],this.canvasTop,c[0],this.canvasTop+this.canvasHeight,g),this.highlightLineId=i.id,b.insertAfterShape(this.lastShapeId,i))},removeHighlight:function(){var a=
this.target;this.highlightSpotId&&(a.removeShapeId(this.highlightSpotId),this.highlightSpotId=null),this.highlightLineId&&(a.removeShapeId(this.highlightLineId),this.highlightLineId=null)},scanValues:function(){var a=this.values,b=a.length,c=this.xvalues,d=this.yvalues,e=this.yminmax,f,g,h,i,j;for(f=0;f<b;f++)g=a[f],h=typeof a[f]=="string",i=typeof a[f]=="object"&&a[f]instanceof Array,j=h&&a[f].split(":"),h&&j.length===2?(c.push(Number(j[0])),d.push(Number(j[1])),e.push(Number(j[1]))):i?(c.push(g[0]),d.push(g[1]),e.push(g[1])):(c.push(f),a[f]===null||a[f]==="null"?d.push(null):(d.push(Number(g)),e.push(Number(g))));this.options.get("xvalues")&&(c=this.options.get("xvalues")),this.maxy=this.maxyorg=Math.max.apply(Math,e),this.miny=this.minyorg=Math.min.apply(Math,e),this.maxx=Math.max.apply(Math,c),this.minx=Math.min.apply(Math,c),this.xvalues=c,this.yvalues=d,this.yminmax=e},processRangeOptions:function(){var a=this.options,b=a.get("normalRangeMin"),c=a.get("normalRangeMax")
;b!==undefined&&(b<this.miny&&(this.miny=b),c>this.maxy&&(this.maxy=c)),a.get("chartRangeMin")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMin")<this.miny)&&(this.miny=a.get("chartRangeMin")),a.get("chartRangeMax")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMax")>this.maxy)&&(this.maxy=a.get("chartRangeMax")),a.get("chartRangeMinX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMinX")<this.minx)&&(this.minx=a.get("chartRangeMinX")),a.get("chartRangeMaxX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMaxX")>this.maxx)&&(this.maxx=a.get("chartRangeMaxX"))},drawNormalRange:function(a,b,c,d,e){var f=this.options.get("normalRangeMin"),g=this.options.get("normalRangeMax"),h=b+Math.round(c-c*((g-this.miny)/e)),i=Math.round(c*(g-f)/e);this.target.drawRect(a,h,d,i,undefined,this.options.get("normalRangeColor")).append()},render:function(){var b=this.options,c=this.target,d=this.canvasWidth,e=this.canvasHeight,f=this.vertices,g=b.get("sp
otRadius"),h=this.regionMap,i,j,k,l,m,n,o,p,r,s,t,v,w,x,y,z,A,B,C,D,E,F,G,H,I;if(!u._super.render.call(this))return;this.scanValues(),this.processRangeOptions(),G=this.xvalues,H=this.yvalues;if(!this.yminmax.length||this.yvalues.length<2)return;l=m=0,i=this.maxx-this.minx===0?1:this.maxx-this.minx,j=this.maxy-this.miny===0?1:this.maxy-this.miny,k=this.yvalues.length-1,g&&(d<g*4||e<g*4)&&(g=0);if(g){E=b.get("highlightSpotColor")&&!b.get("disableInteraction");if(E||b.get("minSpotColor")||b.get("spotColor")&&H[k]===this.miny)e-=Math.ceil(g);if(E||b.get("maxSpotColor")||b.get("spotColor")&&H[k]===this.maxy)e-=Math.ceil(g),l+=Math.ceil(g);if(E||(b.get("minSpotColor")||b.get("maxSpotColor"))&&(H[0]===this.miny||H[0]===this.maxy))m+=Math.ceil(g),d-=Math.ceil(g);if(E||b.get("spotColor")||b.get("minSpotColor")||b.get("maxSpotColor")&&(H[k]===this.miny||H[k]===this.maxy))d-=Math.ceil(g)}e--,b.get("normalRangeMin")!==undefined&&!b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j)
,o=[],p=[o],x=y=null,z=H.length;for(I=0;I<z;I++)r=G[I],t=G[I+1],s=H[I],v=m+Math.round((r-this.minx)*(d/i)),w=I<z-1?m+Math.round((t-this.minx)*(d/i)):d,y=v+(w-v)/2,h[I]=[x||0,y,I],x=y,s===null?I&&(H[I-1]!==null&&(o=[],p.push(o)),f.push(null)):(s<this.miny&&(s=this.miny),s>this.maxy&&(s=this.maxy),o.length||o.push([v,l+e]),n=[v,l+Math.round(e-e*((s-this.miny)/j))],o.push(n),f.push(n));A=[],B=[],C=p.length;for(I=0;I<C;I++)o=p[I],o.length&&(b.get("fillColor")&&(o.push([o[o.length-1][0],l+e]),B.push(o.slice(0)),o.pop()),o.length>2&&(o[0]=[o[0][0],o[1][1]]),A.push(o));C=B.length;for(I=0;I<C;I++)c.drawShape(B[I],b.get("fillColor"),b.get("fillColor")).append();b.get("normalRangeMin")!==undefined&&b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j),C=A.length;for(I=0;I<C;I++)c.drawShape(A[I],b.get("lineColor"),undefined,b.get("lineWidth")).append();if(g&&b.get("valueSpots")){D=b.get("valueSpots"),D.get===undefined&&(D=new q(D));for(I=0;I<z;I++)F=D.get(H[I]),F&&c.drawCircle(m+Ma
th.round((G[I]-this.minx)*(d/i)),l+Math.round(e-e*((H[I]-this.miny)/j)),g,undefined,F).append()}g&&b.get("spotColor")&&c.drawCircle(m+Math.round((G[G.length-1]-this.minx)*(d/i)),l+Math.round(e-e*((H[k]-this.miny)/j)),g,undefined,b.get("spotColor")).append(),this.maxy!==this.minyorg&&(g&&b.get("minSpotColor")&&(r=G[a.inArray(this.minyorg,H)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.minyorg-this.miny)/j)),g,undefined,b.get("minSpotColor")).append()),g&&b.get("maxSpotColor")&&(r=G[a.inArray(this.maxyorg,H)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.maxyorg-this.miny)/j)),g,undefined,b.get("maxSpotColor")).append())),this.lastShapeId=c.getLastShapeId(),this.canvasTop=l,c.render()}}),a.fn.sparkline.bar=v=d(a.fn.sparkline._base,t,{type:"bar",init:function(b,c,d,e,g){var k=parseInt(d.get("barWidth"),10),l=parseInt(d.get("barSpacing"),10),m=d.get("chartRangeMin"),n=d.get("chartRangeMax"),o=d.get("chartRangeClip"),p=Infinity,
r=-Infinity,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P;v._super.init.call(this,b,c,d,e,g);for(y=0,z=c.length;y<z;y++){M=c[y],s=typeof M=="string"&&M.indexOf(":")>-1;if(s||a.isArray(M))H=!0,s&&(M=c[y]=i(M.split(":"))),M=j(M,null),t=Math.min.apply(Math,M),u=Math.max.apply(Math,M),t<p&&(p=t),u>r&&(r=u)}this.stacked=H,this.regionShapes={},this.barWidth=k,this.barSpacing=l,this.totalBarWidth=k+l,this.width=e=c.length*k+(c.length-1)*l,this.initTarget(),o&&(F=m===undefined?-Infinity:m,G=n===undefined?Infinity:n),x=[],w=H?[]:x;var Q=[],R=[];for(y=0,z=c.length;y<z;y++)if(H){I=c[y],c[y]=L=[],Q[y]=0,w[y]=R[y]=0;for(J=0,K=I.length;J<K;J++)M=L[J]=o?f(I[J],F,G):I[J],M!==null&&(M>0&&(Q[y]+=M),p<0&&r>0?M<0?R[y]+=Math.abs(M):w[y]+=M:w[y]+=Math.abs(M-(M<0?r:p)),x.push(M))}else M=o?f(c[y],F,G):c[y],M=c[y]=h(M),M!==null&&x.push(M);this.max=E=Math.max.apply(Math,x),this.min=D=Math.min.apply(Math,x),this.stackMax=r=H?Math.max.apply(Math,Q):E,this.stackMin=p=H?Math.min.apply(Math,x):D,d.get("ch
artRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<D)&&(D=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMax")>E)&&(E=d.get("chartRangeMax")),this.zeroAxis=B=d.get("zeroAxis",!0),D<=0&&E>=0&&B?C=0:B==0?C=D:D>0?C=D:C=E,this.xaxisOffset=C,A=H?Math.max.apply(Math,w)+Math.max.apply(Math,R):E-D,this.canvasHeightEf=B&&D<0?this.canvasHeight-2:this.canvasHeight-1,D<C?(O=H&&E>=0?r:E,N=(O-C)/A*this.canvasHeight,N!==Math.ceil(N)&&(this.canvasHeightEf-=2,N=Math.ceil(N))):N=this.canvasHeight,this.yoffset=N,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.range=A},getRegion:function(a,b,c){var d=Math.floor(b/this.totalBarWidth);return d<0||d>=this.values.length?undefined:d},getCurren
tRegionFields:function(){var a=this.currentRegion,b=o(this.values[a]),c=[],d,e;for(e=b.length;e--;)d=b[e],c.push({isNull:d===null,value:d,color:this.calcColor(e,d,a),offset:a});return c},calcColor:function(b,c,d){var e=this.colorMapByIndex,f=this.colorMapByValue,g=this.options,h,i;return this.stacked?h=g.get("stackedBarColor"):h=c<0?g.get("negBarColor"):g.get("barColor"),c===0&&g.get("zeroColor")!==undefined&&(h=g.get("zeroColor")),f&&(i=f.get(c))?h=i:e&&e.length>d&&(h=e[d]),a.isArray(h)?h[b%h.length]:h},renderRegion:function(b,c){var d=this.values[b],e=this.options,f=this.xaxisOffset,g=[],h=this.range,i=this.stacked,j=this.target,k=b*this.totalBarWidth,m=this.canvasHeightEf,n=this.yoffset,o,p,q,r,s,t,u,v,w,x;d=a.isArray(d)?d:[d],u=d.length,v=d[0],r=l(null,d),x=l(f,d,!0);if(r)return e.get("nullColor")?(q=c?e.get("nullColor"):this.calcHighlightColor(e.get("nullColor"),e),o=n>0?n-1:n,j.drawRect(k,o,this.barWidth-1,0,q,q)):undefined;s=n;for(t=0;t<u;t++){v=d[t];if(i&&v===f){if(!
x||w)continue;w=!0}h>0?p=Math.floor(m*(Math.abs(v-f)/h))+1:p=1,v<f||v===f&&n===0?(o=s,s+=p):(o=n-p,n-=p),q=this.calcColor(t,v,b),c&&(q=this.calcHighlightColor(q,e)),g.push(j.drawRect(k,o,this.barWidth-1,p-1,q,q))}return g.length===1?g[0]:g}}),a.fn.sparkline.tristate=w=d(a.fn.sparkline._base,t,{type:"tristate",init:function(b,c,d,e,f){var g=parseInt(d.get("barWidth"),10),h=parseInt(d.get("barSpacing"),10);w._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.barWidth=g,this.barSpacing=h,this.totalBarWidth=g+h,this.values=a.map(c,Number),this.width=e=c.length*g+(c.length-1)*h,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.initTarget()},getRegion:function(a,b,c){return Math.floor(b/this.totalBarWidth)},getCurrentRegionFields:function(){var a=t
his.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],color:this.calcColor(this.values[a],a),offset:a}},calcColor:function(a,b){var c=this.values,d=this.options,e=this.colorMapByIndex,f=this.colorMapByValue,g,h;return f&&(h=f.get(a))?g=h:e&&e.length>b?g=e[b]:c[b]<0?g=d.get("negBarColor"):c[b]>0?g=d.get("posBarColor"):g=d.get("zeroBarColor"),g},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.target,f,g,h,i,j,k;f=e.pixelHeight,h=Math.round(f/2),i=a*this.totalBarWidth,c[a]<0?(j=h,g=h-1):c[a]>0?(j=0,g=h-1):(j=h-1,g=2),k=this.calcColor(c[a],a);if(k===null)return;return b&&(k=this.calcHighlightColor(k,d)),e.drawRect(i,j,this.barWidth-1,g-1,k,k)}}),a.fn.sparkline.discrete=x=d(a.fn.sparkline._base,t,{type:"discrete",init:function(b,c,d,e,f){x._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.values=c=a.map(c,Number),this.min=Math.min.apply(Math,c),this.max=Math.max.apply(Math,c),this.range=this.max-this.min,this.width=e=d.get("wi
dth")==="auto"?c.length*2:this.width,this.interval=Math.floor(e/c.length),this.itemWidth=e/c.length,d.get("chartRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<this.min)&&(this.min=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMax")>this.max)&&(this.max=d.get("chartRangeMax")),this.initTarget(),this.target&&(this.lineHeight=d.get("lineHeight")==="auto"?Math.round(this.canvasHeight*.3):d.get("lineHeight"))},getRegion:function(a,b,c){return Math.floor(b/this.itemWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],offset:a}},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.min,g=this.max,h=this.range,i=this.interval,j=this.target,k=this.canvasHeight,l=this.lineHeight,m=k-l,n,o,p,q;return o=f(c[a],e,g),q=a*i,n=Math.round(m-m*((o-e)/h)),p=d.get("thresholdColor")&&o<d.get("thresholdValue")?d.get("thresholdC
olor"):d.get("lineColor"),b&&(p=this.calcHighlightColor(p,d)),j.drawLine(q,n,q,n+l,p)}}),a.fn.sparkline.bullet=y=d(a.fn.sparkline._base,{type:"bullet",init:function(a,b,c,d,e){var f,g,h;y._super.init.call(this,a,b,c,d,e),this.values=b=i(b),h=b.slice(),h[0]=h[0]===null?h[2]:h[0],h[1]=b[1]===null?h[2]:h[1],f=Math.min.apply(Math,b),g=Math.max.apply(Math,b),c.get("base")===undefined?f=f<0?f:0:f=c.get("base"),this.min=f,this.max=g,this.range=g-f,this.shapes={},this.valueShapes={},this.regiondata={},this.width=d=c.get("width")==="auto"?"4.0em":d,this.target=this.$el.simpledraw(d,e,c.get("composite")),b.length||(this.disabled=!0),this.initTarget()},getRegion:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{fieldkey:a.substr(0,1),value:this.values[a.substr(1)],region:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.valueShapes
[b],d;delete this.shapes[c];switch(b.substr(0,1)){case"r":d=this.renderRange(b.substr(1),a);break;case"p":d=this.renderPerformance(a);break;case"t":d=this.renderTarget(a)}this.valueShapes[b]=d.id,this.shapes[d.id]=b,this.target.replaceWithShape(c,d)},renderRange:function(a,b){var c=this.values[a],d=Math.round(this.canvasWidth*((c-this.min)/this.range)),e=this.options.get("rangeColors")[a-2];return b&&(e=this.calcHighlightColor(e,this.options)),this.target.drawRect(0,0,d-1,this.canvasHeight-1,e,e)},renderPerformance:function(a){var b=this.values[1],c=Math.round(this.canvasWidth*((b-this.min)/this.range)),d=this.options.get("performanceColor");return a&&(d=this.calcHighlightColor(d,this.options)),this.target.drawRect(0,Math.round(this.canvasHeight*.3),c-1,Math.round(this.canvasHeight*.4)-1,d,d)},renderTarget:function(a){var b=this.values[0],c=Math.round(this.canvasWidth*((b-this.min)/this.range)-this.options.get("targetWidth")/2),d=Math.round(this.canvasHeight*.1),e=this.canva
sHeight-d*2,f=this.options.get("targetColor");return a&&(f=this.calcHighlightColor(f,this.options)),this.target.drawRect(c,d,this.options.get("targetWidth")-1,e-1,f,f)},render:function(){var a=this.values.length,b=this.target,c,d;if(!y._super.render.call(this))return;for(c=2;c<a;c++)d=this.renderRange(c).append(),this.shapes[d.id]="r"+c,this.valueShapes["r"+c]=d.id;this.values[1]!==null&&(d=this.renderPerformance().append(),this.shapes[d.id]="p1",this.valueShapes.p1=d.id),this.values[0]!==null&&(d=this.renderTarget().append(),this.shapes[d.id]="t0",this.valueShapes.t0=d.id),b.render()}}),a.fn.sparkline.pie=z=d(a.fn.sparkline._base,{type:"pie",init:function(b,c,d,e,f){var g=0,h;z._super.init.call(this,b,c,d,e,f),this.shapes={},this.valueShapes={},this.values=c=a.map(c,Number),d.get("width")==="auto"&&(this.width=this.height);if(c.length>0)for(h=c.length;h--;)g+=c[h];this.total=g,this.initTarget(),this.radius=Math.floor(Math.min(this.canvasWidth,this.canvasHeight)/2)},getRegio
n:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],percent:this.values[a]/this.total*100,color:this.options.get("sliceColors")[a%this.options.get("sliceColors").length],offset:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.renderSlice(b,a),d=this.valueShapes[b];delete this.shapes[d],this.target.replaceWithShape(d,c),this.valueShapes[b]=c.id,this.shapes[c.id]=b},renderSlice:function(a,b){var c=this.target,d=this.options,e=this.radius,f=d.get("borderWidth"),g=d.get("offset"),h=2*Math.PI,i=this.values,j=this.total,k=g?2*Math.PI*(g/360):0,l,m,n,o,p;o=i.length;for(n=0;n<o;n++){l=k,m=k,j>0&&(m=k+h*(i[n]/j));if(a===n)return p=d.get("sliceColors")[n%d.get("sliceColors").length],b&&(p=this.calcHighlightColor(p,d)),c.drawPieSlice(e,e,e-f,l,m,undefined,p);k=m}},render:funct
ion(){var a=this.target,b=this.values,c=this.options,d=this.radius,e=c.get("borderWidth"),f,g;if(!z._super.render.call(this))return;
-e&&a.drawCircle(d,d,Math.floor(d-e/2),c.get("borderColor"),undefined,e).append();for(g=b.length;g--;)b[g]&&(f=this.renderSlice(g).append(),this.valueShapes[g]=f.id,this.shapes[f.id]=g);a.render()}}),a.fn.sparkline.box=A=d(a.fn.sparkline._base,{type:"box",init:function(b,c,d,e,f){A._super.init.call(this,b,c,d,e,f),this.values=a.map(c,Number),this.width=d.get("width")==="auto"?"4.0em":e,this.initTarget(),this.values.length||(this.disabled=1)},getRegion:function(){return 1},getCurrentRegionFields:function(){var a=[{field:"lq",value:this.quartiles[0]},{field:"med",value:this.quartiles[1]},{field:"uq",value:this.quartiles[2]}];return this.loutlier!==undefined&&a.push({field:"lo",value:this.loutlier}),this.routlier!==undefined&&a.push({field:"ro",value:this.routlier}),this.lwhisker!==undefined&&a.push({field:"lw",value:this.lwhisker}),this.rwhisker!==undefined&&a.push({field:"rw",value:this.rwhisker}),a},render:function(){var a=this.target,b=this.values,c=b.length,d=this.options,e
=this.canvasWidth,f=this.canvasHeight,h=d.get("chartRangeMin")===undefined?Math.min.apply(Math,b):d.get("chartRangeMin"),i=d.get("chartRangeMax")===undefined?Math.max.apply(Math,b):d.get("chartRangeMax"),j=0,k,l,m,n,o,p,q,r,s,t,u;if(!A._super.render.call(this))return;if(d.get("raw"))d.get("showOutliers")&&b.length>5?(l=b[0],k=b[1],n=b[2],o=b[3],p=b[4],q=b[5],r=b[6]):(k=b[0],n=b[1],o=b[2],p=b[3],q=b[4]);else{b.sort(function(a,b){return a-b}),n=g(b,1),o=g(b,2),p=g(b,3),m=p-n;if(d.get("showOutliers")){k=q=undefined;for(s=0;s<c;s++)k===undefined&&b[s]>n-m*d.get("outlierIQR")&&(k=b[s]),b[s]<p+m*d.get("outlierIQR")&&(q=b[s]);l=b[0],r=b[c-1]}else k=b[0],q=b[c-1]}this.quartiles=[n,o,p],this.lwhisker=k,this.rwhisker=q,this.loutlier=l,this.routlier=r,u=e/(i-h+1),d.get("showOutliers")&&(j=Math.ceil(d.get("spotRadius")),e-=2*Math.ceil(d.get("spotRadius")),u=e/(i-h+1),l<k&&a.drawCircle((l-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append(),r>q&&a.
drawCircle((r-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append()),a.drawRect(Math.round((n-h)*u+j),Math.round(f*.1),Math.round((p-n)*u),Math.round(f*.8),d.get("boxLineColor"),d.get("boxFillColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/2),Math.round((n-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/4),Math.round((k-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math.round((q-h)*u+j),Math.round(f/2),Math.round((p-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((q-h)*u+j),Math.round(f/4),Math.round((q-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math.round((o-h)*u+j),Math.round(f*.1),Math.round((o-h)*u+j),Math.round(f*.9),d.get("medianColor")).append(),d.get("target")&&(t=Math.ceil(d.get("spotRadius")),a.drawLine(Math.round((d.get("target")-h)*u+j),Math.round(f/2-t),Math.round((d.get("target")-h)
*u+j),Math.round(f/2+t),d.get("targetColor")).append(),a.drawLine(Math.round((d.get("target")-h)*u+j-t),Math.round(f/2),Math.round((d.get("target")-h)*u+j+t),Math.round(f/2),d.get("targetColor")).append()),a.render()}}),a.browser.msie&&document.namespaces&&!document.namespaces.v&&document.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"),a.browser.hasCanvas===undefined&&(a.browser.hasCanvas=document.createElement("canvas").getContext!==undefined),D=d({init:function(a,b,c,d){this.target=a,this.id=b,this.type=c,this.args=d},append:function(){return this.target.appendShape(this),this}}),E=d({_pxregex:/(\d+)(px)?\s*$/i,init:function(b,c,d){if(!b)return;this.width=b,this.height=c,this.target=d,this.lastShapeId=null,d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this)},drawLine:function(a,b,c,d,e,f){return this.drawShape([[a,b],[c,d]],e,f)},drawShape:function(a,b,c,d){return this._genShape("Shape",[a,b,c,d])},drawCircle:function(a,b,c,d,e,f){return this._genShape("Circle"
,[a,b,c,d,e,f])},drawPieSlice:function(a,b,c,d,e,f,g){return this._genShape("PieSlice",[a,b,c,d,e,f,g])},drawRect:function(a,b,c,d,e,f){return this._genShape("Rect",[a,b,c,d,e,f])},getElement:function(){return this.canvas},getLastShapeId:function(){return this.lastShapeId},reset:function(){alert("reset not implemented")},_insert:function(b,c){a(c).html(b)},_calculatePixelDims:function(b,c,d){var e;e=this._pxregex.exec(c),e?this.pixelHeight=e[1]:this.pixelHeight=a(d).height(),e=this._pxregex.exec(b),e?this.pixelWidth=e[1]:this.pixelWidth=a(d).width()},_genShape:function(a,b){var c=I++;return b.unshift(c),new D(this,c,a,b)},appendShape:function(a){alert("appendShape not implemented")},replaceWithShape:function(a,b){alert("replaceWithShape not implemented")},insertAfterShape:function(a,b){alert("insertAfterShape not implemented")},removeShapeId:function(a){alert("removeShapeId not implemented")},getShapeAt:function(a,b,c){alert("getShapeAt not implemented")},render:function(){a
lert("render not implemented")}}),F=d(E,{init:function(b,c,d,e){F._super.init.call(this,b,c,d),this.canvas=document.createElement("canvas"),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),a(this.canvas).css({display:"inline-block",width:b,height:c,verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,this.interact=e,this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined,a(this.canvas).css({width:this.pixelWidth,height:this.pixelHeight})},_getContext:function(a,b,c){var d=this.canvas.getContext("2d");return a!==undefined&&(d.strokeStyle=a),d.lineWidth=c===undefined?1:c,b!==undefined&&(d.fillStyle=b),d},reset:function(){var a=this._getContext();a.clearRect(0,0,this.pixelWidth,this.pixelHeight),this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined},_drawShape:function(a,b,c,d,e){var f=this._getContext(c,d,e),g,h;f.beginPath(),f.moveTo(b[0][0]+.5,b[
0][1]+.5);for(g=1,h=b.length;g<h;g++)f.lineTo(b[g][0]+.5,b[g][1]+.5);c!==undefined&&f.stroke(),d!==undefined&&f.fill(),this.targetX!==undefined&&this.targetY!==undefined&&f.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawCircle:function(a,b,c,d,e,f,g){var h=this._getContext(e,f,g);h.beginPath(),h.arc(b,c,d,0,2*Math.PI,!1),this.targetX!==undefined&&this.targetY!==undefined&&h.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a),e!==undefined&&h.stroke(),f!==undefined&&h.fill()},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i=this._getContext(g,h);i.beginPath(),i.moveTo(b,c),i.arc(b,c,d,e,f,!1),i.lineTo(b,c),i.closePath(),g!==undefined&&i.stroke(),h&&i.fill(),this.targetX!==undefined&&this.targetY!==undefined&&i.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b+d,c],[b+d,c+e],[b,c+e],[b,c]],f,g)},appendShape:function(a){return this.shapes[a
.id]=a,this.shapeseq.push(a.id),this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=this.shapeseq,d;this.shapes[b.id]=b;for(d=c.length;d--;)c[d]==a&&(c[d]=b.id);delete this.shapes[a]},replaceWithShapes:function(a,b){var c=this.shapeseq,d={},e,f,g;for(f=a.length;f--;)d[a[f]]=!0;for(f=c.length;f--;)e=c[f],d[e]&&(c.splice(f,1),delete this.shapes[e],g=f);for(f=b.length;f--;)c.splice(g,0,b[f].id),this.shapes[b[f].id]=b[f]},insertAfterShape:function(a,b){var c=this.shapeseq,d;for(d=c.length;d--;)if(c[d]===a){c.splice(d+1,0,b.id),this.shapes[b.id]=b;return}},removeShapeId:function(a){var b=this.shapeseq,c;for(c=b.length;c--;)if(b[c]===a){b.splice(c,1);break}delete this.shapes[a]},getShapeAt:function(a,b,c){return this.targetX=b,this.targetY=c,this.render(),this.currentTargetShapeId},render:function(){var a=this.shapeseq,b=this.shapes,c=a.length,d=this._getContext(),e,f,g;d.clearRect(0,0,this.pixelWidth,this.pixelHeight);for(g=0;g<c;g++)e=a[g],f=b[e],this["_draw"+f.type
].apply(this,f.args);this.interact||(this.shapes={},this.shapeseq=[])}}),G=d(E,{init:function(b,c,d){var e;G._super.init.call(this,b,c,d),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),this.canvas=document.createElement("span"),a(this.canvas).css({display:"inline-block",position:"relative",overflow:"hidden",width:b,height:c,margin:"0px",padding:"0px",verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,e='<v:group coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'"'+' style="position:absolute;top:0;left:0;width:'+this.pixelWidth+"px;height="+this.pixelHeight+'px;"></v:group>',this.canvas.insertAdjacentHTML("beforeEnd",e),this.group=a(this.canvas).children()[0],this.rendered=!1,this.prerender=""},_drawShape:function(a,b,c,d,e){var f=[],g,h,i,j,k,l,m;for(m=0,l=b.length;m<l;m++)f[m]=""+b[m][0]+","+b[m][1];return g=f.splice(0,1),e=e===undefined?1:e,h=c===
undefined?' stroked="false" ':' strokeWeight="'+e+'px" strokeColor="'+c+'" ',i=d===undefined?' filled="false"':' fillColor="'+d+'" filled="true" ',j=f[0]===f[f.length-1]?"x ":"",k='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+h+i+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+g+" l "+f.join(", ")+" "+j+'e">'+" </v:shape>",k},_drawCircle:function(a,b,c,d,e,f,g){var h,i,j;return b-=d,c-=d,h=e===undefined?' stroked="false" ':' strokeWeight="'+g+'px" strokeColor="'+e+'" ',i=f===undefined?' filled="false"':' fillColor="'+f+'" filled="true" ',j='<v:oval id="jqsshape'+a+'" '+h+i+' style="position:absolute;top:'+c+"px; left:"+b+"px; width:"+d*2+"px; height:"+d*2+'px"></v:oval>',j},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i,j,k,l,m,n,o,p;if(e===f)return;f-e===2*Math.PI&&(e=0,f=2*Math.PI),j=b+Math.round(Math.cos(e)*d),k=c+Math.ro
und(Math.sin(e)*d),l=b+Math.round(Math.cos(f)*d),m=c+Math.round(Math.sin(f)*d);if(j===l&&k===m&&f-e<Math.PI)return;return i=[b-d,c-d,b+d,c+d,j,k,l,m],n=g===undefined?' stroked="false" ':' strokeWeight="1px" strokeColor="'+g+'" ',o=h===undefined?' filled="false"':' fillColor="'+h+'" filled="true" ',p='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+n+o+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+b+","+c+" wa "+i.join(", ")+' x e">'+" </v:shape>",p},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b,c+e],[b+d,c+e],[b+d,c],[b,c]],f,g)},reset:function(){this.group.innerHTML=""},appendShape:function(a){var b=this["_draw"+a.type].apply(this,a.args);return this.rendered?this.group.insertAdjacentHTML("beforeEnd",b):this.prerender+=b,this.lastShapeId=a.id,a.id},replaceWithShape:function(b,c){var d=a("#jqsshape"+b),
e=this["_draw"+c.type].apply(this,c.args);d[0].outerHTML=e},replaceWithShapes:function(b,c){var d=a("#jqsshape"+b[0]),e="",f=c.length,g;for(g=0;g<f;g++)e+=this["_draw"+c[g].type].apply(this,c[g].args);d[0].outerHTML=e;for(g=1;g<b.length;g++)a("#jqsshape"+b[g]).remove()},insertAfterShape:function(b,c){var d=a("#jqsshape"+b),e=this["_draw"+c.type].apply(this,c.args);d[0].insertAdjacentHTML("afterEnd",e)},removeShapeId:function(b){var c=a("#jqsshape"+b);this.group.removeChild(c[0])},getShapeAt:function(a,b,c){var d=a.id.substr(8);return d},render:function(){this.rendered||(this.group.innerHTML=this.prerender,this.rendered=!0)}})});
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/moment.js b/modules/enterprise/gui/coregui/src/main/webapp/js/moment.js
new file mode 100644
index 0000000..30a0a6c
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/moment.js
@@ -0,0 +1,1400 @@
+// moment.js
+// version : 2.0.0
+// author : Tim Wood
+// license : MIT
+// momentjs.com
+
+(function (undefined) {
+
+ /************************************
+ Constants
+ ************************************/
+
+ var moment,
+ VERSION = "2.0.0",
+ round = Math.round, i,
+ // internal storage for language config files
+ languages = {},
+
+ // check for nodeJS
+ hasModule = (typeof module !== 'undefined' && module.exports),
+
+ // ASP.NET json date format regex
+ aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
+
+ // format tokens
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,
+ localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
+
+ // parsing tokens
+ parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
+
+ // parsing token regexes
+ parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
+ parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
+ parseTokenThreeDigits = /\d{3}/, // 000 - 999
+ parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
+ parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
+ parseTokenWord = /[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i, // any word (or two) characters or numbers including two word month in arabic.
+ parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
+ parseTokenT = /T/i, // T (ISO seperator)
+ parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
+
+ // preliminary iso regex
+ // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
+ isoRegex = /^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
+ isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
+
+ // iso time formats and regexes
+ isoTimes = [
+ ['HH:mm:ss.S', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
+ ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
+ ['HH:mm', /(T| )\d\d:\d\d/],
+ ['HH', /(T| )\d\d/]
+ ],
+
+ // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
+ parseTimezoneChunker = /([\+\-]|\d\d)/gi,
+
+ // getter and setter names
+ proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
+ unitMillisecondFactors = {
+ 'Milliseconds' : 1,
+ 'Seconds' : 1e3,
+ 'Minutes' : 6e4,
+ 'Hours' : 36e5,
+ 'Days' : 864e5,
+ 'Months' : 2592e6,
+ 'Years' : 31536e6
+ },
+
+ // format function strings
+ formatFunctions = {},
+
+ // tokens to ordinalize and pad
+ ordinalizeTokens = 'DDD w W M D d'.split(' '),
+ paddedTokens = 'M D H h m s w W'.split(' '),
+
+ formatTokenFunctions = {
+ M : function () {
+ return this.month() + 1;
+ },
+ MMM : function (format) {
+ return this.lang().monthsShort(this, format);
+ },
+ MMMM : function (format) {
+ return this.lang().months(this, format);
+ },
+ D : function () {
+ return this.date();
+ },
+ DDD : function () {
+ return this.dayOfYear();
+ },
+ d : function () {
+ return this.day();
+ },
+ dd : function (format) {
+ return this.lang().weekdaysMin(this, format);
+ },
+ ddd : function (format) {
+ return this.lang().weekdaysShort(this, format);
+ },
+ dddd : function (format) {
+ return this.lang().weekdays(this, format);
+ },
+ w : function () {
+ return this.week();
+ },
+ W : function () {
+ return this.isoWeek();
+ },
+ YY : function () {
+ return leftZeroFill(this.year() % 100, 2);
+ },
+ YYYY : function () {
+ return leftZeroFill(this.year(), 4);
+ },
+ YYYYY : function () {
+ return leftZeroFill(this.year(), 5);
+ },
+ a : function () {
+ return this.lang().meridiem(this.hours(), this.minutes(), true);
+ },
+ A : function () {
+ return this.lang().meridiem(this.hours(), this.minutes(), false);
+ },
+ H : function () {
+ return this.hours();
+ },
+ h : function () {
+ return this.hours() % 12 || 12;
+ },
+ m : function () {
+ return this.minutes();
+ },
+ s : function () {
+ return this.seconds();
+ },
+ S : function () {
+ return ~~(this.milliseconds() / 100);
+ },
+ SS : function () {
+ return leftZeroFill(~~(this.milliseconds() / 10), 2);
+ },
+ SSS : function () {
+ return leftZeroFill(this.milliseconds(), 3);
+ },
+ Z : function () {
+ var a = -this.zone(),
+ b = "+";
+ if (a < 0) {
+ a = -a;
+ b = "-";
+ }
+ return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2);
+ },
+ ZZ : function () {
+ var a = -this.zone(),
+ b = "+";
+ if (a < 0) {
+ a = -a;
+ b = "-";
+ }
+ return b + leftZeroFill(~~(10 * a / 6), 4);
+ },
+ X : function () {
+ return this.unix();
+ }
+ };
+
+ function padToken(func, count) {
+ return function (a) {
+ return leftZeroFill(func.call(this, a), count);
+ };
+ }
+ function ordinalizeToken(func) {
+ return function (a) {
+ return this.lang().ordinal(func.call(this, a));
+ };
+ }
+
+ while (ordinalizeTokens.length) {
+ i = ordinalizeTokens.pop();
+ formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
+ }
+ while (paddedTokens.length) {
+ i = paddedTokens.pop();
+ formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
+ }
+ formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
+
+
+ /************************************
+ Constructors
+ ************************************/
+
+ function Language() {
+
+ }
+
+ // Moment prototype object
+ function Moment(config) {
+ extend(this, config);
+ }
+
+ // Duration Constructor
+ function Duration(duration) {
+ var data = this._data = {},
+ years = duration.years || duration.year || duration.y || 0,
+ months = duration.months || duration.month || duration.M || 0,
+ weeks = duration.weeks || duration.week || duration.w || 0,
+ days = duration.days || duration.day || duration.d || 0,
+ hours = duration.hours || duration.hour || duration.h || 0,
+ minutes = duration.minutes || duration.minute || duration.m || 0,
+ seconds = duration.seconds || duration.second || duration.s || 0,
+ milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0;
+
+ // representation for dateAddRemove
+ this._milliseconds = milliseconds +
+ seconds * 1e3 + // 1000
+ minutes * 6e4 + // 1000 * 60
+ hours * 36e5; // 1000 * 60 * 60
+ // Because of dateAddRemove treats 24 hours as different from a
+ // day when working around DST, we need to store them separately
+ this._days = days +
+ weeks * 7;
+ // It is impossible translate months into days without knowing
+ // which months you are are talking about, so we have to store
+ // it separately.
+ this._months = months +
+ years * 12;
+
+ // The following code bubbles up values, see the tests for
+ // examples of what that means.
+ data.milliseconds = milliseconds % 1000;
+ seconds += absRound(milliseconds / 1000);
+
+ data.seconds = seconds % 60;
+ minutes += absRound(seconds / 60);
+
+ data.minutes = minutes % 60;
+ hours += absRound(minutes / 60);
+
+ data.hours = hours % 24;
+ days += absRound(hours / 24);
+
+ days += weeks * 7;
+ data.days = days % 30;
+
+ months += absRound(days / 30);
+
+ data.months = months % 12;
+ years += absRound(months / 12);
+
+ data.years = years;
+ }
+
+
+ /************************************
+ Helpers
+ ************************************/
+
+
+ function extend(a, b) {
+ for (var i in b) {
+ if (b.hasOwnProperty(i)) {
+ a[i] = b[i];
+ }
+ }
+ return a;
+ }
+
+ function absRound(number) {
+ if (number < 0) {
+ return Math.ceil(number);
+ } else {
+ return Math.floor(number);
+ }
+ }
+
+ // left zero fill a number
+ // see http://jsperf.com/left-zero-filling for performance comparison
+ function leftZeroFill(number, targetLength) {
+ var output = number + '';
+ while (output.length < targetLength) {
+ output = '0' + output;
+ }
+ return output;
+ }
+
+ // helper function for _.addTime and _.subtractTime
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
+ var ms = duration._milliseconds,
+ d = duration._days,
+ M = duration._months,
+ currentDate;
+
+ if (ms) {
+ mom._d.setTime(+mom + ms * isAdding);
+ }
+ if (d) {
+ mom.date(mom.date() + d * isAdding);
+ }
+ if (M) {
+ currentDate = mom.date();
+ mom.date(1)
+ .month(mom.month() + M * isAdding)
+ .date(Math.min(currentDate, mom.daysInMonth()));
+ }
+ }
+
+ // check if is an array
+ function isArray(input) {
+ return Object.prototype.toString.call(input) === '[object Array]';
+ }
+
+ // compare two arrays, return the number of differences
+ function compareArrays(array1, array2) {
+ var len = Math.min(array1.length, array2.length),
+ lengthDiff = Math.abs(array1.length - array2.length),
+ diffs = 0,
+ i;
+ for (i = 0; i < len; i++) {
+ if (~~array1[i] !== ~~array2[i]) {
+ diffs++;
+ }
+ }
+ return diffs + lengthDiff;
+ }
+
+
+ /************************************
+ Languages
+ ************************************/
+
+
+ Language.prototype = {
+ set : function (config) {
+ var prop, i;
+ for (i in config) {
+ prop = config[i];
+ if (typeof prop === 'function') {
+ this[i] = prop;
+ } else {
+ this['_' + i] = prop;
+ }
+ }
+ },
+
+ _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+ months : function (m) {
+ return this._months[m.month()];
+ },
+
+ _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+ monthsShort : function (m) {
+ return this._monthsShort[m.month()];
+ },
+
+ monthsParse : function (monthName) {
+ var i, mom, regex, output;
+
+ if (!this._monthsParse) {
+ this._monthsParse = [];
+ }
+
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ if (!this._monthsParse[i]) {
+ mom = moment([2000, i]);
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (this._monthsParse[i].test(monthName)) {
+ return i;
+ }
+ }
+ },
+
+ _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+ weekdays : function (m) {
+ return this._weekdays[m.day()];
+ },
+
+ _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+ weekdaysShort : function (m) {
+ return this._weekdaysShort[m.day()];
+ },
+
+ _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
+ weekdaysMin : function (m) {
+ return this._weekdaysMin[m.day()];
+ },
+
+ _longDateFormat : {
+ LT : "h:mm A",
+ L : "MM/DD/YYYY",
+ LL : "MMMM D YYYY",
+ LLL : "MMMM D YYYY LT",
+ LLLL : "dddd, MMMM D YYYY LT"
+ },
+ longDateFormat : function (key) {
+ var output = this._longDateFormat[key];
+ if (!output && this._longDateFormat[key.toUpperCase()]) {
+ output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
+ return val.slice(1);
+ });
+ this._longDateFormat[key] = output;
+ }
+ return output;
+ },
+
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'pm' : 'PM';
+ } else {
+ return isLower ? 'am' : 'AM';
+ }
+ },
+
+ _calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ calendar : function (key, mom) {
+ var output = this._calendar[key];
+ return typeof output === 'function' ? output.apply(mom) : output;
+ },
+
+ _relativeTime : {
+ 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"
+ },
+ relativeTime : function (number, withoutSuffix, string, isFuture) {
+ var output = this._relativeTime[string];
+ return (typeof output === 'function') ?
+ output(number, withoutSuffix, string, isFuture) :
+ output.replace(/%d/i, number);
+ },
+ pastFuture : function (diff, output) {
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+ return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
+ },
+
+ ordinal : function (number) {
+ return this._ordinal.replace("%d", number);
+ },
+ _ordinal : "%d",
+
+ preparse : function (string) {
+ return string;
+ },
+
+ postformat : function (string) {
+ return string;
+ },
+
+ week : function (mom) {
+ return weekOfYear(mom, this._week.dow, this._week.doy);
+ },
+ _week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+ };
+
+ // Loads a language definition into the `languages` cache. The function
+ // takes a key and optionally values. If not in the browser and no values
+ // are provided, it will load the language file module. As a convenience,
+ // this function also returns the language values.
+ function loadLang(key, values) {
+ values.abbr = key;
+ if (!languages[key]) {
+ languages[key] = new Language();
+ }
+ languages[key].set(values);
+ return languages[key];
+ }
+
+ // Determines which language definition to use and returns it.
+ //
+ // With no parameters, it will return the global language. If you
+ // pass in a language key, such as 'en', it will return the
+ // definition for 'en', so long as 'en' has already been loaded using
+ // moment.lang.
+ function getLangDefinition(key) {
+ if (!key) {
+ return moment.fn._lang;
+ }
+ if (!languages[key] && hasModule) {
+ require('./lang/' + key);
+ }
+ return languages[key];
+ }
+
+
+ /************************************
+ Formatting
+ ************************************/
+
+
+ function removeFormattingTokens(input) {
+ if (input.match(/\[.*\]/)) {
+ return input.replace(/^\[|\]$/g, "");
+ }
+ return input.replace(/\\/g, "");
+ }
+
+ function makeFormatFunction(format) {
+ var array = format.match(formattingTokens), i, length;
+
+ for (i = 0, length = array.length; i < length; i++) {
+ if (formatTokenFunctions[array[i]]) {
+ array[i] = formatTokenFunctions[array[i]];
+ } else {
+ array[i] = removeFormattingTokens(array[i]);
+ }
+ }
+
+ return function (mom) {
+ var output = "";
+ for (i = 0; i < length; i++) {
+ output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i];
+ }
+ return output;
+ };
+ }
+
+ // format date using native date object
+ function formatMoment(m, format) {
+ var i = 5;
+
+ function replaceLongDateFormatTokens(input) {
+ return m.lang().longDateFormat(input) || input;
+ }
+
+ while (i-- && localFormattingTokens.test(format)) {
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+ }
+
+ if (!formatFunctions[format]) {
+ formatFunctions[format] = makeFormatFunction(format);
+ }
+
+ return formatFunctions[format](m);
+ }
+
+
+ /************************************
+ Parsing
+ ************************************/
+
+
+ // get the regex to find the next token
+ function getParseRegexForToken(token) {
+ switch (token) {
+ case 'DDDD':
+ return parseTokenThreeDigits;
+ case 'YYYY':
+ return parseTokenFourDigits;
+ case 'YYYYY':
+ return parseTokenSixDigits;
+ case 'S':
+ case 'SS':
+ case 'SSS':
+ case 'DDD':
+ return parseTokenOneToThreeDigits;
+ case 'MMM':
+ case 'MMMM':
+ case 'dd':
+ case 'ddd':
+ case 'dddd':
+ case 'a':
+ case 'A':
+ return parseTokenWord;
+ case 'X':
+ return parseTokenTimestampMs;
+ case 'Z':
+ case 'ZZ':
+ return parseTokenTimezone;
+ case 'T':
+ return parseTokenT;
+ case 'MM':
+ case 'DD':
+ case 'YY':
+ case 'HH':
+ case 'hh':
+ case 'mm':
+ case 'ss':
+ case 'M':
+ case 'D':
+ case 'd':
+ case 'H':
+ case 'h':
+ case 'm':
+ case 's':
+ return parseTokenOneOrTwoDigits;
+ default :
+ return new RegExp(token.replace('\\', ''));
+ }
+ }
+
+ // function to convert string input to date
+ function addTimeToArrayFromToken(token, input, config) {
+ var a, b,
+ datePartArray = config._a;
+
+ switch (token) {
+ // MONTH
+ case 'M' : // fall through to MM
+ case 'MM' :
+ datePartArray[1] = (input == null) ? 0 : ~~input - 1;
+ break;
+ case 'MMM' : // fall through to MMMM
+ case 'MMMM' :
+ a = getLangDefinition(config._l).monthsParse(input);
+ // if we didn't find a month name, mark the date as invalid.
+ if (a != null) {
+ datePartArray[1] = a;
+ } else {
+ config._isValid = false;
+ }
+ break;
+ // DAY OF MONTH
+ case 'D' : // fall through to DDDD
+ case 'DD' : // fall through to DDDD
+ case 'DDD' : // fall through to DDDD
+ case 'DDDD' :
+ if (input != null) {
+ datePartArray[2] = ~~input;
+ }
+ break;
+ // YEAR
+ case 'YY' :
+ datePartArray[0] = ~~input + (~~input > 68 ? 1900 : 2000);
+ break;
+ case 'YYYY' :
+ case 'YYYYY' :
+ datePartArray[0] = ~~input;
+ break;
+ // AM / PM
+ case 'a' : // fall through to A
+ case 'A' :
+ config._isPm = ((input + '').toLowerCase() === 'pm');
+ break;
+ // 24 HOUR
+ case 'H' : // fall through to hh
+ case 'HH' : // fall through to hh
+ case 'h' : // fall through to hh
+ case 'hh' :
+ datePartArray[3] = ~~input;
+ break;
+ // MINUTE
+ case 'm' : // fall through to mm
+ case 'mm' :
+ datePartArray[4] = ~~input;
+ break;
+ // SECOND
+ case 's' : // fall through to ss
+ case 'ss' :
+ datePartArray[5] = ~~input;
+ break;
+ // MILLISECOND
+ case 'S' :
+ case 'SS' :
+ case 'SSS' :
+ datePartArray[6] = ~~ (('0.' + input) * 1000);
+ break;
+ // UNIX TIMESTAMP WITH MS
+ case 'X':
+ config._d = new Date(parseFloat(input) * 1000);
+ break;
+ // TIMEZONE
+ case 'Z' : // fall through to ZZ
+ case 'ZZ' :
+ config._useUTC = true;
+ a = (input + '').match(parseTimezoneChunker);
+ if (a && a[1]) {
+ config._tzh = ~~a[1];
+ }
+ if (a && a[2]) {
+ config._tzm = ~~a[2];
+ }
+ // reverse offsets
+ if (a && a[0] === '+') {
+ config._tzh = -config._tzh;
+ config._tzm = -config._tzm;
+ }
+ break;
+ }
+
+ // if the input is null, the date is not valid
+ if (input == null) {
+ config._isValid = false;
+ }
+ }
+
+ // convert an array to a date.
+ // the array should mirror the parameters below
+ // note: all values past the year are optional and will default to the lowest possible value.
+ // [year, month, day , hour, minute, second, millisecond]
+ function dateFromArray(config) {
+ var i, date, input = [];
+
+ if (config._d) {
+ return;
+ }
+
+ for (i = 0; i < 7; i++) {
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+ }
+
+ // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
+ input[3] += config._tzh || 0;
+ input[4] += config._tzm || 0;
+
+ date = new Date(0);
+
+ if (config._useUTC) {
+ date.setUTCFullYear(input[0], input[1], input[2]);
+ date.setUTCHours(input[3], input[4], input[5], input[6]);
+ } else {
+ date.setFullYear(input[0], input[1], input[2]);
+ date.setHours(input[3], input[4], input[5], input[6]);
+ }
+
+ config._d = date;
+ }
+
+ // date from string and format string
+ function makeDateFromStringAndFormat(config) {
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
+ var tokens = config._f.match(formattingTokens),
+ string = config._i,
+ i, parsedInput;
+
+ config._a = [];
+
+ for (i = 0; i < tokens.length; i++) {
+ parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
+ if (parsedInput) {
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
+ }
+ // don't parse if its not a known token
+ if (formatTokenFunctions[tokens[i]]) {
+ addTimeToArrayFromToken(tokens[i], parsedInput, config);
+ }
+ }
+ // handle am pm
+ if (config._isPm && config._a[3] < 12) {
+ config._a[3] += 12;
+ }
+ // if is 12 am, change hours to 0
+ if (config._isPm === false && config._a[3] === 12) {
+ config._a[3] = 0;
+ }
+ // return
+ dateFromArray(config);
+ }
+
+ // date from string and array of format strings
+ function makeDateFromStringAndArray(config) {
+ var tempConfig,
+ tempMoment,
+ bestMoment,
+
+ scoreToBeat = 99,
+ i,
+ currentDate,
+ currentScore;
+
+ while (config._f.length) {
+ tempConfig = extend({}, config);
+ tempConfig._f = config._f.pop();
+ makeDateFromStringAndFormat(tempConfig);
+ tempMoment = new Moment(tempConfig);
+
+ if (tempMoment.isValid()) {
+ bestMoment = tempMoment;
+ break;
+ }
+
+ currentScore = compareArrays(tempConfig._a, tempMoment.toArray());
+
+ if (currentScore < scoreToBeat) {
+ scoreToBeat = currentScore;
+ bestMoment = tempMoment;
+ }
+ }
+
+ extend(config, bestMoment);
+ }
+
+ // date from iso format
+ function makeDateFromString(config) {
+ var i,
+ string = config._i;
+ if (isoRegex.exec(string)) {
+ config._f = 'YYYY-MM-DDT';
+ for (i = 0; i < 4; i++) {
+ if (isoTimes[i][1].exec(string)) {
+ config._f += isoTimes[i][0];
+ break;
+ }
+ }
+ if (parseTokenTimezone.exec(string)) {
+ config._f += " Z";
+ }
+ makeDateFromStringAndFormat(config);
+ } else {
+ config._d = new Date(string);
+ }
+ }
+
+ function makeDateFromInput(config) {
+ var input = config._i,
+ matched = aspNetJsonRegex.exec(input);
+
+ if (input === undefined) {
+ config._d = new Date();
+ } else if (matched) {
+ config._d = new Date(+matched[1]);
+ } else if (typeof input === 'string') {
+ makeDateFromString(config);
+ } else if (isArray(input)) {
+ config._a = input.slice(0);
+ dateFromArray(config);
+ } else {
+ config._d = input instanceof Date ? new Date(+input) : new Date(input);
+ }
+ }
+
+
+ /************************************
+ Relative Time
+ ************************************/
+
+
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
+ return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+ }
+
+ function relativeTime(milliseconds, withoutSuffix, lang) {
+ var seconds = round(Math.abs(milliseconds) / 1000),
+ minutes = round(seconds / 60),
+ hours = round(minutes / 60),
+ days = round(hours / 24),
+ years = round(days / 365),
+ args = seconds < 45 && ['s', seconds] ||
+ minutes === 1 && ['m'] ||
+ minutes < 45 && ['mm', minutes] ||
+ hours === 1 && ['h'] ||
+ hours < 22 && ['hh', hours] ||
+ days === 1 && ['d'] ||
+ days <= 25 && ['dd', days] ||
+ days <= 45 && ['M'] ||
+ days < 345 && ['MM', round(days / 30)] ||
+ years === 1 && ['y'] || ['yy', years];
+ args[2] = withoutSuffix;
+ args[3] = milliseconds > 0;
+ args[4] = lang;
+ return substituteTimeAgo.apply({}, args);
+ }
+
+
+ /************************************
+ Week of Year
+ ************************************/
+
+
+ // firstDayOfWeek 0 = sun, 6 = sat
+ // the day of the week that starts the week
+ // (usually sunday or monday)
+ // firstDayOfWeekOfYear 0 = sun, 6 = sat
+ // the first week is the week that contains the first
+ // of this day of the week
+ // (eg. ISO weeks use thursday (4))
+ function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
+ var end = firstDayOfWeekOfYear - firstDayOfWeek,
+ daysToDayOfWeek = firstDayOfWeekOfYear - mom.day();
+
+
+ if (daysToDayOfWeek > end) {
+ daysToDayOfWeek -= 7;
+ }
+
+ if (daysToDayOfWeek < end - 7) {
+ daysToDayOfWeek += 7;
+ }
+
+ return Math.ceil(moment(mom).add('d', daysToDayOfWeek).dayOfYear() / 7);
+ }
+
+
+ /************************************
+ Top Level Functions
+ ************************************/
+
+ function makeMoment(config) {
+ var input = config._i,
+ format = config._f;
+
+ if (input === null || input === '') {
+ return null;
+ }
+
+ if (typeof input === 'string') {
+ config._i = input = getLangDefinition().preparse(input);
+ }
+
+ if (moment.isMoment(input)) {
+ config = extend({}, input);
+ config._d = new Date(+input._d);
+ } else if (format) {
+ if (isArray(format)) {
+ makeDateFromStringAndArray(config);
+ } else {
+ makeDateFromStringAndFormat(config);
+ }
+ } else {
+ makeDateFromInput(config);
+ }
+
+ return new Moment(config);
+ }
+
+ moment = function (input, format, lang) {
+ return makeMoment({
+ _i : input,
+ _f : format,
+ _l : lang,
+ _isUTC : false
+ });
+ };
+
+ // creating with utc
+ moment.utc = function (input, format, lang) {
+ return makeMoment({
+ _useUTC : true,
+ _isUTC : true,
+ _l : lang,
+ _i : input,
+ _f : format
+ });
+ };
+
+ // creating with unix timestamp (in seconds)
+ moment.unix = function (input) {
+ return moment(input * 1000);
+ };
+
+ // duration
+ moment.duration = function (input, key) {
+ var isDuration = moment.isDuration(input),
+ isNumber = (typeof input === 'number'),
+ duration = (isDuration ? input._data : (isNumber ? {} : input)),
+ ret;
+
+ if (isNumber) {
+ if (key) {
+ duration[key] = input;
+ } else {
+ duration.milliseconds = input;
+ }
+ }
+
+ ret = new Duration(duration);
+
+ if (isDuration && input.hasOwnProperty('_lang')) {
+ ret._lang = input._lang;
+ }
+
+ return ret;
+ };
+
+ // version number
+ moment.version = VERSION;
+
+ // default format
+ moment.defaultFormat = isoFormat;
+
+ // This function will load languages and then set the global language. If
+ // no arguments are passed in, it will simply return the current global
+ // language key.
+ moment.lang = function (key, values) {
+ var i;
+
+ if (!key) {
+ return moment.fn._lang._abbr;
+ }
+ if (values) {
+ loadLang(key, values);
+ } else if (!languages[key]) {
+ getLangDefinition(key);
+ }
+ moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
+ };
+
+ // returns language data
+ moment.langData = function (key) {
+ if (key && key._lang && key._lang._abbr) {
+ key = key._lang._abbr;
+ }
+ return getLangDefinition(key);
+ };
+
+ // compare moment object
+ moment.isMoment = function (obj) {
+ return obj instanceof Moment;
+ };
+
+ // for typechecking Duration objects
+ moment.isDuration = function (obj) {
+ return obj instanceof Duration;
+ };
+
+
+ /************************************
+ Moment Prototype
+ ************************************/
+
+
+ moment.fn = Moment.prototype = {
+
+ clone : function () {
+ return moment(this);
+ },
+
+ valueOf : function () {
+ return +this._d;
+ },
+
+ unix : function () {
+ return Math.floor(+this._d / 1000);
+ },
+
+ toString : function () {
+ return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
+ },
+
+ toDate : function () {
+ return this._d;
+ },
+
+ toJSON : function () {
+ return moment.utc(this).format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+ },
+
+ toArray : function () {
+ var m = this;
+ return [
+ m.year(),
+ m.month(),
+ m.date(),
+ m.hours(),
+ m.minutes(),
+ m.seconds(),
+ m.milliseconds()
+ ];
+ },
+
+ isValid : function () {
+ if (this._isValid == null) {
+ if (this._a) {
+ this._isValid = !compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray());
+ } else {
+ this._isValid = !isNaN(this._d.getTime());
+ }
+ }
+ return !!this._isValid;
+ },
+
+ utc : function () {
+ this._isUTC = true;
+ return this;
+ },
+
+ local : function () {
+ this._isUTC = false;
+ return this;
+ },
+
+ format : function (inputString) {
+ var output = formatMoment(this, inputString || moment.defaultFormat);
+ return this.lang().postformat(output);
+ },
+
+ add : function (input, val) {
+ var dur;
+ // switch args to support add('s', 1) and add(1, 's')
+ if (typeof input === 'string') {
+ dur = moment.duration(+val, input);
+ } else {
+ dur = moment.duration(input, val);
+ }
+ addOrSubtractDurationFromMoment(this, dur, 1);
+ return this;
+ },
+
+ subtract : function (input, val) {
+ var dur;
+ // switch args to support subtract('s', 1) and subtract(1, 's')
+ if (typeof input === 'string') {
+ dur = moment.duration(+val, input);
+ } else {
+ dur = moment.duration(input, val);
+ }
+ addOrSubtractDurationFromMoment(this, dur, -1);
+ return this;
+ },
+
+ diff : function (input, units, asFloat) {
+ var that = this._isUTC ? moment(input).utc() : moment(input).local(),
+ zoneDiff = (this.zone() - that.zone()) * 6e4,
+ diff, output;
+
+ if (units) {
+ // standardize on singular form
+ units = units.replace(/s$/, '');
+ }
+
+ if (units === 'year' || units === 'month') {
+ diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
+ output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
+ output += ((this - moment(this).startOf('month')) - (that - moment(that).startOf('month'))) / diff;
+ if (units === 'year') {
+ output = output / 12;
+ }
+ } else {
+ diff = (this - that) - zoneDiff;
+ output = units === 'second' ? diff / 1e3 : // 1000
+ units === 'minute' ? diff / 6e4 : // 1000 * 60
+ units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
+ units === 'day' ? diff / 864e5 : // 1000 * 60 * 60 * 24
+ units === 'week' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
+ diff;
+ }
+ return asFloat ? output : absRound(output);
+ },
+
+ from : function (time, withoutSuffix) {
+ return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
+ },
+
+ fromNow : function (withoutSuffix) {
+ return this.from(moment(), withoutSuffix);
+ },
+
+ calendar : function () {
+ var diff = this.diff(moment().startOf('day'), 'days', true),
+ format = diff < -6 ? 'sameElse' :
+ diff < -1 ? 'lastWeek' :
+ diff < 0 ? 'lastDay' :
+ diff < 1 ? 'sameDay' :
+ diff < 2 ? 'nextDay' :
+ diff < 7 ? 'nextWeek' : 'sameElse';
+ return this.format(this.lang().calendar(format, this));
+ },
+
+ isLeapYear : function () {
+ var year = this.year();
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+ },
+
+ isDST : function () {
+ return (this.zone() < moment([this.year()]).zone() ||
+ this.zone() < moment([this.year(), 5]).zone());
+ },
+
+ day : function (input) {
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+ return input == null ? day :
+ this.add({ d : input - day });
+ },
+
+ startOf: function (units) {
+ units = units.replace(/s$/, '');
+ // the following switch intentionally omits break keywords
+ // to utilize falling through the cases.
+ switch (units) {
+ case 'year':
+ this.month(0);
+ /* falls through */
+ case 'month':
+ this.date(1);
+ /* falls through */
+ case 'week':
+ case 'day':
+ this.hours(0);
+ /* falls through */
+ case 'hour':
+ this.minutes(0);
+ /* falls through */
+ case 'minute':
+ this.seconds(0);
+ /* falls through */
+ case 'second':
+ this.milliseconds(0);
+ /* falls through */
+ }
+
+ // weeks are a special case
+ if (units === 'week') {
+ this.day(0);
+ }
+
+ return this;
+ },
+
+ endOf: function (units) {
+ return this.startOf(units).add(units.replace(/s?$/, 's'), 1).subtract('ms', 1);
+ },
+
+ isAfter: function (input, units) {
+ units = typeof units !== 'undefined' ? units : 'millisecond';
+ return +this.clone().startOf(units) > +moment(input).startOf(units);
+ },
+
+ isBefore: function (input, units) {
+ units = typeof units !== 'undefined' ? units : 'millisecond';
+ return +this.clone().startOf(units) < +moment(input).startOf(units);
+ },
+
+ isSame: function (input, units) {
+ units = typeof units !== 'undefined' ? units : 'millisecond';
+ return +this.clone().startOf(units) === +moment(input).startOf(units);
+ },
+
+ zone : function () {
+ return this._isUTC ? 0 : this._d.getTimezoneOffset();
+ },
+
+ daysInMonth : function () {
+ return moment.utc([this.year(), this.month() + 1, 0]).date();
+ },
+
+ dayOfYear : function (input) {
+ var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
+ return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
+ },
+
+ isoWeek : function (input) {
+ var week = weekOfYear(this, 1, 4);
+ return input == null ? week : this.add("d", (input - week) * 7);
+ },
+
+ week : function (input) {
+ var week = this.lang().week(this);
+ return input == null ? week : this.add("d", (input - week) * 7);
+ },
+
+ // If passed a language key, it will set the language for this
+ // instance. Otherwise, it will return the language configuration
+ // variables for this instance.
+ lang : function (key) {
+ if (key === undefined) {
+ return this._lang;
+ } else {
+ this._lang = getLangDefinition(key);
+ return this;
+ }
+ }
+ };
+
+ // helper for adding shortcuts
+ function makeGetterAndSetter(name, key) {
+ moment.fn[name] = moment.fn[name + 's'] = function (input) {
+ var utc = this._isUTC ? 'UTC' : '';
+ if (input != null) {
+ this._d['set' + utc + key](input);
+ return this;
+ } else {
+ return this._d['get' + utc + key]();
+ }
+ };
+ }
+
+ // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
+ for (i = 0; i < proxyGettersAndSetters.length; i ++) {
+ makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
+ }
+
+ // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
+ makeGetterAndSetter('year', 'FullYear');
+
+ // add plural methods
+ moment.fn.days = moment.fn.day;
+ moment.fn.weeks = moment.fn.week;
+ moment.fn.isoWeeks = moment.fn.isoWeek;
+
+ /************************************
+ Duration Prototype
+ ************************************/
+
+
+ moment.duration.fn = Duration.prototype = {
+ weeks : function () {
+ return absRound(this.days() / 7);
+ },
+
+ valueOf : function () {
+ return this._milliseconds +
+ this._days * 864e5 +
+ this._months * 2592e6;
+ },
+
+ humanize : function (withSuffix) {
+ var difference = +this,
+ output = relativeTime(difference, !withSuffix, this.lang());
+
+ if (withSuffix) {
+ output = this.lang().pastFuture(difference, output);
+ }
+
+ return this.lang().postformat(output);
+ },
+
+ lang : moment.fn.lang
+ };
+
+ function makeDurationGetter(name) {
+ moment.duration.fn[name] = function () {
+ return this._data[name];
+ };
+ }
+
+ function makeDurationAsGetter(name, factor) {
+ moment.duration.fn['as' + name] = function () {
+ return +this / factor;
+ };
+ }
+
+ for (i in unitMillisecondFactors) {
+ if (unitMillisecondFactors.hasOwnProperty(i)) {
+ makeDurationAsGetter(i, unitMillisecondFactors[i]);
+ makeDurationGetter(i.toLowerCase());
+ }
+ }
+
+ makeDurationAsGetter('Weeks', 6048e5);
+
+
+ /************************************
+ Default Lang
+ ************************************/
+
+
+ // Set default language, other languages will inherit from English.
+ moment.lang('en', {
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~ (number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ }
+ });
+
+
+ /************************************
+ Exposing Moment
+ ************************************/
+
+
+ // CommonJS module is defined
+ if (hasModule) {
+ module.exports = moment;
+ }
+ /*global ender:false */
+ if (typeof ender === 'undefined') {
+ // here, `this` means `window` in the browser, or `global` on the server
+ // add `moment` as a global object via a string identifier,
+ // for Closure Compiler "advanced" mode
+ this['moment'] = moment;
+ }
+ /*global define:false */
+ if (typeof define === "function" && define.amd) {
+ define("moment", [], function () {
+ return moment;
+ });
+ }
+}).call(this);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/moment.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/moment.min.js
new file mode 100644
index 0000000..4e8497a
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/moment.min.js
@@ -0,0 +1,6 @@
+// moment.js
+// version : 2.0.0
+// author : Tim Wood
+// license : MIT
+// momentjs.com
+(function(e){function O(e,t){return function(n){return j(e.call(this,n),t)}}function M(e){return function(t){return this.lang().ordinal(e.call(this,t))}}function _(){}function D(e){H(this,e)}function P(e){var t=this._data={},n=e.years||e.year||e.y||0,r=e.months||e.month||e.M||0,i=e.weeks||e.week||e.w||0,s=e.days||e.day||e.d||0,o=e.hours||e.hour||e.h||0,u=e.minutes||e.minute||e.m||0,a=e.seconds||e.second||e.s||0,f=e.milliseconds||e.millisecond||e.ms||0;this._milliseconds=f+a*1e3+u*6e4+o*36e5,this._days=s+i*7,this._months=r+n*12,t.milliseconds=f%1e3,a+=B(f/1e3),t.seconds=a%60,u+=B(a/60),t.minutes=u%60,o+=B(u/60),t.hours=o%24,s+=B(o/24),s+=i*7,t.days=s%30,r+=B(s/30),t.months=r%12,n+=B(r/12),t.years=n}function H(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function B(e){return e<0?Math.ceil(e):Math.floor(e)}function j(e,t){var n=e+"";while(n.length<t)n="0"+n;return n}function F(e,t,n){var r=t._milliseconds,i=t._days,s=t._months,o;r&&e._d.setTime(+e+r*n),i&&e.dat
e(e.date()+i*n),s&&(o=e.date(),e.date(1).month(e.month()+s*n).date(Math.min(o,e.daysInMonth())))}function I(e){return Object.prototype.toString.call(e)==="[object Array]"}function q(e,t){var n=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),i=0,s;for(s=0;s<n;s++)~~e[s]!==~~t[s]&&i++;return i+r}function R(e,t){return t.abbr=e,s[e]||(s[e]=new _),s[e].set(t),s[e]}function U(e){return e?(!s[e]&&o&&require("./lang/"+e),s[e]):t.fn._lang}function z(e){return e.match(/\[.*\]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function W(e){var t=e.match(a),n,r;for(n=0,r=t.length;n<r;n++)A[t[n]]?t[n]=A[t[n]]:t[n]=z(t[n]);return function(i){var s="";for(n=0;n<r;n++)s+=typeof t[n].call=="function"?t[n].call(i,e):t[n];return s}}function X(e,t){function r(t){return e.lang().longDateFormat(t)||t}var n=5;while(n--&&f.test(t))t=t.replace(f,r);return C[t]||(C[t]=W(t)),C[t](e)}function V(e){switch(e){case"DDDD":return p;case"YYYY":return d;case"YYYYY":return v;case"S":case"SS":case"SSS":
case"DDD":return h;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return m;case"X":return b;case"Z":case"ZZ":return g;case"T":return y;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return c;default:return new RegExp(e.replace("\\",""))}}function $(e,t,n){var r,i,s=n._a;switch(e){case"M":case"MM":s[1]=t==null?0:~~t-1;break;case"MMM":case"MMMM":r=U(n._l).monthsParse(t),r!=null?s[1]=r:n._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":t!=null&&(s[2]=~~t);break;case"YY":s[0]=~~t+(~~t>68?1900:2e3);break;case"YYYY":case"YYYYY":s[0]=~~t;break;case"a":case"A":n._isPm=(t+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":s[3]=~~t;break;case"m":case"mm":s[4]=~~t;break;case"s":case"ss":s[5]=~~t;break;case"S":case"SS":case"SSS":s[6]=~~(("0."+t)*1e3);break;case"X":n._d=new Date(parseFloat(t)*1e3);break;case"Z":case"ZZ":n._useUTC=!0,r=(t+"").match(x),r&&r[1]&&(n._tzh=~~r[1]),r
&&r[2]&&(n._tzm=~~r[2]),r&&r[0]==="+"&&(n._tzh=-n._tzh,n._tzm=-n._tzm)}t==null&&(n._isValid=!1)}function J(e){var t,n,r=[];if(e._d)return;for(t=0;t<7;t++)e._a[t]=r[t]=e._a[t]==null?t===2?1:0:e._a[t];r[3]+=e._tzh||0,r[4]+=e._tzm||0,n=new Date(0),e._useUTC?(n.setUTCFullYear(r[0],r[1],r[2]),n.setUTCHours(r[3],r[4],r[5],r[6])):(n.setFullYear(r[0],r[1],r[2]),n.setHours(r[3],r[4],r[5],r[6])),e._d=n}function K(e){var t=e._f.match(a),n=e._i,r,i;e._a=[];for(r=0;r<t.length;r++)i=(V(t[r]).exec(n)||[])[0],i&&(n=n.slice(n.indexOf(i)+i.length)),A[t[r]]&&$(t[r],i,e);e._isPm&&e._a[3]<12&&(e._a[3]+=12),e._isPm===!1&&e._a[3]===12&&(e._a[3]=0),J(e)}function Q(e){var t,n,r,i=99,s,o,u;while(e._f.length){t=H({},e),t._f=e._f.pop(),K(t),n=new D(t);if(n.isValid()){r=n;break}u=q(t._a,n.toArray()),u<i&&(i=u,r=n)}H(e,r)}function G(e){var t,n=e._i;if(w.exec(n)){e._f="YYYY-MM-DDT";for(t=0;t<4;t++)if(S[t][1].exec(n)){e._f+=S[t][0];break}g.exec(n)&&(e._f+=" Z"),K(e)}else e._d=new Date(n)}function Y(t){var
n=t._i,r=u.exec(n);n===e?t._d=new Date:r?t._d=new Date(+r[1]):typeof n=="string"?G(t):I(n)?(t._a=n.slice(0),J(t)):t._d=n instanceof Date?new Date(+n):new Date(n)}function Z(e,t,n,r,i){return i.relativeTime(t||1,!!n,e,r)}function et(e,t,n){var i=r(Math.abs(e)/1e3),s=r(i/60),o=r(s/60),u=r(o/24),a=r(u/365),f=i<45&&["s",i]||s===1&&["m"]||s<45&&["mm",s]||o===1&&["h"]||o<22&&["hh",o]||u===1&&["d"]||u<=25&&["dd",u]||u<=45&&["M"]||u<345&&["MM",r(u/30)]||a===1&&["y"]||["yy",a];return f[2]=t,f[3]=e>0,f[4]=n,Z.apply({},f)}function tt(e,n,r){var i=r-n,s=r-e.day();return s>i&&(s-=7),s<i-7&&(s+=7),Math.ceil(t(e).add("d",s).dayOfYear()/7)}function nt(e){var n=e._i,r=e._f;return n===null||n===""?null:(typeof n=="string"&&(e._i=n=U().preparse(n)),t.isMoment(n)?(e=H({},n),e._d=new Date(+n._d)):r?I(r)?Q(e):K(e):Y(e),new D(e))}function rt(e,n){t.fn[e]=t.fn[e+"s"]=function(e){var t=this._isUTC?"UTC":"";return e!=null?(this._d["set"+t+n](e),this):this._d["get"+t+n]()}}function it(e){t.duration.fn
[e]=function(){return this._data[e]}}function st(e,n){t.duration.fn["as"+e]=function(){return+this/n}}var t,n="2.0.0",r=Math.round,i,s={},o=typeof module!="undefined"&&module.exports,u=/^\/?Date\((\-?\d+)/i,a=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,f=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,l=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,c=/\d\d?/,h=/\d{1,3}/,p=/\d{3}/,d=/\d{1,4}/,v=/[+\-]?\d{1,6}/,m=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,g=/Z|[\+\-]\d\d:?\d\d/i,y=/T/i,b=/[\+\-]?\d+(\.\d{1,3})?/,w=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,E="YYYY-MM-DDTHH:mm:ssZ",S=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],x=/([\+\-]|\d\d)/gi,T="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|
"),N={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},C={},k="DDD w W M D d".split(" "),L="M D H h m s w W".split(" "),A={M:function(){return this.month()+1},MMM:function(e){return this.lang().monthsShort(this,e)},MMMM:function(e){return this.lang().months(this,e)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(e){return this.lang().weekdaysMin(this,e)},ddd:function(e){return this.lang().weekdaysShort(this,e)},dddd:function(e){return this.lang().weekdays(this,e)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return j(this.year()%100,2)},YYYY:function(){return j(this.year(),4)},YYYYY:function(){return j(this.year(),5)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()
%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return j(~~(this.milliseconds()/10),2)},SSS:function(){return j(this.milliseconds(),3)},Z:function(){var e=-this.zone(),t="+";return e<0&&(e=-e,t="-"),t+j(~~(e/60),2)+":"+j(~~e%60,2)},ZZ:function(){var e=-this.zone(),t="+";return e<0&&(e=-e,t="-"),t+j(~~(10*e/6),4)},X:function(){return this.unix()}};while(k.length)i=k.pop(),A[i+"o"]=M(A[i]);while(L.length)i=L.pop(),A[i+i]=O(A[i],2);A.DDDD=O(A.DDD,3),_.prototype={set:function(e){var t,n;for(n in e)t=e[n],typeof t=="function"?this[n]=t:this["_"+n]=t},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(e){return this._months[e.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(e){return this._monthsShort[e.month()]},monthsParse:function(e){var n,r,i,s;this._monthsP
arse||(this._monthsParse=[]);for(n=0;n<12;n++){this._monthsParse[n]||(r=t([2e3,n]),i="^"+this.months(r,"")+"|^"+this.monthsShort(r,""),this._monthsParse[n]=new RegExp(i.replace(".",""),"i"));if(this._monthsParse[n].test(e))return n}},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(e){return this._weekdays[e.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(e){return this._weekdaysShort[e.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(e){return this._weekdaysMin[e.day()]},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(e){var t=this._longDateFormat[e];return!t&&this._longDateFormat[e.toUpperCase()]&&(t=this._longDateFormat[e.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e]=t),t},meridiem:function(e,t,n){return e>11?n?"pm":"PM":n
?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(e,t){var n=this._calendar[e];return typeof n=="function"?n.apply(t):n},_relativeTime:{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"},relativeTime:function(e,t,n,r){var i=this._relativeTime[n];return typeof i=="function"?i(e,t,n,r):i.replace(/%d/i,e)},pastFuture:function(e,t){var n=this._relativeTime[e>0?"future":"past"];return typeof n=="function"?n(t):n.replace(/%s/i,t)},ordinal:function(e){return this._ordinal.replace("%d",e)},_ordinal:"%d",preparse:function(e){return e},postformat:function(e){return e},week:function(e){return tt(e,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},t=function(e,t,n){return nt({_i:e,_f:t,_l:n,_isUTC:!1})},t.utc=function(e,t,
n){return nt({_useUTC:!0,_isUTC:!0,_l:n,_i:e,_f:t})},t.unix=function(e){return t(e*1e3)},t.duration=function(e,n){var r=t.isDuration(e),i=typeof e=="number",s=r?e._data:i?{}:e,o;return i&&(n?s[n]=e:s.milliseconds=e),o=new P(s),r&&e.hasOwnProperty("_lang")&&(o._lang=e._lang),o},t.version=n,t.defaultFormat=E,t.lang=function(e,n){var r;if(!e)return t.fn._lang._abbr;n?R(e,n):s[e]||U(e),t.duration.fn._lang=t.fn._lang=U(e)},t.langData=function(e){return e&&e._lang&&e._lang._abbr&&(e=e._lang._abbr),U(e)},t.isMoment=function(e){return e instanceof D},t.isDuration=function(e){return e instanceof P},t.fn=D.prototype={clone:function(){return t(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return t.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var e=this;return[e.year(),e.month(),e.date(),e.hou
rs(),e.minutes(),e.seconds(),e.milliseconds()]},isValid:function(){return this._isValid==null&&(this._a?this._isValid=!q(this._a,(this._isUTC?t.utc(this._a):t(this._a)).toArray()):this._isValid=!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(e){var n=X(this,e||t.defaultFormat);return this.lang().postformat(n)},add:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,1),this},subtract:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,-1),this},diff:function(e,n,r){var i=this._isUTC?t(e).utc():t(e).local(),s=(this.zone()-i.zone())*6e4,o,u;return n&&(n=n.replace(/s$/,"")),n==="year"||n==="month"?(o=(this.daysInMonth()+i.daysInMonth())*432e5,u=(this.year()-i.year())*12+(this.month()-i.month()),u+=(this-t(this).startOf("month")-(i-t(i).startOf("month")))/o,n==="year"&&(u/=12)):(o=this-i-s,u=n==="second
"?o/1e3:n==="minute"?o/6e4:n==="hour"?o/36e5:n==="day"?o/864e5:n==="week"?o/6048e5:o),r?u:B(u)},from:function(e,n){return t.duration(this.diff(e)).lang(this.lang()._abbr).humanize(!n)},fromNow:function(e){return this.from(t(),e)},calendar:function(){var e=this.diff(t().startOf("day"),"days",!0),n=e<-6?"sameElse":e<-1?"lastWeek":e<0?"lastDay":e<1?"sameDay":e<2?"nextDay":e<7?"nextWeek":"sameElse";return this.format(this.lang().calendar(n,this))},isLeapYear:function(){var e=this.year();return e%4===0&&e%100!==0||e%400===0},isDST:function(){return this.zone()<t([this.year()]).zone()||this.zone()<t([this.year(),5]).zone()},day:function(e){var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return e==null?t:this.add({d:e-t})},startOf:function(e){e=e.replace(/s$/,"");switch(e){case"year":this.month(0);case"month":this.date(1);case"week":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return e==="week"&&this.day(0)
,this},endOf:function(e){return this.startOf(e).add(e.replace(/s?$/,"s"),1).subtract("ms",1)},isAfter:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)>+t(e).startOf(n)},isBefore:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)<+t(e).startOf(n)},isSame:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)===+t(e).startOf(n)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return t.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(e){var n=r((t(this).startOf("day")-t(this).startOf("year"))/864e5)+1;return e==null?n:this.add("d",e-n)},isoWeek:function(e){var t=tt(this,1,4);return e==null?t:this.add("d",(e-t)*7)},week:function(e){var t=this.lang().week(this);return e==null?t:this.add("d",(e-t)*7)},lang:function(t){return t===e?this._lang:(this._lang=U(t),this)}};for(i=0;i<T.length;i++)rt(T[i].toLowerCase().replace(/s$/,""
),T[i]);rt("year","FullYear"),t.fn.days=t.fn.day,t.fn.weeks=t.fn.week,t.fn.isoWeeks=t.fn.isoWeek,t.duration.fn=P.prototype={weeks:function(){return B(this.days()/7)},valueOf:function(){return this._milliseconds+this._days*864e5+this._months*2592e6},humanize:function(e){var t=+this,n=et(t,!e,this.lang());return e&&(n=this.lang().pastFuture(t,n)),this.lang().postformat(n)},lang:t.fn.lang};for(i in N)N.hasOwnProperty(i)&&(st(i,N[i]),it(i.toLowerCase()));st("Weeks",6048e5),t.lang("en",{ordinal:function(e){var t=e%10,n=~~(e%100/10)===1?"th":t===1?"st":t===2?"nd":t===3?"rd":"th";return e+n}}),o&&(module.exports=t),typeof ender=="undefined"&&(this.moment=t),typeof define=="function"&&define.amd&&define("moment",[],function(){return t})}).call(this);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
index 3b35252..161ebcb 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
@@ -11,6 +11,29 @@ if (!window.console.log) window.console.log = function () { };
* Contains all of the data required to render a chart.
* A ChartContext can be passed to multiple chart renders to display different chart types
* of that data.
+ * @param chartId
+ * @param chartHeight
+ * @param metricsData
+ * @param xAxisLabel
+ * @param chartTitle
+ * @param yAxisUnits
+ * @param minChartTitle
+ * @param avgChartTitle
+ * @param peakChartTitle
+ * @param dateLabel
+ * @param timeLabel
+ * @param downLabel
+ * @param unknownLabel
+ * @param noDataLabel
+ * @param hoverStartLabel
+ * @param hoverEndLabel
+ * @param hoverPeriodLabel
+ * @param hoverBarLabel
+ * @param chartHoverTimeFormat
+ * @param chartHoverDateFormat
+ * @param isPortalGraph
+ * @param portalId
+ * @constructor
*/
var ChartContext = function (chartId, chartHeight, metricsData, xAxisLabel, chartTitle, yAxisUnits, minChartTitle, avgChartTitle, peakChartTitle, dateLabel, timeLabel, downLabel, unknownLabel, noDataLabel, hoverStartLabel,hoverEndLabel, hoverPeriodLabel, hoverBarLabel, chartHoverTimeFormat, chartHoverDateFormat, isPortalGraph, portalId )
{
@@ -48,6 +71,22 @@ var ChartContext = function (chartId, chartHeight, metricsData, xAxisLabel, char
this.chartSelection = this.chartHandle + " svg";
},
+/**
+ * Availability Context object constructor
+ * @param chartId
+ * @param availData
+ * @param dateLabel
+ * @param timeLabel
+ * @param hoverStartLabel
+ * @param hoverBarLabel
+ * @param availabilityLabel
+ * @param chartHoverTimeFormat
+ * @param chartHoverDateFormat
+ * @param chartTitle
+ * @param chartUpLabel
+ * @param chartDownLabel
+ * @constructor
+ */
AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverStartLabel, hoverBarLabel, availabilityLabel, chartHoverTimeFormat, chartHoverDateFormat, chartTitle, chartUpLabel, chartDownLabel) {
"use strict";
if (!(this instanceof AvailChartContext)) {
@@ -68,4 +107,26 @@ AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverSta
this.chartDownLabel = chartDownLabel;
this.chartUpLabel = chartUpLabel;
+},
+
+/**
+ * GraphDateContext object constructor.
+ * @param startDate
+ * @param endDate
+ * @constructor
+ */
+GraphDateContext = function (startDate, endDate){
+ "use strict";
+ if (!(this instanceof GraphDateContext)) {
+ throw new Error("GraphDateContext function cannot be called as a function.")
+ }
+ this.startDate = startDate;
+ this.endDate = endDate;
};
+
+function brushed() {
+ x.domain(brush.empty() ? x2.domain() : brush.extent());
+ focus.select("path").attr("d", area);
+ focus.select(".x.axis").call(xAxis);
+}
+
commit dfdc5e6125cf405b2f6e54318fab2d76ca0f4f08
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon May 13 19:34:47 2013 -0700
Add new jQuery stuff.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 206b586..430365f 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -10,7 +10,16 @@
<!-- support internationalized characters -->
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
- <script type="text/javascript" src="js/rhq.js"></script>
+
+ <link rel="stylesheet" href="CoreGUI.css">
+ <!-- for d3 charting -->
+ <link rel="stylesheet" href="css/nv.d3.css">
+ <link rel="stylesheet" href="css/tipsy.css">
+ <link rel="stylesheet" href="css/charts.css">
+ <!-- for d3 dual slider control -->
+ <link rel="stylesheet" href="css/jquery-ui-1.10.3.custom.css">
+ <link href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css">
+
<script type="text/javascript">
var search = location.search;
// only do this if you have not specified locale as query param
@@ -20,6 +29,9 @@
lang = lang.replace("-", "_");
document.write("<meta name='gwt:property' content='locale="+lang +"'>");
}
+ jQuery(function () {
+ jQuery("#dateRangeRadio").buttonset();
+ });
</script>
<title>RHQ</title>
@@ -31,10 +43,6 @@
</script>
- <link rel="stylesheet" href="CoreGUI.css">
- <link rel="stylesheet" href="css/nv.d3.css">
- <link rel="stylesheet" href="css/tipsy.css">
- <link rel="stylesheet" href="css/charts.css">
</head>
<body>
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
index 8728026..631b405 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
@@ -44,6 +44,12 @@
stroke: #50505a;
}
+.brush .extent {
+ stroke: #fff;
+ fill-opacity: .125;
+ shape-rendering: crispEdges;
+}
+
.minLabel, .avgLabel, .highLabel {
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.css b/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.css
new file mode 100755
index 0000000..569ed54
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.css
@@ -0,0 +1,924 @@
+/*! jQuery UI - v1.10.3 - 2013-05-11
+* http://jqueryui.com
+* Includes: jquery.ui.core.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerd...
lorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
+* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+ display: none;
+}
+.ui-helper-hidden-accessible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+.ui-helper-reset {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ line-height: 1.3;
+ text-decoration: none;
+ font-size: 100%;
+ list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+ content: "";
+ display: table;
+ border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+ clear: both;
+}
+.ui-helper-clearfix {
+ min-height: 0; /* support: IE7 */
+}
+.ui-helper-zfix {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ position: absolute;
+ opacity: 0;
+ filter:Alpha(Opacity=0);
+}
+
+.ui-front {
+ z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+ cursor: default !important;
+}
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ display: block;
+ text-indent: -99999px;
+ overflow: hidden;
+ background-repeat: no-repeat;
+}
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+.ui-button {
+ display: inline-block;
+ position: relative;
+ padding: 0;
+ line-height: normal;
+ margin-right: .1em;
+ cursor: pointer;
+ vertical-align: middle;
+ text-align: center;
+ overflow: visible; /* removes extra width in IE */
+}
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+ text-decoration: none;
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+ width: 2.2em;
+}
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+ width: 2.4em;
+}
+.ui-button-icons-only {
+ width: 3.4em;
+}
+button.ui-button-icons-only {
+ width: 3.7em;
+}
+
+/* button text element */
+.ui-button .ui-button-text {
+ display: block;
+ line-height: normal;
+}
+.ui-button-text-only .ui-button-text {
+ padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+ padding: .4em;
+ text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+ padding-left: 2.1em;
+ padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+ padding: .4em 1em;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+ position: absolute;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+ left: 50%;
+ margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+ left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+ right: .5em;
+}
+
+/* button sets */
+.ui-buttonset {
+ margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+ margin-left: 0;
+ margin-right: -.3em;
+}
+
+/* workarounds */
+/* reset extra padding in Firefox, see h5bp.com/l */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+.ui-datepicker {
+ width: 17em;
+ padding: .2em .2em 0;
+ display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+ position: relative;
+ padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+ position: absolute;
+ top: 2px;
+ width: 1.8em;
+ height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+ top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+ left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+ right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+ left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+ right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+ display: block;
+ position: absolute;
+ left: 50%;
+ margin-left: -8px;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+ margin: 0 2.3em;
+ line-height: 1.8em;
+ text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+ font-size: 1em;
+ margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month-year {
+ width: 100%;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+ width: 49%;
+}
+.ui-datepicker table {
+ width: 100%;
+ font-size: .9em;
+ border-collapse: collapse;
+ margin: 0 0 .4em;
+}
+.ui-datepicker th {
+ padding: .7em .3em;
+ text-align: center;
+ font-weight: bold;
+ border: 0;
+}
+.ui-datepicker td {
+ border: 0;
+ padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+ display: block;
+ padding: .2em;
+ text-align: right;
+ text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+ background-image: none;
+ margin: .7em 0 0 0;
+ padding: 0 .2em;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+ float: right;
+ margin: .5em .2em .4em;
+ cursor: pointer;
+ padding: .2em .6em .3em .6em;
+ width: auto;
+ overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+ float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+ width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+ float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+ width: 95%;
+ margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+ width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+ width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+ width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+ border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+ clear: left;
+}
+.ui-datepicker-row-break {
+ clear: both;
+ width: 100%;
+ font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+ direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+ right: 2px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+ left: 2px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+ right: 1px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+ left: 1px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+ clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+ float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+ float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+ border-right-width: 0;
+ border-left-width: 1px;
+}
+.ui-slider {
+ position: relative;
+ text-align: left;
+}
+.ui-slider .ui-slider-handle {
+ position: absolute;
+ z-index: 2;
+ width: 1.2em;
+ height: 1.2em;
+ cursor: default;
+}
+.ui-slider .ui-slider-range {
+ position: absolute;
+ z-index: 1;
+ font-size: .7em;
+ display: block;
+ border: 0;
+ background-position: 0 0;
+}
+
+/* For IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+ filter: inherit;
+}
+
+.ui-slider-horizontal {
+ height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+ top: -.3em;
+ margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+ top: 0;
+ height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+ left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+ right: 0;
+}
+
+.ui-slider-vertical {
+ width: .8em;
+ height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+ left: -.3em;
+ margin-left: 0;
+ margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+ left: 0;
+ width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+ bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+ top: 0;
+}
+.ui-spinner {
+ position: relative;
+ display: inline-block;
+ overflow: hidden;
+ padding: 0;
+ vertical-align: middle;
+}
+.ui-spinner-input {
+ border: none;
+ background: none;
+ color: inherit;
+ padding: 0;
+ margin: .2em 0;
+ vertical-align: middle;
+ margin-left: .4em;
+ margin-right: 22px;
+}
+.ui-spinner-button {
+ width: 16px;
+ height: 50%;
+ font-size: .5em;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+ position: absolute;
+ cursor: default;
+ display: block;
+ overflow: hidden;
+ right: 0;
+}
+/* more specificity required here to overide default borders */
+.ui-spinner a.ui-spinner-button {
+ border-top: none;
+ border-bottom: none;
+ border-right: none;
+}
+/* vertical centre icon */
+.ui-spinner .ui-icon {
+ position: absolute;
+ margin-top: -8px;
+ top: 50%;
+ left: 0;
+}
+.ui-spinner-up {
+ top: 0;
+}
+.ui-spinner-down {
+ bottom: 0;
+}
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+ /* need to fix icons sprite */
+ background-position: -65px -16px;
+}
+.ui-tabs {
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+ padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+ margin: 0;
+ padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+ list-style: none;
+ float: left;
+ position: relative;
+ top: 0;
+ margin: 1px .2em 0 0;
+ border-bottom-width: 0;
+ padding: 0;
+ white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav li a {
+ float: left;
+ padding: .5em 1em;
+ text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+ margin-bottom: -1px;
+ padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active a,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled a,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
+ cursor: text;
+}
+.ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
+ cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+ display: block;
+ border-width: 0;
+ padding: 1em 1.4em;
+ background: none;
+}
+.ui-tooltip {
+ padding: 8px;
+ position: absolute;
+ z-index: 9999;
+ max-width: 300px;
+ -webkit-box-shadow: 0 0 5px #aaa;
+ box-shadow: 0 0 5px #aaa;
+}
+body .ui-tooltip {
+ border-width: 2px;
+}
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+ font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
+ font-size: 1.1em;
+}
+.ui-widget .ui-widget {
+ font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+ font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
+ font-size: 1em;
+}
+.ui-widget-content {
+ border: 1px solid #dddddd;
+ background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;
+ color: #333333;
+}
+.ui-widget-content a {
+ color: #333333;
+}
+.ui-widget-header {
+ border: 1px solid #e78f08;
+ background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;
+ color: #ffffff;
+ font-weight: bold;
+}
+.ui-widget-header a {
+ color: #ffffff;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+ border: 1px solid #cccccc;
+ background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;
+ font-weight: bold;
+ color: #1c94c4;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+ color: #1c94c4;
+ text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+ border: 1px solid #fbcb09;
+ background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;
+ font-weight: bold;
+ color: #c77405;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited {
+ color: #c77405;
+ text-decoration: none;
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active {
+ border: 1px solid #fbd850;
+ background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;
+ font-weight: bold;
+ color: #eb8f00;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+ color: #eb8f00;
+ text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+ border: 1px solid #fed22f;
+ background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;
+ color: #363636;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+ color: #363636;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+ border: 1px solid #cd0a0a;
+ background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;
+ color: #ffffff;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+ color: #ffffff;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+ color: #ffffff;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+ font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+ opacity: .7;
+ filter:Alpha(Opacity=70);
+ font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+ opacity: .35;
+ filter:Alpha(Opacity=35);
+ background-image: none;
+}
+.ui-state-disabled .ui-icon {
+ filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ width: 16px;
+ height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+ background-image: url(images/ui-icons_222222_256x240.png);
+}
+.ui-widget-header .ui-icon {
+ background-image: url(images/ui-icons_ffffff_256x240.png);
+}
+.ui-state-default .ui-icon {
+ background-image: url(images/ui-icons_ef8c08_256x240.png);
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon {
+ background-image: url(images/ui-icons_ef8c08_256x240.png);
+}
+.ui-state-active .ui-icon {
+ background-image: url(images/ui-icons_ef8c08_256x240.png);
+}
+.ui-state-highlight .ui-icon {
+ background-image: url(images/ui-icons_228ef1_256x240.png);
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+ background-image: url(images/ui-icons_ffd27a_256x240.png);
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+ border-top-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+ border-top-right-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+ border-bottom-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+ border-bottom-right-radius: 4px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+ background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;
+ opacity: .5;
+ filter: Alpha(Opacity=50);
+}
+.ui-widget-shadow {
+ margin: -5px 0 0 -5px;
+ padding: 5px;
+ background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;
+ opacity: .2;
+ filter: Alpha(Opacity=20);
+ border-radius: 5px;
+}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.min.css b/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.min.css
new file mode 100755
index 0000000..ab5191b
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/jquery-ui-1.10.3.custom.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.10.3 - 2013-05-11
+* http://jqueryui.com
+* Includes: jquery.ui.core.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerd...
lorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
+* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:
middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.
ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepi
cker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane
{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepic
ker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-
disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:0;background:0;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner
a.ui-spinner-button{border-top:0;border-bottom:0;border-right:0}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0}.ui-tooltip{padding:8px;pos
ition:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-st
ate-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;backgr
ound:#ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header
.ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_228ef1_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-
32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32
px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-a
rrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position
:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui
-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calcul
ator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-i
con-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-s
tart{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}
.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position
:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.js
new file mode 100644
index 0000000..bc8f36a
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.js
@@ -0,0 +1,9597 @@
+/*!
+ * jQuery JavaScript Library v1.9.1
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2013-2-4
+ */
+(function( window, undefined ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//"use strict";
+ var
+ // The deferred used on DOM ready
+ readyList,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // Support: IE<9
+ // For `typeof node.method` instead of `node.method !== undefined`
+ core_strundefined = typeof undefined,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+ location = window.location,
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // [[Class]] -> type pairs
+ class2type = {},
+
+ // List of deleted data cache ids, so we can reuse them
+ core_deletedIds = [],
+
+ core_version = "1.9.1",
+
+ // Save a reference to some core methods
+ core_concat = core_deletedIds.concat,
+ core_push = core_deletedIds.push,
+ core_slice = core_deletedIds.slice,
+ core_indexOf = core_deletedIds.indexOf,
+ core_toString = class2type.toString,
+ core_hasOwn = class2type.hasOwnProperty,
+ core_trim = core_version.trim,
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Used for matching numbers
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
+
+ // Used for splitting on whitespace
+ core_rnotwhite = /\S+/g,
+
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ },
+
+ // The ready event handler
+ completed = function( event ) {
+
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+ detach();
+ jQuery.ready();
+ }
+ },
+ // Clean-up method for dom ready events
+ detach = function() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+
+ } else {
+ document.detachEvent( "onreadystatechange", completed );
+ window.detachEvent( "onload", completed );
+ }
+ };
+
+ jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: core_version,
+
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return core_slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+ },
+
+ slice: function() {
+ return this.pushStack( core_slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: core_push,
+ sort: [].sort,
+ splice: [].splice
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+ jQuery.fn.init.prototype = jQuery.fn;
+
+ jQuery.extend = jQuery.fn.extend = function() {
+ var src, copyIsArray, copy, name, options, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+ };
+
+ jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger("ready").off("ready");
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return String( obj );
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ core_toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !core_hasOwn.call(obj, "constructor") &&
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || core_hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ // data: string of html
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
+ // keepScripts (optional): If true, will include scripts passed in the html string
+ parseHTML: function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
+ if ( scripts ) {
+ jQuery( scripts ).remove();
+ }
+ return jQuery.merge( [], parsed.childNodes );
+ },
+
+ parseJSON: function( data ) {
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ if ( data === null ) {
+ return data;
+ }
+
+ if ( typeof data === "string" ) {
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ if ( data ) {
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+ }
+ }
+ }
+
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-...
+ globalEval: function( data ) {
+ if ( data && jQuery.trim( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+ function( text ) {
+ return text == null ?
+ "" :
+ core_trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ core_push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( core_indexOf ) {
+ return core_indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var l = second.length,
+ i = first.length,
+ j = 0;
+
+ if ( typeof l === "number" ) {
+ for ( ; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var retVal,
+ ret = [],
+ i = 0,
+ length = elems.length;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return core_concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var args, proxy, tmp;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = core_slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Multifunctional method to get and set values of a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ }
+ });
+
+ jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", completed );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", completed );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // detach all dom ready events
+ detach();
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+ };
+
+// Populate the class2type map
+ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+ });
+
+ function isArraylike( obj ) {
+ var length = obj.length,
+ type = jQuery.type( obj );
+
+ if ( jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || type !== "function" &&
+ ( length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
+ }
+
+// All jQuery objects should point back to these
+ rootjQuery = jQuery(document);
+// String to Object options format cache
+ var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+ function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+ }
+
+ /*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+ jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( list && ( !fired || stack ) ) {
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+ };
+ jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var action = tuple[ 0 ],
+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = core_slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+ if( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+ } else if ( !( --remaining ) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+ });
+ jQuery.support = (function() {
+
+ var support, all, a,
+ input, select, fragment,
+ opt, eventName, isSupported, i,
+ div = document.createElement("div");
+
+ // Setup
+ div.setAttribute( "className", "t" );
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+ // Support tests won't run in some limited or non-browser environments
+ all = div.getElementsByTagName("*");
+ a = div.getElementsByTagName("a")[ 0 ];
+ if ( !all || !a || !all.length ) {
+ return {};
+ }
+
+ // First batch of tests
+ select = document.createElement("select");
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName("input")[ 0 ];
+
+ a.style.cssText = "top:1px;float:left;opacity:.5";
+ support = {
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType === 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.5/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+ checkOn: !!input.value,
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Tests for enctype support on a form (#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
+ boxModel: document.compatMode === "CSS1Compat",
+
+ // Will be defined later
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true,
+ boxSizingReliable: true,
+ pixelPosition: false
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE<9
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ // Check if we can trust getAttribute("value")
+ input = document.createElement("input");
+ input.setAttribute( "value", "" );
+ support.input = input.getAttribute( "value" ) === "";
+
+ // Check if an input maintains its value after becoming a radio
+ input.value = "t";
+ input.setAttribute( "type", "radio" );
+ support.radioValue = input.value === "t";
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "checked", "t" );
+ input.setAttribute( "name", "t" );
+
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( input );
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<9
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+ if ( div.attachEvent ) {
+ div.attachEvent( "onclick", function() {
+ support.noCloneEvent = false;
+ });
+
+ div.cloneNode( true ).click();
+ }
+
+ // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
+ for ( i in { submit: true, change: true, focusin: true }) {
+ div.setAttribute( eventName = "on" + i, "t" );
+
+ support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
+ }
+
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, marginDiv, tds,
+ divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ container = document.createElement("div");
+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
+
+ body.appendChild( container ).appendChild( div );
+
+ // Support: IE8
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName("td");
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Support: IE8
+ // Check if empty table cells still have offsetWidth/Height
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Check box-sizing and margin behavior
+ div.innerHTML = "";
+ div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
+ support.boxSizing = ( div.offsetWidth === 4 );
+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
+
+ // Use window.getComputedStyle because jsdom on node.js will break without it.
+ if ( window.getComputedStyle ) {
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. (#3333)
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ marginDiv = div.appendChild( document.createElement("div") );
+ marginDiv.style.cssText = div.style.cssText = divReset;
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+
+ support.reliableMarginRight =
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+ }
+
+ if ( typeof div.style.zoom !== core_strundefined ) {
+ // Support: IE<8
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ div.innerHTML = "";
+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+ // Support: IE6
+ // Check if elements with layout shrink-wrap their children
+ div.style.display = "block";
+ div.innerHTML = "<div></div>";
+ div.firstChild.style.width = "5px";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+
+ if ( support.inlineBlockNeedsLayout ) {
+ // Prevent IE 6 from affecting layout for positioned elements #11048
+ // Prevent IE from shrinking the body in IE 7 mode #12869
+ // Support: IE<8
+ body.style.zoom = 1;
+ }
+ }
+
+ body.removeChild( container );
+
+ // Null elements to avoid leaks in IE
+ container = div = tds = marginDiv = null;
+ });
+
+ // Null elements to avoid leaks in IE
+ all = select = fragment = opt = a = input = null;
+
+ return support;
+ })();
+
+ var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+ function internalData( elem, name, data, pvt /* Internal Use Only */ ){
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+ }
+
+ function internalRemoveData( elem, name, pvt ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var i, l, thisCache,
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ } else {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+ }
+
+ jQuery.extend({
+ cache: {},
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return internalData( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ return internalRemoveData( elem, name );
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return internalData( elem, name, data, true );
+ },
+
+ _removeData: function( elem, name ) {
+ return internalRemoveData( elem, name, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ // Do not set data on non-element because it will not be cleared (#8335).
+ if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
+ return false;
+ }
+
+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ // nodes accept data unless otherwise specified; rejection can be conditional
+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
+ }
+ });
+
+ jQuery.fn.extend({
+ data: function( key, value ) {
+ var attrs, name,
+ elem = this[0],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ attrs = elem.attributes;
+ for ( ; i < attrs.length; i++ ) {
+ name = attrs[i].name;
+
+ if ( !name.indexOf( "data-" ) ) {
+ name = jQuery.camelCase( name.slice(5) );
+
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ return jQuery.access( this, function( value ) {
+
+ if ( value === undefined ) {
+ // Try to fetch any internally stored data first
+ return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
+ }
+
+ this.each(function() {
+ jQuery.data( this, key, value );
+ });
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+ });
+
+ function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+ }
+
+// checks a cache object for emptiness
+ function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ hooks.cur = fn;
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery._removeData( elem, type + "queue" );
+ jQuery._removeData( elem, key );
+ })
+ });
+ }
+ });
+
+ jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+ });
+ var nodeHook, boolHook,
+ rclass = /[\t\r\n]/g,
+ rreturn = /\r/g,
+ rfocusable = /^(?:input|select|textarea|button|object)$/i,
+ rclickable = /^(?:a|area)$/i,
+ rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
+ ruseDefault = /^(?:checked|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ getSetInput = jQuery.support.input;
+
+ jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
+ });
+ }
+
+ if ( proceed ) {
+ // The disjunction here is for better compressibility (see removeClass)
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " "
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+ elem.className = jQuery.trim( cur );
+
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = arguments.length === 0 || typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
+ });
+ }
+ if ( proceed ) {
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ ""
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+ elem.className = value ? jQuery.trim( cur ) : "";
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.match( core_rnotwhite ) || [];
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ // Toggle whole class name
+ } else if ( type === core_strundefined || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // If the element has a class name or if we're passed "false",
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var ret, hooks, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val,
+ self = jQuery(this);
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+ });
+
+ jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // oldIE doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+ // Don't return options that are disabled or in a disabled optgroup
+ ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attr: function( elem, name, value ) {
+ var hooks, notxml, ret,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === core_strundefined ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+
+ } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ // In IE9+, Flash objects don't have .getAttribute (#12945)
+ // Support: IE9+
+ if ( typeof elem.getAttribute !== core_strundefined ) {
+ ret = elem.getAttribute( name );
+ }
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( core_rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( (name = attrNames[i++]) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( rboolean.test( name ) ) {
+ // Set corresponding property to false for boolean attributes
+ // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
+ if ( !getSetAttribute && ruseDefault.test( name ) ) {
+ elem[ jQuery.camelCase( "default-" + name ) ] =
+ elem[ propName ] = false;
+ } else {
+ elem[ propName ] = false;
+ }
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ } else {
+ jQuery.attr( elem, name, "" );
+ }
+
+ elem.removeAttribute( getSetAttribute ? name : propName );
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to default in case type is set after value during creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabi...
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+ });
+
+// Hook for boolean attributes
+ boolHook = {
+ get: function( elem, name ) {
+ var
+ // Use .prop to determine if this attribute is understood as boolean
+ prop = jQuery.prop( elem, name ),
+
+ // Fetch it accordingly
+ attr = typeof prop === "boolean" && elem.getAttribute( name ),
+ detail = typeof prop === "boolean" ?
+
+ getSetInput && getSetAttribute ?
+ attr != null :
+ // oldIE fabricates an empty string for missing boolean attributes
+ // and conflates checked/selected into attroperties
+ ruseDefault.test( name ) ?
+ elem[ jQuery.camelCase( "default-" + name ) ] :
+ !!attr :
+
+ // fetch an attribute node for properties not recognized as boolean
+ elem.getAttributeNode( name );
+
+ return detail && detail.value !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ // IE<8 needs the *property* name
+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+ // Use defaultChecked and defaultSelected for oldIE
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+ }
+
+ return name;
+ }
+ };
+
+// fix oldIE value attroperty
+ if ( !getSetInput || !getSetAttribute ) {
+ jQuery.attrHooks.value = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return jQuery.nodeName( elem, "input" ) ?
+
+ // Ignore the value *property* by using defaultValue
+ elem.defaultValue :
+
+ ret && ret.specified ? ret.value : undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( jQuery.nodeName( elem, "input" ) ) {
+ // Does not return so that setAttribute is also used
+ elem.defaultValue = value;
+ } else {
+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
+ return nodeHook && nodeHook.set( elem, value, name );
+ }
+ }
+ };
+ }
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+ if ( !getSetAttribute ) {
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
+ ret.value :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ elem.setAttributeNode(
+ (ret = elem.ownerDocument.createAttribute( name ))
+ );
+ }
+
+ ret.value = value += "";
+
+ // Break association with cloned elements by also using setAttribute (#9646)
+ return name === "value" || value === elem.getAttribute( name ) ?
+ value :
+ undefined;
+ }
+ };
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ nodeHook.set( elem, value === "" ? false : value, name );
+ }
+ };
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+ }
+
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+ if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret == null ? undefined : ret;
+ }
+ });
+ });
+
+ // href/src property should get the full normalized URL (#10299/#12915)
+ jQuery.each([ "href", "src" ], function( i, name ) {
+ jQuery.propHooks[ name ] = {
+ get: function( elem ) {
+ return elem.getAttribute( name, 4 );
+ }
+ };
+ });
+ }
+
+ if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
+ return elem.style.cssText || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = value + "" );
+ }
+ };
+ }
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+ if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+// IE6/7 call enctype encoding
+ if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+ }
+
+// Radios and checkboxes getter/setter
+ if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+ }
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+ });
+ var rformElems = /^(?:input|select|textarea)$/i,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+ function returnTrue() {
+ return true;
+ }
+
+ function returnFalse() {
+ return false;
+ }
+
+ /*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+ jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+ var tmp, events, t, handleObjIn,
+ special, eventHandle, handleObj,
+ handlers, type, namespaces, origType,
+ elemData = jQuery._data( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+ var j, handleObj, tmp,
+ origCount, t, events,
+ special, handlers, type,
+ namespaces, origType,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery._removeData( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ var handle, ontype, cur,
+ bubbleType, special, tmp, i,
+ eventPath = [ elem || document ],
+ type = core_hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ event.isTrigger = true;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ try {
+ elem[ type ]();
+ } catch ( e ) {
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+ }
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, ret, handleObj, matched, j,
+ handlerQueue = [],
+ args = core_slice.call( arguments ),
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var sel, handleObj, matches, i,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+ for ( ; cur != this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, handlers: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ }
+
+ return handlerQueue;
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: IE<9
+ // Fix target property (#1925)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Support: Chrome 23+, Safari?
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Support: IE<9
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+ event.metaKey = !!event.metaKey;
+
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var body, eventDoc, doc,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ click: {
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+ this.click();
+ return false;
+ }
+ }
+ },
+ focus: {
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== document.activeElement && this.focus ) {
+ try {
+ this.focus();
+ return false;
+ } catch ( e ) {
+ // Support: IE<9
+ // If we error on focus to hidden element (#1486, #12518),
+ // let .trigger() run the handlers
+ }
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === document.activeElement && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Even when returnValue equals to undefined Firefox will still show alert
+ if ( event.result !== undefined ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+ };
+
+ jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ var name = "on" + type;
+
+ if ( elem.detachEvent ) {
+
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
+ if ( typeof elem[ name ] === core_strundefined ) {
+ elem[ name ] = null;
+ }
+
+ elem.detachEvent( name, handle );
+ }
+ };
+
+ jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+ };
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-bind...
+ jQuery.Event.prototype = {
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+ if ( !e ) {
+ return;
+ }
+
+ // If preventDefault exists, run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // Support: IE
+ // Otherwise set the returnValue property of the original event to false
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+ if ( !e ) {
+ return;
+ }
+ // If stopPropagation exists, run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+
+ // Support: IE
+ // Set the cancelBubble property of the original event to true
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ }
+ };
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+ jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+ }, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+ });
+
+// IE submit delegation
+ if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ jQuery._data( form, "submitBubbles", true );
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+ }
+
+// IE change delegation and checkbox/radio fix
+ if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ }
+ // Allow triggered, simulated change events (#11500)
+ jQuery.event.simulate( "change", this, event, true );
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ jQuery._data( elem, "changeBubbles", true );
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return !rformElems.test( this.nodeName );
+ }
+ };
+ }
+
+// Create "bubbling" focus and blur events
+ if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+ }
+
+ jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var type, origFn;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[0];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+ });
+ /*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://sizzlejs.com/
+ */
+ (function( window, undefined ) {
+
+ var i,
+ cachedruns,
+ Expr,
+ getText,
+ isXML,
+ compile,
+ hasDuplicate,
+ outermostContext,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsXML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+ sortOrder,
+
+ // Instance-specific data
+ expando = "sizzle" + -(new Date()),
+ preferredDoc = window.document,
+ support = {},
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+
+ // General-purpose constants
+ strundefined = typeof undefined,
+ MAX_NEGATIVE = 1 << 31,
+
+ // Array methods
+ arr = [],
+ pop = arr.pop,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf if we can't use a native one
+ indexOf = arr.indexOf || function( elem ) {
+ var i = 0,
+ len = this.length;
+ for ( ; i < len; i++ ) {
+ if ( this[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+ operators = "([*^$|!~]?=)",
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+ // Prefer arguments quoted,
+ // then not containing pseudos/brackets,
+ // then attribute selectors/non-parenthetical expressions,
+ // then anything else
+ // These preferences are here to reduce the number of selectors
+ // needing tokenize in the PSEUDO preFilter
+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rsibling = /[\x20\t\r\n\f]*[+~]/,
+
+ rnative = /^[^{]+\{\s*\[native code/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rescape = /'|\\/g,
+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
+ funescape = function( _, escaped ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ return high !== high ?
+ escaped :
+ // BMP codepoint
+ high < 0 ?
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ };
+
+// Use a stripped-down slice if we can't use a native one
+ try {
+ slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
+ } catch ( e ) {
+ slice = function( i ) {
+ var elem,
+ results = [];
+ while ( (elem = this[i++]) ) {
+ results.push( elem );
+ }
+ return results;
+ };
+ }
+
+ /**
+ * For feature detection
+ * @param {Function} fn The function to test for native support
+ */
+ function isNative( fn ) {
+ return rnative.test( fn + "" );
+ }
+
+ /**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+ function createCache() {
+ var cache,
+ keys = [];
+
+ return (cache = function( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key ] = value);
+ });
+ }
+
+ /**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+ function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+ }
+
+ /**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+ function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // release memory in IE
+ div = null;
+ }
+ }
+
+ function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !documentIsXML && !seed ) {
+
+ // Shortcuts
+ if ( (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && !rbuggyQSA.test(selector) ) {
+ old = true;
+ nid = expando;
+ newContext = context;
+ newSelector = nodeType === 9 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && context.parentNode || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results, slice.call( newContext.querySelectorAll(
+ newSelector
+ ), 0 ) );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+ }
+
+ /**
+ * Detect xml
+ * @param {Element|Object} elem An element or a document
+ */
+ isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+ };
+
+ /**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+ setDocument = Sizzle.setDocument = function( node ) {
+ var doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+
+ // Support tests
+ documentIsXML = isXML( doc );
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.tagNameNoComments = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Check if attributes should be retrieved by attribute nodes
+ support.attributes = assert(function( div ) {
+ div.innerHTML = "<select></select>";
+ var type = typeof div.lastChild.getAttribute("multiple");
+ // IE8 returns a string for some attributes even when not present
+ return type !== "boolean" && type !== "string";
+ });
+
+ // Check if getElementsByClassName can be trusted
+ support.getByClassName = assert(function( div ) {
+ // Opera can't find a second classname (in 9.6)
+ div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
+ return false;
+ }
+
+ // Safari 3.2 caches class attributes and doesn't catch changes
+ div.lastChild.className = "e";
+ return div.getElementsByClassName("e").length === 2;
+ });
+
+ // Check if getElementById returns elements by name
+ // Check if getElementsByName privileges form controls or returns elements by ID
+ support.getByName = assert(function( div ) {
+ // Inject content
+ div.id = expando + 0;
+ div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
+ docElem.insertBefore( div, docElem.firstChild );
+
+ // Test
+ var pass = doc.getElementsByName &&
+ // buggy browsers will return fewer than the correct 2
+ doc.getElementsByName( expando ).length === 2 +
+ // buggy browsers will return more than the correct 0
+ doc.getElementsByName( expando + 0 ).length;
+ support.getIdNotName = !doc.getElementById( expando );
+
+ // Cleanup
+ docElem.removeChild( div );
+
+ return pass;
+ });
+
+ // IE6/7 return modified attributes
+ Expr.attrHandle = assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
+ div.firstChild.getAttribute("href") === "#";
+ }) ?
+ {} :
+ {
+ "href": function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ },
+ "type": function( elem ) {
+ return elem.getAttribute("type");
+ }
+ };
+
+ // ID find and filter
+ if ( support.getIdNotName ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+
+ return m ?
+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.tagNameNoComments ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== strundefined ) {
+ return context.getElementsByTagName( tag );
+ }
+ } :
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Name
+ Expr.find["NAME"] = support.getByName && function( tag, context ) {
+ if ( typeof context.getElementsByName !== strundefined ) {
+ return context.getElementsByName( name );
+ }
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21),
+ // no need to also add to buggyMatches since matches checks buggyQSA
+ // A support test would require too much code (would include document ready)
+ rbuggyQSA = [ ":focus" ];
+
+ if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explictly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = "<select><option selected=''></option></select>";
+
+ // IE8 - Some boolean attributes are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+ });
+
+ assert(function( div ) {
+
+ // Opera 10-12/IE8 - ^= $= *= and empty values
+ // Should not select anything
+ div.innerHTML = "<input type='hidden' i=''/>";
+ if ( div.querySelectorAll("[i^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.webkitMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ // Document order sorting
+ sortOrder = docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var compare;
+
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
+ if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
+ if ( a === doc || contains( preferredDoc, a ) ) {
+ return -1;
+ }
+ if ( b === doc || contains( preferredDoc, b ) ) {
+ return 1;
+ }
+ return 0;
+ }
+ return compare & 4 ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition ? -1 : 1;
+ } :
+ function( a, b ) {
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Parentless nodes are either documents or disconnected
+ } else if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ // Always assume the presence of duplicates if sort doesn't
+ // pass them to our comparison function (as in Google Chrome).
+ hasDuplicate = false;
+ [0, 0].sort( sortOrder );
+ support.detectDuplicates = hasDuplicate;
+
+ return document;
+ };
+
+ Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+ };
+
+ Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ // rbuggyQSA always contains :focus, so no need for an existence check
+ if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle( expr, document, null, [elem] ).length > 0;
+ };
+
+ Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+ };
+
+ Sizzle.attr = function( elem, name ) {
+ var val;
+
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ if ( !documentIsXML ) {
+ name = name.toLowerCase();
+ }
+ if ( (val = Expr.attrHandle[ name ]) ) {
+ return val( elem );
+ }
+ if ( documentIsXML || support.attributes ) {
+ return elem.getAttribute( name );
+ }
+ return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
+ name :
+ val && val.specified ? val.value : null;
+ };
+
+ Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+ };
+
+// Document sorting and removing duplicates
+ Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ i = 1,
+ j = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( ; (elem = results[i]); i++ ) {
+ if ( elem === results[ i - 1 ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ return results;
+ };
+
+ function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+ }
+
+// Returns a function to use in pseudos for input types
+ function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+ }
+
+// Returns a function to use in pseudos for buttons
+ function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+ }
+
+// Returns a function to use in pseudos for positionals
+ function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+ }
+
+ /**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+ getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ for ( ; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (see #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+ };
+
+ Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[5] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[4] ) {
+ match[2] = match[4];
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeName ) {
+ if ( nodeName === "*" ) {
+ return function() { return true; };
+ }
+
+ nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf.call( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifider
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsXML ?
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
+ elem.lang) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+ // not comment, processing instructions, or others
+ // Thanks to Diego Perini for the nodeName shortcut
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+ };
+
+// Add button/input type pseudos
+ for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+ }
+ for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+ }
+
+ function tokenize( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( tokens = [] );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ type: type,
+ matches: match
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+ }
+
+ function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+ }
+
+ function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var data, cache, outerCache,
+ dirkey = dirruns + " " + doneName;
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
+ if ( (data = cache[1]) === true || data === cachedruns ) {
+ return data === true;
+ }
+ } else {
+ cache = outerCache[ dir ] = [ dirkey ];
+ cache[1] = matcher( elem, context, xml ) || cachedruns;
+ if ( cache[1] === true ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+
+ function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+ }
+
+ function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+ }
+
+ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+ }
+
+ function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf.call( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+ }
+
+ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ // A counter to specify which element is currently being matched
+ var matcherCachedRuns = 0,
+ bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, expandContext ) {
+ var elem, j, matcher,
+ setMatched = [],
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ outermost = expandContext != null,
+ contextBackup = outermostContext,
+ // We must always have either seed elements or context
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ cachedruns = matcherCachedRuns;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ cachedruns = ++matcherCachedRuns;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+ }
+
+ compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !group ) {
+ group = tokenize( selector );
+ }
+ i = group.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( group[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+ }
+ return cached;
+ };
+
+ function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+ }
+
+ function select( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ match = tokenize( selector );
+
+ if ( !seed ) {
+ // Try to minimize operations if there is only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ context.nodeType === 9 && !documentIsXML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
+ if ( !context ) {
+ return results;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && context.parentNode || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, slice.call( seed, 0 ) );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function
+ // Provide `match` to avoid retokenization if we modified the selector above
+ compile( selector, match )(
+ seed,
+ context,
+ documentIsXML,
+ results,
+ rsibling.test( selector )
+ );
+ return results;
+ }
+
+// Deprecated
+ Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Easy API for creating new setFilters
+ function setFilters() {}
+ Expr.filters = setFilters.prototype = Expr.pseudos;
+ Expr.setFilters = new setFilters();
+
+// Initialize with the default document
+ setDocument();
+
+// Override sizzle attribute retrieval
+ Sizzle.attr = jQuery.attr;
+ jQuery.find = Sizzle;
+ jQuery.expr = Sizzle.selectors;
+ jQuery.expr[":"] = jQuery.expr.pseudos;
+ jQuery.unique = Sizzle.uniqueSort;
+ jQuery.text = Sizzle.getText;
+ jQuery.isXMLDoc = Sizzle.isXML;
+ jQuery.contains = Sizzle.contains;
+
+
+ })( window );
+ var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ rneedsContext = jQuery.expr.match.needsContext,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+ jQuery.fn.extend({
+ find: function( selector ) {
+ var i, ret, self,
+ len = this.length;
+
+ if ( typeof selector !== "string" ) {
+ self = this;
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ ret = [];
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, this[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
+ return ret;
+ },
+
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false) );
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true) );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ rneedsContext.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ ret = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+ }
+ cur = cur.parentNode;
+ }
+ }
+
+ return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( jQuery.unique(all) );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+ });
+
+ jQuery.fn.andSelf = jQuery.fn.addBack;
+
+ function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+ }
+
+ jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+ }, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( this.length > 1 && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret );
+ };
+ });
+
+ jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+ });
+
+// Implement the identical functionality for filter and not
+ function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+ }
+ function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+ }
+
+ var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style|link)/i,
+ manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /^$|\/(?:java|ecma)script/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+ // We have to close these tags to support XHTML (#13200)
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ area: [ 1, "<map>", "</map>" ],
+ param: [ 1, "<object>", "</object>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+ // unless wrapped in a div with non-breaking characters in front of it.
+ _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
+ },
+ safeFragment = createSafeFragment( document ),
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+ wrapMap.optgroup = wrapMap.option;
+ wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+ wrapMap.th = wrapMap.td;
+
+ jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ });
+ },
+
+ after: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ });
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem ) );
+ }
+
+ if ( elem.parentNode ) {
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+ setGlobalEval( getAll( elem, "script" ) );
+ }
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+
+ // If this is a select, ensure that it displays empty (#12336)
+ // Support: IE<9
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+ elem.options.length = 0;
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[0] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ undefined;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function( value ) {
+ var isFunc = jQuery.isFunction( value );
+
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( !isFunc && typeof value !== "string" ) {
+ value = jQuery( value ).not( this ).detach();
+ }
+
+ return this.domManip( [ value ], true, function( elem ) {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ if ( parent ) {
+ jQuery( this ).remove();
+ parent.insertBefore( elem, next );
+ }
+ });
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+
+ // Flatten any nested arrays
+ args = core_concat.apply( [], args );
+
+ var first, node, hasScripts,
+ scripts, doc, fragment,
+ i = 0,
+ l = this.length,
+ set = this,
+ iNoClone = l - 1,
+ value = args[0],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
+ return this.each(function( index ) {
+ var self = set.eq( index );
+ if ( isFunction ) {
+ args[0] = value.call( this, index, table ? self.html() : undefined );
+ }
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( l ) {
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call(
+ table && jQuery.nodeName( this[i], "table" ) ?
+ findOrAppend( this[i], "tbody" ) :
+ this[i],
+ node,
+ i
+ );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+ // Hope ajax is available...
+ jQuery.ajax({
+ url: node.src,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+ } else {
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+
+ // Fix #11809: Avoid leaking memory
+ fragment = first = null;
+ }
+ }
+
+ return this;
+ }
+ });
+
+ function findOrAppend( elem, tag ) {
+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
+ }
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+ function disableScript( elem ) {
+ var attr = elem.getAttributeNode("type");
+ elem.type = ( attr && attr.specified ) + "/" + elem.type;
+ return elem;
+ }
+ function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+ if ( match ) {
+ elem.type = match[1];
+ } else {
+ elem.removeAttribute("type");
+ }
+ return elem;
+ }
+
+// Mark scripts as having already been evaluated
+ function setGlobalEval( elems, refElements ) {
+ var elem,
+ i = 0;
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+ }
+ }
+
+ function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+ }
+
+ function fixCloneNodeIssues( src, dest ) {
+ var nodeName, e, data;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
+ if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
+ data = jQuery._data( dest );
+
+ for ( e in data.events ) {
+ jQuery.removeEvent( dest, e, data.handle );
+ }
+
+ // Event data gets referenced instead of copied if the expando gets copied too
+ dest.removeAttribute( jQuery.expando );
+ }
+
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+ if ( nodeName === "script" && dest.text !== src.text ) {
+ disableScript( dest ).text = src.text;
+ restoreScript( dest );
+
+ // IE6-10 improperly clones children of object elements using classid.
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
+ } else if ( nodeName === "object" ) {
+ if ( dest.parentNode ) {
+ dest.outerHTML = src.outerHTML;
+ }
+
+ // This path appears unavoidable for IE9. When cloning an object
+ // element in IE9, the outerHTML strategy above is not sufficient.
+ // If the src has innerHTML and the destination does not,
+ // copy the src.innerHTML into the dest.innerHTML. #10324
+ if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+ dest.innerHTML = src.innerHTML;
+ }
+
+ } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+
+ dest.defaultChecked = dest.checked = src.checked;
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.defaultSelected = dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+ }
+
+ jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+ }, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ i = 0,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone(true);
+ jQuery( insert[i] )[ original ]( elems );
+
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+ core_push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+ });
+
+ function getAll( context, tag ) {
+ var elems, elem,
+ i = 0,
+ found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
+ undefined;
+
+ if ( !found ) {
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
+ found.push( elem );
+ } else {
+ jQuery.merge( found, getAll( elem, tag ) );
+ }
+ }
+ }
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], found ) :
+ found;
+ }
+
+// Used in buildFragment, fixes the defaultChecked property
+ function fixDefaultChecked( elem ) {
+ if ( manipulation_rcheckableType.test( elem.type ) ) {
+ elem.defaultChecked = elem.checked;
+ }
+ }
+
+ jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var destElements, node, clone, i, srcElements,
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+ clone = elem.cloneNode( true );
+
+ // IE<=8 does not properly clone detached, unknown element nodes
+ } else {
+ fragmentDiv.innerHTML = elem.outerHTML;
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ }
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ // Fix all IE cloning issues
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ fixCloneNodeIssues( node, destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+ cloneCopyEvent( node, destElements[i] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ destElements = srcElements = node = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ buildFragment: function( elems, context, scripts, selection ) {
+ var j, elem, contains,
+ tmp, tag, tbody, wrap,
+ l = elems.length,
+
+ // Ensure a safe fragment
+ safe = createSafeFragment( context ),
+
+ nodes = [],
+ i = 0;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || safe.appendChild( context.createElement("div") );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+ // Descend through wrappers to the right content
+ j = wrap[0];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Manually add leading whitespace removed by IE
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ elem = tag === "table" && !rtbody.test( elem ) ?
+ tmp.firstChild :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
+ tmp :
+ 0;
+
+ j = elem && elem.childNodes.length;
+ while ( j-- ) {
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+ elem.removeChild( tbody );
+ }
+ }
+ }
+
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Fix #12392 for WebKit and IE > 9
+ tmp.textContent = "";
+
+ // Fix #12392 for oldIE
+ while ( tmp.firstChild ) {
+ tmp.removeChild( tmp.firstChild );
+ }
+
+ // Remember the top-level container for proper cleanup
+ tmp = safe.lastChild;
+ }
+ }
+ }
+
+ // Fix #11356: Clear elements from fragment
+ if ( tmp ) {
+ safe.removeChild( tmp );
+ }
+
+ // Reset defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ if ( !jQuery.support.appendChecked ) {
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+ }
+
+ i = 0;
+ while ( (elem = nodes[ i++ ]) ) {
+
+ // #4087 - If origin and destination elements are the same, and this is
+ // that element, do not do anything
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( safe.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( (elem = tmp[ j++ ]) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ tmp = null;
+
+ return safe;
+ },
+
+ cleanData: function( elems, /* internal */ acceptData ) {
+ var elem, type, id, data,
+ i = 0,
+ internalKey = jQuery.expando,
+ cache = jQuery.cache,
+ deleteExpando = jQuery.support.deleteExpando,
+ special = jQuery.event.special;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+
+ if ( acceptData || jQuery.acceptData( elem ) ) {
+
+ id = elem[ internalKey ];
+ data = id && cache[ id ];
+
+ if ( data ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Remove cache only if it was not already removed by jQuery.event.remove
+ if ( cache[ id ] ) {
+
+ delete cache[ id ];
+
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( deleteExpando ) {
+ delete elem[ internalKey ];
+
+ } else if ( typeof elem.removeAttribute !== core_strundefined ) {
+ elem.removeAttribute( internalKey );
+
+ } else {
+ elem[ internalKey ] = null;
+ }
+
+ core_deletedIds.push( id );
+ }
+ }
+ }
+ }
+ }
+ });
+ var iframe, getStyles, curCSS,
+ ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity\s*=\s*([^)]*)/,
+ rposition = /^(top|right|bottom|left)$/,
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rmargin = /^margin/,
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
+ elemdisplay = { BODY: "block" },
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: 0,
+ fontWeight: 400
+ },
+
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+// return a css property mapped to a potentially vendor prefixed property
+ function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+ }
+
+ function isHidden( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+ }
+
+ function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = jQuery._data( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+ }
+ } else {
+
+ if ( !values[ index ] ) {
+ hidden = isHidden( elem );
+
+ if ( display && display !== "none" || !hidden ) {
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+ }
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+ }
+
+ jQuery.fn.extend({
+ css: function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ var len, styles,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ var bool = typeof state === "boolean";
+
+ return this.each(function() {
+ if ( bool ? state : isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+ });
+
+ jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "columnCount": true,
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+ // but it would mean to define eight (for every problematic property) identical functions
+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var num, val, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ }
+ });
+
+// NOTE: we've included the "window" in window.getComputedStyle
+// because jsdom on node.js will break without it.
+ if ( window.getComputedStyle ) {
+ getStyles = function( elem ) {
+ return window.getComputedStyle( elem, null );
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var width, minWidth, maxWidth,
+ computed = _computed || getStyles( elem ),
+
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
+ style = elem.style;
+
+ if ( computed ) {
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret;
+ };
+ } else if ( document.documentElement.currentStyle ) {
+ getStyles = function( elem ) {
+ return elem.currentStyle;
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var left, rs, rsLeft,
+ computed = _computed || getStyles( elem ),
+ ret = computed ? computed[ name ] : undefined,
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && style[ name ] ) {
+ ret = style[ name ];
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ // but not position css attributes, as those are proportional to the parent element instead
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rs = elem.runtimeStyle;
+ rsLeft = rs && rs.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ rs.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ rs.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+ }
+
+ function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+ }
+
+ function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+ }
+
+ function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+ }
+
+// Try to determine the default display value of an element
+ function css_defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+ // Use the already-created iframe if possible
+ iframe = ( iframe ||
+ jQuery("<iframe frameborder='0' width='0' height='0'/>")
+ .css( "cssText", "display:block !important" )
+ ).appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
+ doc.write("<!doctype html><html><body>");
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+ }
+
+// Called ONLY from within css_defaultDisplay
+ function actualDisplay( name, doc ) {
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+ display = jQuery.css( elem[0], "display" );
+ elem.remove();
+ return display;
+ }
+
+ jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
+ jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ }) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var styles = extra && getStyles( elem );
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ ) : 0
+ );
+ }
+ };
+ });
+
+ if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ // if value === "", then remove inline opacity #12685
+ if ( ( value >= 1 || value === "" ) &&
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+ style.removeAttribute ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+ }
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+ jQuery(function() {
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+ };
+ }
+
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+ // getComputedStyle returns percent when specified for top/left/bottom/right
+ // rather than make the css module depend on the offset module, we just check for it here
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ };
+ });
+ }
+
+ });
+
+ if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+ (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+ }
+
+// These hooks are used by animate to expand properties
+ jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+ }, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+ });
+ var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+ jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ })
+ .filter(function(){
+ var type = this.type;
+ // Use .is(":disabled") so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !manipulation_rcheckableType.test( type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+ });
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+ jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+ };
+
+ function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+ }
+ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+ });
+
+ jQuery.fn.hover = function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ };
+ var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+ ajax_nonce = jQuery.now(),
+
+ ajax_rquery = /\?/,
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+ try {
+ ajaxLocation = location.href;
+ } catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+ }
+
+// Segment location into parts
+ ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+ function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+ // For each dataType in the dataTypeExpression
+ while ( (dataType = dataTypes[i++]) ) {
+ // Prepend if requested
+ if ( dataType[0] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+ // Otherwise append
+ } else {
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ }
+ }
+ }
+ };
+ }
+
+// Base inspection function for prefilters and transports
+ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ });
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+ }
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+ function ajaxExtend( target, src ) {
+ var deep, key,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+ }
+
+ jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, response, type,
+ self = this,
+ off = url.indexOf(" ");
+
+ if ( off >= 0 ) {
+ selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax({
+ url: url,
+
+ // if "type" variable is undefined, then "GET" method will be used
+ type: type,
+ dataType: "html",
+ data: params
+ }).done(function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+ };
+
+// Attach a bunch of functions for handling common AJAX events
+ jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
+ jQuery.fn[ type ] = function( fn ){
+ return this.on( type, fn );
+ };
+ });
+
+ jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+ });
+
+ jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Cross-domain detection vars
+ parts,
+ // Loop variable
+ i,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers as string
+ responseHeadersString,
+ // timeout handle
+ timeoutTimer,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ transport,
+ // Response headers
+ responseHeaders,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 ) {
+ isSuccess = true;
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ isSuccess = true;
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ isSuccess = ajaxConvert( s, response );
+ statusText = isSuccess.state;
+ success = isSuccess.data;
+ error = isSuccess.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ }
+ });
+
+ /* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+ function ajaxHandleResponses( s, jqXHR, responses ) {
+ var firstDataType, ct, finalDataType, type,
+ contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+ }
+
+// Chain conversions given the request and the original response
+ function ajaxConvert( s, response ) {
+ var conv2, current, conv, tmp,
+ converters = {},
+ i = 0,
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice(),
+ prev = dataTypes[ 0 ];
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ // Convert to each sequential dataType, tolerating list modification
+ for ( ; (current = dataTypes[++i]); ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current !== "*" ) {
+
+ // Convert response if prev dataType is non-auto and differs from current
+ if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split(" ");
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.splice( i--, 0, current );
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s["throws"] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+
+ // Update prev for next iteration
+ prev = current;
+ }
+ }
+
+ return { state: "success", data: response };
+ }
+// Install script dataType
+ jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+ });
+
+// Handle cache's special case and global
+ jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+ });
+
+// Bind script tag hack transport
+ jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || jQuery("head")[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement("script");
+
+ script.async = true;
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( script.parentNode ) {
+ script.parentNode.removeChild( script );
+ }
+
+ // Dereference the script
+ script = null;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( undefined, true );
+ }
+ }
+ };
+ }
+ });
+ var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+ jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+ });
+
+// Detect, normalize options and install callbacks for jsonp requests
+ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+ });
+ var xhrCallbacks, xhrSupported,
+ xhrId = 0,
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject && function() {
+ // Abort all pending requests
+ var key;
+ for ( key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( undefined, true );
+ }
+ };
+
+// Functions to create xhrs
+ function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+ }
+
+ function createActiveXHR() {
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch( e ) {}
+ }
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+ jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+ xhrSupported = jQuery.ajaxSettings.xhr();
+ jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+ xhrSupported = jQuery.support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+ if ( xhrSupported ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var handle, i,
+ xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( err ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+ var status, responseHeaders, statusText, responses;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occurred
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:...
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ responses = {};
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+
+ // When requesting binary data, IE6-9 will throw an exception
+ // on any attempt to access responseText (#11426)
+ if ( typeof xhr.responseText === "string" ) {
+ responses.text = xhr.responseText;
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ if ( !s.async ) {
+ // if we're in sync mode we fire the callback
+ callback();
+ } else if ( xhr.readyState === 4 ) {
+ // (IE6 & IE7) if it's in cache and has been
+ // retrieved directly we need to fire the callback
+ setTimeout( callback );
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback( undefined, true );
+ }
+ }
+ };
+ }
+ });
+ }
+ var fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [function( prop, value ) {
+ var end, unit,
+ tween = this.createTween( prop, value ),
+ parts = rfxnum.exec( value ),
+ target = tween.cur(),
+ start = +target || 0,
+ scale = 1,
+ maxIterations = 20;
+
+ if ( parts ) {
+ end = +parts[2];
+ unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" && start ) {
+ // Iteratively approximate from a nonzero starting point
+ // Prefer the current property, because this process will be trivial if it uses the same units
+ // Fallback to end or a simple constant
+ start = jQuery.css( tween.elem, prop, true ) || end || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ tween.unit = unit;
+ tween.start = start;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
+ }
+ return tween;
+ }]
+ };
+
+// Animations created synchronously will run synchronously
+ function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+ }
+
+ function createTweens( animation, props ) {
+ jQuery.each( props, function( prop, value ) {
+ var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( collection[ index ].call( animation, prop, value ) ) {
+
+ // we're done with this property
+ return;
+ }
+ }
+ });
+ }
+
+ function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ createTweens( animation, props );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+ }
+
+ function propFilter( props, specialEasing ) {
+ var value, name, index, easing, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+ }
+
+ jQuery.Animation = jQuery.extend( Animation, {
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+ });
+
+ function defaultPrefilter( elem, props, opts ) {
+ /*jshint validthis:true */
+ var prop, index, length,
+ value, dataShow, toggle,
+ tween, hooks, oldfire,
+ anim = this,
+ style = elem.style,
+ orig = {},
+ handled = [],
+ hidden = elem.nodeType && isHidden( elem );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( elem, "display" ) === "inline" &&
+ jQuery.css( elem, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
+ style.display = "inline-block";
+
+ } else {
+ style.zoom = 1;
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ if ( !jQuery.support.shrinkWrapBlocks ) {
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+ }
+
+
+ // show/hide pass
+ for ( index in props ) {
+ value = props[ index ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ index ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+ continue;
+ }
+ handled.push( index );
+ }
+ }
+
+ length = handled.length;
+ if ( length ) {
+ dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+ jQuery._removeData( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( index = 0 ; index < length ; index++ ) {
+ prop = handled[ index ];
+ tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
+ orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+ }
+ }
+
+ function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+ }
+ jQuery.Tween = Tween;
+
+ Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+ };
+
+ Tween.prototype.init.prototype = Tween.prototype;
+
+ Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+ };
+
+// Remove in 2.0 - this supports IE8's panic based approach
+// to setting things on disconnected nodes
+
+ Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ };
+
+ jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+ });
+
+ jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+ doAnimation.finish = function() {
+ anim.stop( true );
+ };
+ // Empty animations, or finishing resolves immediately
+ if ( empty || jQuery._data( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = jQuery._data( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.cur && hooks.cur.finish ) {
+ hooks.cur.finish.call( this );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+ });
+
+// Generate parameters to create a standard animation
+ function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth? 1 : 0;
+ for( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+ }
+
+// Generate shortcuts for custom animations
+ jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+ }, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+ });
+
+ jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+ };
+
+ jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
+ }
+ };
+
+ jQuery.timers = [];
+ jQuery.fx = Tween.prototype.init;
+ jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+ };
+
+ jQuery.fx.timer = function( timer ) {
+ if ( timer() && jQuery.timers.push( timer ) ) {
+ jQuery.fx.start();
+ }
+ };
+
+ jQuery.fx.interval = 13;
+
+ jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+ };
+
+ jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+ };
+
+ jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ };
+
+// Back Compat <1.8 extension point
+ jQuery.fx.step = {};
+
+ if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+ }
+ jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+ };
+
+ jQuery.offset = {
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+ };
+
+
+ jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.documentElement;
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || document.documentElement;
+ });
+ }
+ });
+
+
+// Create scrollLeft and scrollTop methods
+ jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+ });
+
+ function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+ }
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return jQuery.access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+ });
+// Limit scope pollution from any deprecated API
+// (function() {
+
+// })();
+// Expose jQuery to the global object
+ window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+ }
+
+})( window );
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.min.js
new file mode 100644
index 0000000..5d9ee08
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.9.1.min.js
@@ -0,0 +1,5 @@
+/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
+ //@ sourceMappingURL=jquery.min.map
+ */(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==
typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.cont
ext,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s}
,b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:functi
on(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){ret
urn e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0
,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventLis
tener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u
&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory
"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r)
{t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.ge
tAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.clon
eNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-b
ox-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e
,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object
:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},rem
oveData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._
removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disab
led|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))
return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e
){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val()
,o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},pro
pFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.
propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.
getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}
function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null
}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.
indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&
&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==
e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"butto
n buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result
!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault(
):e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
+ return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)})
,b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.exten
d({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate
:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp
("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}functi
on it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[
id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getB
yName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e
.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").l
ength&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compare
DocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.s
pecified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}
else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];
return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];
while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return
(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:
function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(
s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s
=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(nul
l,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);
return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e)
{var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:
function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)
},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.gre
p(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</
fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wr
apInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},rem
ove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&
this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.te
st(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(
t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a])
;a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._def
ault,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
+}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-
])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){
for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||
b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=f
unction(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.bo
xSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.f
ilter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width
"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};i
f(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEA
D)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),
b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},con
verters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:functi
on(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("I
f-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C
="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.d
ataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.chars
et=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e
[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[
s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?
s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=
l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p(
)}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="wi
dth"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step
[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),th
is.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},functio
n(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slo
w:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left
=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or
(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.js
new file mode 100755
index 0000000..453f99f
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.js
@@ -0,0 +1,6253 @@
+/*! jQuery UI - v1.10.3 - 2013-05-11
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
+* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
+
+(function( $, undefined ) {
+
+var uuid = 0,
+ runiqueId = /^ui-id-\d+$/;
+
+// $.ui might exist from components with no dependencies, e.g., $.ui.position
+$.ui = $.ui || {};
+
+$.extend( $.ui, {
+ version: "1.10.3",
+
+ keyCode: {
+ BACKSPACE: 8,
+ COMMA: 188,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ LEFT: 37,
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38
+ }
+});
+
+// plugins
+$.fn.extend({
+ focus: (function( orig ) {
+ return function( delay, fn ) {
+ return typeof delay === "number" ?
+ this.each(function() {
+ var elem = this;
+ setTimeout(function() {
+ $( elem ).focus();
+ if ( fn ) {
+ fn.call( elem );
+ }
+ }, delay );
+ }) :
+ orig.apply( this, arguments );
+ };
+ })( $.fn.focus ),
+
+ scrollParent: function() {
+ var scrollParent;
+ if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
+ scrollParent = this.parents().filter(function() {
+ return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
+ }).eq(0);
+ } else {
+ scrollParent = this.parents().filter(function() {
+ return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
+ }).eq(0);
+ }
+
+ return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
+ },
+
+ zIndex: function( zIndex ) {
+ if ( zIndex !== undefined ) {
+ return this.css( "zIndex", zIndex );
+ }
+
+ if ( this.length ) {
+ var elem = $( this[ 0 ] ), position, value;
+ while ( elem.length && elem[ 0 ] !== document ) {
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
+ // This makes behavior of this function consistent across browsers
+ // WebKit always returns auto if the element is positioned
+ position = elem.css( "position" );
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
+ // IE returns 0 when zIndex is not specified
+ // other browsers return a string
+ // we ignore the case of nested elements with an explicit value of 0
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
+ value = parseInt( elem.css( "zIndex" ), 10 );
+ if ( !isNaN( value ) && value !== 0 ) {
+ return value;
+ }
+ }
+ elem = elem.parent();
+ }
+ }
+
+ return 0;
+ },
+
+ uniqueId: function() {
+ return this.each(function() {
+ if ( !this.id ) {
+ this.id = "ui-id-" + (++uuid);
+ }
+ });
+ },
+
+ removeUniqueId: function() {
+ return this.each(function() {
+ if ( runiqueId.test( this.id ) ) {
+ $( this ).removeAttr( "id" );
+ }
+ });
+ }
+});
+
+// selectors
+function focusable( element, isTabIndexNotNaN ) {
+ var map, mapName, img,
+ nodeName = element.nodeName.toLowerCase();
+ if ( "area" === nodeName ) {
+ map = element.parentNode;
+ mapName = map.name;
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
+ return false;
+ }
+ img = $( "img[usemap=#" + mapName + "]" )[0];
+ return !!img && visible( img );
+ }
+ return ( /input|select|textarea|button|object/.test( nodeName ) ?
+ !element.disabled :
+ "a" === nodeName ?
+ element.href || isTabIndexNotNaN :
+ isTabIndexNotNaN) &&
+ // the element and all of its ancestors must be visible
+ visible( element );
+}
+
+function visible( element ) {
+ return $.expr.filters.visible( element ) &&
+ !$( element ).parents().addBack().filter(function() {
+ return $.css( this, "visibility" ) === "hidden";
+ }).length;
+}
+
+$.extend( $.expr[ ":" ], {
+ data: $.expr.createPseudo ?
+ $.expr.createPseudo(function( dataName ) {
+ return function( elem ) {
+ return !!$.data( elem, dataName );
+ };
+ }) :
+ // support: jQuery <1.8
+ function( elem, i, match ) {
+ return !!$.data( elem, match[ 3 ] );
+ },
+
+ focusable: function( element ) {
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
+ },
+
+ tabbable: function( element ) {
+ var tabIndex = $.attr( element, "tabindex" ),
+ isTabIndexNaN = isNaN( tabIndex );
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
+ }
+});
+
+// support: jQuery <1.8
+if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
+ $.each( [ "Width", "Height" ], function( i, name ) {
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
+ type = name.toLowerCase(),
+ orig = {
+ innerWidth: $.fn.innerWidth,
+ innerHeight: $.fn.innerHeight,
+ outerWidth: $.fn.outerWidth,
+ outerHeight: $.fn.outerHeight
+ };
+
+ function reduce( elem, size, border, margin ) {
+ $.each( side, function() {
+ size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
+ if ( border ) {
+ size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
+ }
+ if ( margin ) {
+ size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
+ }
+ });
+ return size;
+ }
+
+ $.fn[ "inner" + name ] = function( size ) {
+ if ( size === undefined ) {
+ return orig[ "inner" + name ].call( this );
+ }
+
+ return this.each(function() {
+ $( this ).css( type, reduce( this, size ) + "px" );
+ });
+ };
+
+ $.fn[ "outer" + name] = function( size, margin ) {
+ if ( typeof size !== "number" ) {
+ return orig[ "outer" + name ].call( this, size );
+ }
+
+ return this.each(function() {
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
+ });
+ };
+ });
+}
+
+// support: jQuery <1.8
+if ( !$.fn.addBack ) {
+ $.fn.addBack = function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter( selector )
+ );
+ };
+}
+
+// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
+if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
+ $.fn.removeData = (function( removeData ) {
+ return function( key ) {
+ if ( arguments.length ) {
+ return removeData.call( this, $.camelCase( key ) );
+ } else {
+ return removeData.call( this );
+ }
+ };
+ })( $.fn.removeData );
+}
+
+
+
+
+
+// deprecated
+$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
+
+$.support.selectstart = "onselectstart" in document.createElement( "div" );
+$.fn.extend({
+ disableSelection: function() {
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
+ ".ui-disableSelection", function( event ) {
+ event.preventDefault();
+ });
+ },
+
+ enableSelection: function() {
+ return this.unbind( ".ui-disableSelection" );
+ }
+});
+
+$.extend( $.ui, {
+ // $.ui.plugin is deprecated. Use $.widget() extensions instead.
+ plugin: {
+ add: function( module, option, set ) {
+ var i,
+ proto = $.ui[ module ].prototype;
+ for ( i in set ) {
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
+ }
+ },
+ call: function( instance, name, args ) {
+ var i,
+ set = instance.plugins[ name ];
+ if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
+ return;
+ }
+
+ for ( i = 0; i < set.length; i++ ) {
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
+ set[ i ][ 1 ].apply( instance.element, args );
+ }
+ }
+ }
+ },
+
+ // only used by resizable
+ hasScroll: function( el, a ) {
+
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
+ if ( $( el ).css( "overflow" ) === "hidden") {
+ return false;
+ }
+
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
+ has = false;
+
+ if ( el[ scroll ] > 0 ) {
+ return true;
+ }
+
+ // TODO: determine which cases actually cause this to happen
+ // if the element doesn't have the scroll set, see if it's possible to
+ // set the scroll
+ el[ scroll ] = 1;
+ has = ( el[ scroll ] > 0 );
+ el[ scroll ] = 0;
+ return has;
+ }
+});
+
+})( jQuery );
+(function( $, undefined ) {
+
+var uuid = 0,
+ slice = Array.prototype.slice,
+ _cleanData = $.cleanData;
+$.cleanData = function( elems ) {
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ try {
+ $( elem ).triggerHandler( "remove" );
+ // http://bugs.jquery.com/ticket/8235
+ } catch( e ) {}
+ }
+ _cleanData( elems );
+};
+
+$.widget = function( name, base, prototype ) {
+ var fullName, existingConstructor, constructor, basePrototype,
+ // proxiedPrototype allows the provided prototype to remain unmodified
+ // so that it can be used as a mixin for multiple widgets (#8876)
+ proxiedPrototype = {},
+ namespace = name.split( "." )[ 0 ];
+
+ name = name.split( "." )[ 1 ];
+ fullName = namespace + "-" + name;
+
+ if ( !prototype ) {
+ prototype = base;
+ base = $.Widget;
+ }
+
+ // create selector for plugin
+ $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
+ return !!$.data( elem, fullName );
+ };
+
+ $[ namespace ] = $[ namespace ] || {};
+ existingConstructor = $[ namespace ][ name ];
+ constructor = $[ namespace ][ name ] = function( options, element ) {
+ // allow instantiation without "new" keyword
+ if ( !this._createWidget ) {
+ return new constructor( options, element );
+ }
+
+ // allow instantiation without initializing for simple inheritance
+ // must use "new" keyword (the code above always passes args)
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+ };
+ // extend with the existing constructor to carry over any static properties
+ $.extend( constructor, existingConstructor, {
+ version: prototype.version,
+ // copy the object used to create the prototype in case we need to
+ // redefine the widget later
+ _proto: $.extend( {}, prototype ),
+ // track widgets that inherit from this widget in case this widget is
+ // redefined after a widget inherits from it
+ _childConstructors: []
+ });
+
+ basePrototype = new base();
+ // we need to make the options hash a property directly on the new instance
+ // otherwise we'll modify the options hash on the prototype that we're
+ // inheriting from
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
+ $.each( prototype, function( prop, value ) {
+ if ( !$.isFunction( value ) ) {
+ proxiedPrototype[ prop ] = value;
+ return;
+ }
+ proxiedPrototype[ prop ] = (function() {
+ var _super = function() {
+ return base.prototype[ prop ].apply( this, arguments );
+ },
+ _superApply = function( args ) {
+ return base.prototype[ prop ].apply( this, args );
+ };
+ return function() {
+ var __super = this._super,
+ __superApply = this._superApply,
+ returnValue;
+
+ this._super = _super;
+ this._superApply = _superApply;
+
+ returnValue = value.apply( this, arguments );
+
+ this._super = __super;
+ this._superApply = __superApply;
+
+ return returnValue;
+ };
+ })();
+ });
+ constructor.prototype = $.widget.extend( basePrototype, {
+ // TODO: remove support for widgetEventPrefix
+ // always use the name + a colon as the prefix, e.g., draggable:start
+ // don't prefix for widgets that aren't DOM-based
+ widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
+ }, proxiedPrototype, {
+ constructor: constructor,
+ namespace: namespace,
+ widgetName: name,
+ widgetFullName: fullName
+ });
+
+ // If this widget is being redefined then we need to find all widgets that
+ // are inheriting from it and redefine all of them so that they inherit from
+ // the new version of this widget. We're essentially trying to replace one
+ // level in the prototype chain.
+ if ( existingConstructor ) {
+ $.each( existingConstructor._childConstructors, function( i, child ) {
+ var childPrototype = child.prototype;
+
+ // redefine the child widget using the same prototype that was
+ // originally used, but inherit from the new version of the base
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
+ });
+ // remove the list of existing child constructors from the old constructor
+ // so the old child constructors can be garbage collected
+ delete existingConstructor._childConstructors;
+ } else {
+ base._childConstructors.push( constructor );
+ }
+
+ $.widget.bridge( name, constructor );
+};
+
+$.widget.extend = function( target ) {
+ var input = slice.call( arguments, 1 ),
+ inputIndex = 0,
+ inputLength = input.length,
+ key,
+ value;
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
+ for ( key in input[ inputIndex ] ) {
+ value = input[ inputIndex ][ key ];
+ if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
+ // Clone objects
+ if ( $.isPlainObject( value ) ) {
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
+ $.widget.extend( {}, target[ key ], value ) :
+ // Don't extend strings, arrays, etc. with objects
+ $.widget.extend( {}, value );
+ // Copy everything else by reference
+ } else {
+ target[ key ] = value;
+ }
+ }
+ }
+ }
+ return target;
+};
+
+$.widget.bridge = function( name, object ) {
+ var fullName = object.prototype.widgetFullName || name;
+ $.fn[ name ] = function( options ) {
+ var isMethodCall = typeof options === "string",
+ args = slice.call( arguments, 1 ),
+ returnValue = this;
+
+ // allow multiple hashes to be passed on init
+ options = !isMethodCall && args.length ?
+ $.widget.extend.apply( null, [ options ].concat(args) ) :
+ options;
+
+ if ( isMethodCall ) {
+ this.each(function() {
+ var methodValue,
+ instance = $.data( this, fullName );
+ if ( !instance ) {
+ return $.error( "cannot call methods on " + name + " prior to initialization; " +
+ "attempted to call method '" + options + "'" );
+ }
+ if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
+ return $.error( "no such method '" + options + "' for " + name + " widget instance" );
+ }
+ methodValue = instance[ options ].apply( instance, args );
+ if ( methodValue !== instance && methodValue !== undefined ) {
+ returnValue = methodValue && methodValue.jquery ?
+ returnValue.pushStack( methodValue.get() ) :
+ methodValue;
+ return false;
+ }
+ });
+ } else {
+ this.each(function() {
+ var instance = $.data( this, fullName );
+ if ( instance ) {
+ instance.option( options || {} )._init();
+ } else {
+ $.data( this, fullName, new object( options, this ) );
+ }
+ });
+ }
+
+ return returnValue;
+ };
+};
+
+$.Widget = function( /* options, element */ ) {};
+$.Widget._childConstructors = [];
+
+$.Widget.prototype = {
+ widgetName: "widget",
+ widgetEventPrefix: "",
+ defaultElement: "<div>",
+ options: {
+ disabled: false,
+
+ // callbacks
+ create: null
+ },
+ _createWidget: function( options, element ) {
+ element = $( element || this.defaultElement || this )[ 0 ];
+ this.element = $( element );
+ this.uuid = uuid++;
+ this.eventNamespace = "." + this.widgetName + this.uuid;
+ this.options = $.widget.extend( {},
+ this.options,
+ this._getCreateOptions(),
+ options );
+
+ this.bindings = $();
+ this.hoverable = $();
+ this.focusable = $();
+
+ if ( element !== this ) {
+ $.data( element, this.widgetFullName, this );
+ this._on( true, this.element, {
+ remove: function( event ) {
+ if ( event.target === element ) {
+ this.destroy();
+ }
+ }
+ });
+ this.document = $( element.style ?
+ // element within the document
+ element.ownerDocument :
+ // element is window or document
+ element.document || element );
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
+ }
+
+ this._create();
+ this._trigger( "create", null, this._getCreateEventData() );
+ this._init();
+ },
+ _getCreateOptions: $.noop,
+ _getCreateEventData: $.noop,
+ _create: $.noop,
+ _init: $.noop,
+
+ destroy: function() {
+ this._destroy();
+ // we can probably remove the unbind calls in 2.0
+ // all event bindings should go through this._on()
+ this.element
+ .unbind( this.eventNamespace )
+ // 1.9 BC for #7810
+ // TODO remove dual storage
+ .removeData( this.widgetName )
+ .removeData( this.widgetFullName )
+ // support: jquery <1.6.3
+ // http://bugs.jquery.com/ticket/9413
+ .removeData( $.camelCase( this.widgetFullName ) );
+ this.widget()
+ .unbind( this.eventNamespace )
+ .removeAttr( "aria-disabled" )
+ .removeClass(
+ this.widgetFullName + "-disabled " +
+ "ui-state-disabled" );
+
+ // clean up events and states
+ this.bindings.unbind( this.eventNamespace );
+ this.hoverable.removeClass( "ui-state-hover" );
+ this.focusable.removeClass( "ui-state-focus" );
+ },
+ _destroy: $.noop,
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key,
+ parts,
+ curOption,
+ i;
+
+ if ( arguments.length === 0 ) {
+ // don't return a reference to the internal hash
+ return $.widget.extend( {}, this.options );
+ }
+
+ if ( typeof key === "string" ) {
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+ options = {};
+ parts = key.split( "." );
+ key = parts.shift();
+ if ( parts.length ) {
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
+ for ( i = 0; i < parts.length - 1; i++ ) {
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
+ curOption = curOption[ parts[ i ] ];
+ }
+ key = parts.pop();
+ if ( value === undefined ) {
+ return curOption[ key ] === undefined ? null : curOption[ key ];
+ }
+ curOption[ key ] = value;
+ } else {
+ if ( value === undefined ) {
+ return this.options[ key ] === undefined ? null : this.options[ key ];
+ }
+ options[ key ] = value;
+ }
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+ _setOptions: function( options ) {
+ var key;
+
+ for ( key in options ) {
+ this._setOption( key, options[ key ] );
+ }
+
+ return this;
+ },
+ _setOption: function( key, value ) {
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this.widget()
+ .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
+ .attr( "aria-disabled", value );
+ this.hoverable.removeClass( "ui-state-hover" );
+ this.focusable.removeClass( "ui-state-focus" );
+ }
+
+ return this;
+ },
+
+ enable: function() {
+ return this._setOption( "disabled", false );
+ },
+ disable: function() {
+ return this._setOption( "disabled", true );
+ },
+
+ _on: function( suppressDisabledCheck, element, handlers ) {
+ var delegateElement,
+ instance = this;
+
+ // no suppressDisabledCheck flag, shuffle arguments
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
+ handlers = element;
+ element = suppressDisabledCheck;
+ suppressDisabledCheck = false;
+ }
+
+ // no element argument, shuffle and use this.element
+ if ( !handlers ) {
+ handlers = element;
+ element = this.element;
+ delegateElement = this.widget();
+ } else {
+ // accept selectors, DOM elements
+ element = delegateElement = $( element );
+ this.bindings = this.bindings.add( element );
+ }
+
+ $.each( handlers, function( event, handler ) {
+ function handlerProxy() {
+ // allow widgets to customize the disabled handling
+ // - disabled as an array instead of boolean
+ // - disabled class as method for disabling individual parts
+ if ( !suppressDisabledCheck &&
+ ( instance.options.disabled === true ||
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
+ return;
+ }
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+
+ // copy the guid so direct unbinding works
+ if ( typeof handler !== "string" ) {
+ handlerProxy.guid = handler.guid =
+ handler.guid || handlerProxy.guid || $.guid++;
+ }
+
+ var match = event.match( /^(\w+)\s*(.*)$/ ),
+ eventName = match[1] + instance.eventNamespace,
+ selector = match[2];
+ if ( selector ) {
+ delegateElement.delegate( selector, eventName, handlerProxy );
+ } else {
+ element.bind( eventName, handlerProxy );
+ }
+ });
+ },
+
+ _off: function( element, eventName ) {
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
+ element.unbind( eventName ).undelegate( eventName );
+ },
+
+ _delay: function( handler, delay ) {
+ function handlerProxy() {
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+ var instance = this;
+ return setTimeout( handlerProxy, delay || 0 );
+ },
+
+ _hoverable: function( element ) {
+ this.hoverable = this.hoverable.add( element );
+ this._on( element, {
+ mouseenter: function( event ) {
+ $( event.currentTarget ).addClass( "ui-state-hover" );
+ },
+ mouseleave: function( event ) {
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
+ }
+ });
+ },
+
+ _focusable: function( element ) {
+ this.focusable = this.focusable.add( element );
+ this._on( element, {
+ focusin: function( event ) {
+ $( event.currentTarget ).addClass( "ui-state-focus" );
+ },
+ focusout: function( event ) {
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
+ }
+ });
+ },
+
+ _trigger: function( type, event, data ) {
+ var prop, orig,
+ callback = this.options[ type ];
+
+ data = data || {};
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ // the original event may come from any element
+ // so we need to reset the target on the new event
+ event.target = this.element[ 0 ];
+
+ // copy original event properties over to the new event
+ orig = event.originalEvent;
+ if ( orig ) {
+ for ( prop in orig ) {
+ if ( !( prop in event ) ) {
+ event[ prop ] = orig[ prop ];
+ }
+ }
+ }
+
+ this.element.trigger( event, data );
+ return !( $.isFunction( callback ) &&
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
+ if ( typeof options === "string" ) {
+ options = { effect: options };
+ }
+ var hasOptions,
+ effectName = !options ?
+ method :
+ options === true || typeof options === "number" ?
+ defaultEffect :
+ options.effect || defaultEffect;
+ options = options || {};
+ if ( typeof options === "number" ) {
+ options = { duration: options };
+ }
+ hasOptions = !$.isEmptyObject( options );
+ options.complete = callback;
+ if ( options.delay ) {
+ element.delay( options.delay );
+ }
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
+ element[ method ]( options );
+ } else if ( effectName !== method && element[ effectName ] ) {
+ element[ effectName ]( options.duration, options.easing, callback );
+ } else {
+ element.queue(function( next ) {
+ $( this )[ method ]();
+ if ( callback ) {
+ callback.call( element[ 0 ] );
+ }
+ next();
+ });
+ }
+ };
+});
+
+})( jQuery );
+(function( $, undefined ) {
+
+var mouseHandled = false;
+$( document ).mouseup( function() {
+ mouseHandled = false;
+});
+
+$.widget("ui.mouse", {
+ version: "1.10.3",
+ options: {
+ cancel: "input,textarea,button,select,option",
+ distance: 1,
+ delay: 0
+ },
+ _mouseInit: function() {
+ var that = this;
+
+ this.element
+ .bind("mousedown."+this.widgetName, function(event) {
+ return that._mouseDown(event);
+ })
+ .bind("click."+this.widgetName, function(event) {
+ if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
+ $.removeData(event.target, that.widgetName + ".preventClickEvent");
+ event.stopImmediatePropagation();
+ return false;
+ }
+ });
+
+ this.started = false;
+ },
+
+ // TODO: make sure destroying one instance of mouse doesn't mess with
+ // other instances of mouse
+ _mouseDestroy: function() {
+ this.element.unbind("."+this.widgetName);
+ if ( this._mouseMoveDelegate ) {
+ $(document)
+ .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
+ .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
+ }
+ },
+
+ _mouseDown: function(event) {
+ // don't let more than one widget handle mouseStart
+ if( mouseHandled ) { return; }
+
+ // we may have missed mouseup (out of window)
+ (this._mouseStarted && this._mouseUp(event));
+
+ this._mouseDownEvent = event;
+
+ var that = this,
+ btnIsLeft = (event.which === 1),
+ // event.target.nodeName works around a bug in IE 8 with
+ // disabled inputs (#7620)
+ elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+ return true;
+ }
+
+ this.mouseDelayMet = !this.options.delay;
+ if (!this.mouseDelayMet) {
+ this._mouseDelayTimer = setTimeout(function() {
+ that.mouseDelayMet = true;
+ }, this.options.delay);
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted = (this._mouseStart(event) !== false);
+ if (!this._mouseStarted) {
+ event.preventDefault();
+ return true;
+ }
+ }
+
+ // Click event may never have fired (Gecko & Opera)
+ if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
+ $.removeData(event.target, this.widgetName + ".preventClickEvent");
+ }
+
+ // these delegates are required to keep context
+ this._mouseMoveDelegate = function(event) {
+ return that._mouseMove(event);
+ };
+ this._mouseUpDelegate = function(event) {
+ return that._mouseUp(event);
+ };
+ $(document)
+ .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
+ .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
+
+ event.preventDefault();
+
+ mouseHandled = true;
+ return true;
+ },
+
+ _mouseMove: function(event) {
+ // IE mouseup check - mouseup happened when mouse was out of window
+ if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
+ return this._mouseUp(event);
+ }
+
+ if (this._mouseStarted) {
+ this._mouseDrag(event);
+ return event.preventDefault();
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted =
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+ }
+
+ return !this._mouseStarted;
+ },
+
+ _mouseUp: function(event) {
+ $(document)
+ .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
+ .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
+
+ if (this._mouseStarted) {
+ this._mouseStarted = false;
+
+ if (event.target === this._mouseDownEvent.target) {
+ $.data(event.target, this.widgetName + ".preventClickEvent", true);
+ }
+
+ this._mouseStop(event);
+ }
+
+ return false;
+ },
+
+ _mouseDistanceMet: function(event) {
+ return (Math.max(
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
+ ) >= this.options.distance
+ );
+ },
+
+ _mouseDelayMet: function(/* event */) {
+ return this.mouseDelayMet;
+ },
+
+ // These are placeholder methods, to be overriden by extending plugin
+ _mouseStart: function(/* event */) {},
+ _mouseDrag: function(/* event */) {},
+ _mouseStop: function(/* event */) {},
+ _mouseCapture: function(/* event */) { return true; }
+});
+
+})(jQuery);
+(function( $, undefined ) {
+
+$.ui = $.ui || {};
+
+var cachedScrollbarWidth,
+ max = Math.max,
+ abs = Math.abs,
+ round = Math.round,
+ rhorizontal = /left|center|right/,
+ rvertical = /top|center|bottom/,
+ roffset = /[\+\-]\d+(\.[\d]+)?%?/,
+ rposition = /^\w+/,
+ rpercent = /%$/,
+ _position = $.fn.position;
+
+function getOffsets( offsets, width, height ) {
+ return [
+ parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
+ parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
+ ];
+}
+
+function parseCss( element, property ) {
+ return parseInt( $.css( element, property ), 10 ) || 0;
+}
+
+function getDimensions( elem ) {
+ var raw = elem[0];
+ if ( raw.nodeType === 9 ) {
+ return {
+ width: elem.width(),
+ height: elem.height(),
+ offset: { top: 0, left: 0 }
+ };
+ }
+ if ( $.isWindow( raw ) ) {
+ return {
+ width: elem.width(),
+ height: elem.height(),
+ offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
+ };
+ }
+ if ( raw.preventDefault ) {
+ return {
+ width: 0,
+ height: 0,
+ offset: { top: raw.pageY, left: raw.pageX }
+ };
+ }
+ return {
+ width: elem.outerWidth(),
+ height: elem.outerHeight(),
+ offset: elem.offset()
+ };
+}
+
+$.position = {
+ scrollbarWidth: function() {
+ if ( cachedScrollbarWidth !== undefined ) {
+ return cachedScrollbarWidth;
+ }
+ var w1, w2,
+ div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
+ innerDiv = div.children()[0];
+
+ $( "body" ).append( div );
+ w1 = innerDiv.offsetWidth;
+ div.css( "overflow", "scroll" );
+
+ w2 = innerDiv.offsetWidth;
+
+ if ( w1 === w2 ) {
+ w2 = div[0].clientWidth;
+ }
+
+ div.remove();
+
+ return (cachedScrollbarWidth = w1 - w2);
+ },
+ getScrollInfo: function( within ) {
+ var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
+ overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
+ hasOverflowX = overflowX === "scroll" ||
+ ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
+ hasOverflowY = overflowY === "scroll" ||
+ ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
+ return {
+ width: hasOverflowY ? $.position.scrollbarWidth() : 0,
+ height: hasOverflowX ? $.position.scrollbarWidth() : 0
+ };
+ },
+ getWithinInfo: function( element ) {
+ var withinElement = $( element || window ),
+ isWindow = $.isWindow( withinElement[0] );
+ return {
+ element: withinElement,
+ isWindow: isWindow,
+ offset: withinElement.offset() || { left: 0, top: 0 },
+ scrollLeft: withinElement.scrollLeft(),
+ scrollTop: withinElement.scrollTop(),
+ width: isWindow ? withinElement.width() : withinElement.outerWidth(),
+ height: isWindow ? withinElement.height() : withinElement.outerHeight()
+ };
+ }
+};
+
+$.fn.position = function( options ) {
+ if ( !options || !options.of ) {
+ return _position.apply( this, arguments );
+ }
+
+ // make a copy, we don't want to modify arguments
+ options = $.extend( {}, options );
+
+ var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
+ target = $( options.of ),
+ within = $.position.getWithinInfo( options.within ),
+ scrollInfo = $.position.getScrollInfo( within ),
+ collision = ( options.collision || "flip" ).split( " " ),
+ offsets = {};
+
+ dimensions = getDimensions( target );
+ if ( target[0].preventDefault ) {
+ // force left top to allow flipping
+ options.at = "left top";
+ }
+ targetWidth = dimensions.width;
+ targetHeight = dimensions.height;
+ targetOffset = dimensions.offset;
+ // clone to reuse original targetOffset later
+ basePosition = $.extend( {}, targetOffset );
+
+ // force my and at to have valid horizontal and vertical positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each( [ "my", "at" ], function() {
+ var pos = ( options[ this ] || "" ).split( " " ),
+ horizontalOffset,
+ verticalOffset;
+
+ if ( pos.length === 1) {
+ pos = rhorizontal.test( pos[ 0 ] ) ?
+ pos.concat( [ "center" ] ) :
+ rvertical.test( pos[ 0 ] ) ?
+ [ "center" ].concat( pos ) :
+ [ "center", "center" ];
+ }
+ pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
+ pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
+
+ // calculate offsets
+ horizontalOffset = roffset.exec( pos[ 0 ] );
+ verticalOffset = roffset.exec( pos[ 1 ] );
+ offsets[ this ] = [
+ horizontalOffset ? horizontalOffset[ 0 ] : 0,
+ verticalOffset ? verticalOffset[ 0 ] : 0
+ ];
+
+ // reduce to just the positions without the offsets
+ options[ this ] = [
+ rposition.exec( pos[ 0 ] )[ 0 ],
+ rposition.exec( pos[ 1 ] )[ 0 ]
+ ];
+ });
+
+ // normalize collision option
+ if ( collision.length === 1 ) {
+ collision[ 1 ] = collision[ 0 ];
+ }
+
+ if ( options.at[ 0 ] === "right" ) {
+ basePosition.left += targetWidth;
+ } else if ( options.at[ 0 ] === "center" ) {
+ basePosition.left += targetWidth / 2;
+ }
+
+ if ( options.at[ 1 ] === "bottom" ) {
+ basePosition.top += targetHeight;
+ } else if ( options.at[ 1 ] === "center" ) {
+ basePosition.top += targetHeight / 2;
+ }
+
+ atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
+ basePosition.left += atOffset[ 0 ];
+ basePosition.top += atOffset[ 1 ];
+
+ return this.each(function() {
+ var collisionPosition, using,
+ elem = $( this ),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ marginLeft = parseCss( this, "marginLeft" ),
+ marginTop = parseCss( this, "marginTop" ),
+ collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
+ collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
+ position = $.extend( {}, basePosition ),
+ myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
+
+ if ( options.my[ 0 ] === "right" ) {
+ position.left -= elemWidth;
+ } else if ( options.my[ 0 ] === "center" ) {
+ position.left -= elemWidth / 2;
+ }
+
+ if ( options.my[ 1 ] === "bottom" ) {
+ position.top -= elemHeight;
+ } else if ( options.my[ 1 ] === "center" ) {
+ position.top -= elemHeight / 2;
+ }
+
+ position.left += myOffset[ 0 ];
+ position.top += myOffset[ 1 ];
+
+ // if the browser doesn't support fractions, then round for consistent results
+ if ( !$.support.offsetFractions ) {
+ position.left = round( position.left );
+ position.top = round( position.top );
+ }
+
+ collisionPosition = {
+ marginLeft: marginLeft,
+ marginTop: marginTop
+ };
+
+ $.each( [ "left", "top" ], function( i, dir ) {
+ if ( $.ui.position[ collision[ i ] ] ) {
+ $.ui.position[ collision[ i ] ][ dir ]( position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ collisionPosition: collisionPosition,
+ collisionWidth: collisionWidth,
+ collisionHeight: collisionHeight,
+ offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
+ my: options.my,
+ at: options.at,
+ within: within,
+ elem : elem
+ });
+ }
+ });
+
+ if ( options.using ) {
+ // adds feedback as second argument to using callback, if present
+ using = function( props ) {
+ var left = targetOffset.left - position.left,
+ right = left + targetWidth - elemWidth,
+ top = targetOffset.top - position.top,
+ bottom = top + targetHeight - elemHeight,
+ feedback = {
+ target: {
+ element: target,
+ left: targetOffset.left,
+ top: targetOffset.top,
+ width: targetWidth,
+ height: targetHeight
+ },
+ element: {
+ element: elem,
+ left: position.left,
+ top: position.top,
+ width: elemWidth,
+ height: elemHeight
+ },
+ horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
+ vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
+ };
+ if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
+ feedback.horizontal = "center";
+ }
+ if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
+ feedback.vertical = "middle";
+ }
+ if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
+ feedback.important = "horizontal";
+ } else {
+ feedback.important = "vertical";
+ }
+ options.using.call( this, props, feedback );
+ };
+ }
+
+ elem.offset( $.extend( position, { using: using } ) );
+ });
+};
+
+$.ui.position = {
+ fit: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
+ outerWidth = within.width,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = withinOffset - collisionPosLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
+ newOverRight;
+
+ // element is wider than within
+ if ( data.collisionWidth > outerWidth ) {
+ // element is initially over the left side of within
+ if ( overLeft > 0 && overRight <= 0 ) {
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
+ position.left += overLeft - newOverRight;
+ // element is initially over right side of within
+ } else if ( overRight > 0 && overLeft <= 0 ) {
+ position.left = withinOffset;
+ // element is initially over both left and right sides of within
+ } else {
+ if ( overLeft > overRight ) {
+ position.left = withinOffset + outerWidth - data.collisionWidth;
+ } else {
+ position.left = withinOffset;
+ }
+ }
+ // too far left -> align with left edge
+ } else if ( overLeft > 0 ) {
+ position.left += overLeft;
+ // too far right -> align with right edge
+ } else if ( overRight > 0 ) {
+ position.left -= overRight;
+ // adjust based on position and margin
+ } else {
+ position.left = max( position.left - collisionPosLeft, position.left );
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
+ outerHeight = data.within.height,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = withinOffset - collisionPosTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
+ newOverBottom;
+
+ // element is taller than within
+ if ( data.collisionHeight > outerHeight ) {
+ // element is initially over the top of within
+ if ( overTop > 0 && overBottom <= 0 ) {
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
+ position.top += overTop - newOverBottom;
+ // element is initially over bottom of within
+ } else if ( overBottom > 0 && overTop <= 0 ) {
+ position.top = withinOffset;
+ // element is initially over both top and bottom of within
+ } else {
+ if ( overTop > overBottom ) {
+ position.top = withinOffset + outerHeight - data.collisionHeight;
+ } else {
+ position.top = withinOffset;
+ }
+ }
+ // too far up -> align with top
+ } else if ( overTop > 0 ) {
+ position.top += overTop;
+ // too far down -> align with bottom edge
+ } else if ( overBottom > 0 ) {
+ position.top -= overBottom;
+ // adjust based on position and margin
+ } else {
+ position.top = max( position.top - collisionPosTop, position.top );
+ }
+ }
+ },
+ flip: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.left + within.scrollLeft,
+ outerWidth = within.width,
+ offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = collisionPosLeft - offsetLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
+ myOffset = data.my[ 0 ] === "left" ?
+ -data.elemWidth :
+ data.my[ 0 ] === "right" ?
+ data.elemWidth :
+ 0,
+ atOffset = data.at[ 0 ] === "left" ?
+ data.targetWidth :
+ data.at[ 0 ] === "right" ?
+ -data.targetWidth :
+ 0,
+ offset = -2 * data.offset[ 0 ],
+ newOverRight,
+ newOverLeft;
+
+ if ( overLeft < 0 ) {
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
+ if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ }
+ else if ( overRight > 0 ) {
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
+ if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.top + within.scrollTop,
+ outerHeight = within.height,
+ offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = collisionPosTop - offsetTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
+ top = data.my[ 1 ] === "top",
+ myOffset = top ?
+ -data.elemHeight :
+ data.my[ 1 ] === "bottom" ?
+ data.elemHeight :
+ 0,
+ atOffset = data.at[ 1 ] === "top" ?
+ data.targetHeight :
+ data.at[ 1 ] === "bottom" ?
+ -data.targetHeight :
+ 0,
+ offset = -2 * data.offset[ 1 ],
+ newOverTop,
+ newOverBottom;
+ if ( overTop < 0 ) {
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
+ if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ }
+ else if ( overBottom > 0 ) {
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
+ if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ }
+ }
+ },
+ flipfit: {
+ left: function() {
+ $.ui.position.flip.left.apply( this, arguments );
+ $.ui.position.fit.left.apply( this, arguments );
+ },
+ top: function() {
+ $.ui.position.flip.top.apply( this, arguments );
+ $.ui.position.fit.top.apply( this, arguments );
+ }
+ }
+};
+
+// fraction support test
+(function () {
+ var testElement, testElementParent, testElementStyle, offsetLeft, i,
+ body = document.getElementsByTagName( "body" )[ 0 ],
+ div = document.createElement( "div" );
+
+ //Create a "fake body" for testing based on method used in jQuery.support
+ testElement = document.createElement( body ? "div" : "body" );
+ testElementStyle = {
+ visibility: "hidden",
+ width: 0,
+ height: 0,
+ border: 0,
+ margin: 0,
+ background: "none"
+ };
+ if ( body ) {
+ $.extend( testElementStyle, {
+ position: "absolute",
+ left: "-1000px",
+ top: "-1000px"
+ });
+ }
+ for ( i in testElementStyle ) {
+ testElement.style[ i ] = testElementStyle[ i ];
+ }
+ testElement.appendChild( div );
+ testElementParent = body || document.documentElement;
+ testElementParent.insertBefore( testElement, testElementParent.firstChild );
+
+ div.style.cssText = "position: absolute; left: 10.7432222px;";
+
+ offsetLeft = $( div ).offset().left;
+ $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
+
+ testElement.innerHTML = "";
+ testElementParent.removeChild( testElement );
+})();
+
+}( jQuery ) );
+(function( $, undefined ) {
+
+var lastActive, startXPos, startYPos, clickDragged,
+ baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
+ stateClasses = "ui-state-hover ui-state-active ",
+ typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
+ formResetHandler = function() {
+ var form = $( this );
+ setTimeout(function() {
+ form.find( ":ui-button" ).button( "refresh" );
+ }, 1 );
+ },
+ radioGroup = function( radio ) {
+ var name = radio.name,
+ form = radio.form,
+ radios = $( [] );
+ if ( name ) {
+ name = name.replace( /'/g, "\\'" );
+ if ( form ) {
+ radios = $( form ).find( "[name='" + name + "']" );
+ } else {
+ radios = $( "[name='" + name + "']", radio.ownerDocument )
+ .filter(function() {
+ return !this.form;
+ });
+ }
+ }
+ return radios;
+ };
+
+$.widget( "ui.button", {
+ version: "1.10.3",
+ defaultElement: "<button>",
+ options: {
+ disabled: null,
+ text: true,
+ label: null,
+ icons: {
+ primary: null,
+ secondary: null
+ }
+ },
+ _create: function() {
+ this.element.closest( "form" )
+ .unbind( "reset" + this.eventNamespace )
+ .bind( "reset" + this.eventNamespace, formResetHandler );
+
+ if ( typeof this.options.disabled !== "boolean" ) {
+ this.options.disabled = !!this.element.prop( "disabled" );
+ } else {
+ this.element.prop( "disabled", this.options.disabled );
+ }
+
+ this._determineButtonType();
+ this.hasTitle = !!this.buttonElement.attr( "title" );
+
+ var that = this,
+ options = this.options,
+ toggleButton = this.type === "checkbox" || this.type === "radio",
+ activeClass = !toggleButton ? "ui-state-active" : "",
+ focusClass = "ui-state-focus";
+
+ if ( options.label === null ) {
+ options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
+ }
+
+ this._hoverable( this.buttonElement );
+
+ this.buttonElement
+ .addClass( baseClasses )
+ .attr( "role", "button" )
+ .bind( "mouseenter" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return;
+ }
+ if ( this === lastActive ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "mouseleave" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).removeClass( activeClass );
+ })
+ .bind( "click" + this.eventNamespace, function( event ) {
+ if ( options.disabled ) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+ });
+
+ this.element
+ .bind( "focus" + this.eventNamespace, function() {
+ // no need to check disabled, focus won't be triggered anyway
+ that.buttonElement.addClass( focusClass );
+ })
+ .bind( "blur" + this.eventNamespace, function() {
+ that.buttonElement.removeClass( focusClass );
+ });
+
+ if ( toggleButton ) {
+ this.element.bind( "change" + this.eventNamespace, function() {
+ if ( clickDragged ) {
+ return;
+ }
+ that.refresh();
+ });
+ // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
+ // prevents issue where button state changes but checkbox/radio checked state
+ // does not in Firefox (see ticket #6970)
+ this.buttonElement
+ .bind( "mousedown" + this.eventNamespace, function( event ) {
+ if ( options.disabled ) {
+ return;
+ }
+ clickDragged = false;
+ startXPos = event.pageX;
+ startYPos = event.pageY;
+ })
+ .bind( "mouseup" + this.eventNamespace, function( event ) {
+ if ( options.disabled ) {
+ return;
+ }
+ if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
+ clickDragged = true;
+ }
+ });
+ }
+
+ if ( this.type === "checkbox" ) {
+ this.buttonElement.bind( "click" + this.eventNamespace, function() {
+ if ( options.disabled || clickDragged ) {
+ return false;
+ }
+ });
+ } else if ( this.type === "radio" ) {
+ this.buttonElement.bind( "click" + this.eventNamespace, function() {
+ if ( options.disabled || clickDragged ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ that.buttonElement.attr( "aria-pressed", "true" );
+
+ var radio = that.element[ 0 ];
+ radioGroup( radio )
+ .not( radio )
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ });
+ } else {
+ this.buttonElement
+ .bind( "mousedown" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ lastActive = this;
+ that.document.one( "mouseup", function() {
+ lastActive = null;
+ });
+ })
+ .bind( "mouseup" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).removeClass( "ui-state-active" );
+ })
+ .bind( "keydown" + this.eventNamespace, function(event) {
+ if ( options.disabled ) {
+ return false;
+ }
+ if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ // see #8559, we bind to blur here in case the button element loses
+ // focus between keydown and keyup, it would be left in an "active" state
+ .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
+ $( this ).removeClass( "ui-state-active" );
+ });
+
+ if ( this.buttonElement.is("a") ) {
+ this.buttonElement.keyup(function(event) {
+ if ( event.keyCode === $.ui.keyCode.SPACE ) {
+ // TODO pass through original event correctly (just as 2nd argument doesn't work)
+ $( this ).click();
+ }
+ });
+ }
+ }
+
+ // TODO: pull out $.Widget's handling for the disabled option into
+ // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
+ // be overridden by individual plugins
+ this._setOption( "disabled", options.disabled );
+ this._resetButton();
+ },
+
+ _determineButtonType: function() {
+ var ancestor, labelSelector, checked;
+
+ if ( this.element.is("[type=checkbox]") ) {
+ this.type = "checkbox";
+ } else if ( this.element.is("[type=radio]") ) {
+ this.type = "radio";
+ } else if ( this.element.is("input") ) {
+ this.type = "input";
+ } else {
+ this.type = "button";
+ }
+
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ // we don't search against the document in case the element
+ // is disconnected from the DOM
+ ancestor = this.element.parents().last();
+ labelSelector = "label[for='" + this.element.attr("id") + "']";
+ this.buttonElement = ancestor.find( labelSelector );
+ if ( !this.buttonElement.length ) {
+ ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
+ this.buttonElement = ancestor.filter( labelSelector );
+ if ( !this.buttonElement.length ) {
+ this.buttonElement = ancestor.find( labelSelector );
+ }
+ }
+ this.element.addClass( "ui-helper-hidden-accessible" );
+
+ checked = this.element.is( ":checked" );
+ if ( checked ) {
+ this.buttonElement.addClass( "ui-state-active" );
+ }
+ this.buttonElement.prop( "aria-pressed", checked );
+ } else {
+ this.buttonElement = this.element;
+ }
+ },
+
+ widget: function() {
+ return this.buttonElement;
+ },
+
+ _destroy: function() {
+ this.element
+ .removeClass( "ui-helper-hidden-accessible" );
+ this.buttonElement
+ .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
+ .removeAttr( "role" )
+ .removeAttr( "aria-pressed" )
+ .html( this.buttonElement.find(".ui-button-text").html() );
+
+ if ( !this.hasTitle ) {
+ this.buttonElement.removeAttr( "title" );
+ }
+ },
+
+ _setOption: function( key, value ) {
+ this._super( key, value );
+ if ( key === "disabled" ) {
+ if ( value ) {
+ this.element.prop( "disabled", true );
+ } else {
+ this.element.prop( "disabled", false );
+ }
+ return;
+ }
+ this._resetButton();
+ },
+
+ refresh: function() {
+ //See #8237 & #8828
+ var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
+
+ if ( isDisabled !== this.options.disabled ) {
+ this._setOption( "disabled", isDisabled );
+ }
+ if ( this.type === "radio" ) {
+ radioGroup( this.element[0] ).each(function() {
+ if ( $( this ).is( ":checked" ) ) {
+ $( this ).button( "widget" )
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", "true" );
+ } else {
+ $( this ).button( "widget" )
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ }
+ });
+ } else if ( this.type === "checkbox" ) {
+ if ( this.element.is( ":checked" ) ) {
+ this.buttonElement
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", "true" );
+ } else {
+ this.buttonElement
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ }
+ }
+ },
+
+ _resetButton: function() {
+ if ( this.type === "input" ) {
+ if ( this.options.label ) {
+ this.element.val( this.options.label );
+ }
+ return;
+ }
+ var buttonElement = this.buttonElement.removeClass( typeClasses ),
+ buttonText = $( "<span></span>", this.document[0] )
+ .addClass( "ui-button-text" )
+ .html( this.options.label )
+ .appendTo( buttonElement.empty() )
+ .text(),
+ icons = this.options.icons,
+ multipleIcons = icons.primary && icons.secondary,
+ buttonClasses = [];
+
+ if ( icons.primary || icons.secondary ) {
+ if ( this.options.text ) {
+ buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
+ }
+
+ if ( icons.primary ) {
+ buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
+ }
+
+ if ( icons.secondary ) {
+ buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
+ }
+
+ if ( !this.options.text ) {
+ buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
+
+ if ( !this.hasTitle ) {
+ buttonElement.attr( "title", $.trim( buttonText ) );
+ }
+ }
+ } else {
+ buttonClasses.push( "ui-button-text-only" );
+ }
+ buttonElement.addClass( buttonClasses.join( " " ) );
+ }
+});
+
+$.widget( "ui.buttonset", {
+ version: "1.10.3",
+ options: {
+ items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
+ },
+
+ _create: function() {
+ this.element.addClass( "ui-buttonset" );
+ },
+
+ _init: function() {
+ this.refresh();
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "disabled" ) {
+ this.buttons.button( "option", key, value );
+ }
+
+ this._super( key, value );
+ },
+
+ refresh: function() {
+ var rtl = this.element.css( "direction" ) === "rtl";
+
+ this.buttons = this.element.find( this.options.items )
+ .filter( ":ui-button" )
+ .button( "refresh" )
+ .end()
+ .not( ":ui-button" )
+ .button()
+ .end()
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
+ .filter( ":first" )
+ .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
+ .end()
+ .filter( ":last" )
+ .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
+ .end()
+ .end();
+ },
+
+ _destroy: function() {
+ this.element.removeClass( "ui-buttonset" );
+ this.buttons
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-left ui-corner-right" )
+ .end()
+ .button( "destroy" );
+ }
+});
+
+}( jQuery ) );
+(function( $, undefined ) {
+
+$.extend($.ui, { datepicker: { version: "1.10.3" } });
+
+var PROP_NAME = "datepicker",
+ instActive;
+
+/* Date picker manager.
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
+ Settings for (groups of) date pickers are maintained in an instance object,
+ allowing multiple different settings on the same page. */
+
+function Datepicker() {
+ this._curInst = null; // The current instance in use
+ this._keyEvent = false; // If the last event was a key event
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
+ this._inDialog = false; // True if showing within a "dialog", false if not
+ this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
+ this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
+ this._appendClass = "ui-datepicker-append"; // The name of the append marker class
+ this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
+ this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
+ this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
+ this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
+ this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
+ this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
+ this.regional = []; // Available regional settings, indexed by language code
+ this.regional[""] = { // Default regional settings
+ closeText: "Done", // Display text for close link
+ prevText: "Prev", // Display text for previous month link
+ nextText: "Next", // Display text for next month link
+ currentText: "Today", // Display text for current month link
+ monthNames: ["January","February","March","April","May","June",
+ "July","August","September","October","November","December"], // Names of months for drop-down and formatting
+ monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
+ dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
+ dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
+ dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
+ weekHeader: "Wk", // Column header for week of the year
+ dateFormat: "mm/dd/yy", // See format options on parseDate
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
+ isRTL: false, // True if right-to-left language, false if left-to-right
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+ yearSuffix: "" // Additional text to append to the year in the month headers
+ };
+ this._defaults = { // Global defaults for all the date picker instances
+ showOn: "focus", // "focus" for popup on focus,
+ // "button" for trigger button, or "both" for either
+ showAnim: "fadeIn", // Name of jQuery animation for popup
+ showOptions: {}, // Options for enhanced animations
+ defaultDate: null, // Used when field is blank: actual date,
+ // +/-number for offset from today, null for today
+ appendText: "", // Display text following the input box, e.g. showing the format
+ buttonText: "...", // Text for trigger button
+ buttonImage: "", // URL for trigger button image
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
+ hideIfNoPrevNext: false, // True to hide next/previous month links
+ // if not applicable, false to just disable them
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
+ gotoCurrent: false, // True if today link goes back to current selection instead
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
+ changeYear: false, // True if year can be selected directly, false if only prev/next
+ yearRange: "c-10:c+10", // Range of years to display in drop-down,
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
+ showWeek: false, // True to show week of the year, false to not show it
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
+ // takes a Date and returns the number of the week for it
+ shortYearCutoff: "+10", // Short year values < this are in the current century,
+ // > this are in the previous century,
+ // string value starting with "+" for current year + value
+ minDate: null, // The earliest selectable date, or null for no limit
+ maxDate: null, // The latest selectable date, or null for no limit
+ duration: "fast", // Duration of display/closure
+ beforeShowDay: null, // Function that takes a date and returns an array with
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
+ beforeShow: null, // Function that takes an input field and
+ // returns a set of custom settings for the date picker
+ onSelect: null, // Define a callback function when a date is selected
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
+ onClose: null, // Define a callback function when the datepicker is closed
+ numberOfMonths: 1, // Number of months to show at a time
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
+ stepMonths: 1, // Number of months to step back/forward
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
+ altField: "", // Selector for an alternate field to store selected dates into
+ altFormat: "", // The date format to use for the alternate field
+ constrainInput: true, // The input is constrained by the current date format
+ showButtonPanel: false, // True to show button panel, false to not show it
+ autoSize: false, // True to size the input for the date format, false to leave as is
+ disabled: false // The initial disabled state
+ };
+ $.extend(this._defaults, this.regional[""]);
+ this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
+}
+
+$.extend(Datepicker.prototype, {
+ /* Class name added to elements to indicate already configured with a date picker. */
+ markerClassName: "hasDatepicker",
+
+ //Keep track of the maximum number of rows displayed (see #7043)
+ maxRows: 4,
+
+ // TODO rename to "widget" when switching to widget factory
+ _widgetDatepicker: function() {
+ return this.dpDiv;
+ },
+
+ /* Override the default settings for all instances of the date picker.
+ * @param settings object - the new settings to use as defaults (anonymous object)
+ * @return the manager object
+ */
+ setDefaults: function(settings) {
+ extendRemove(this._defaults, settings || {});
+ return this;
+ },
+
+ /* Attach the date picker to a jQuery selection.
+ * @param target element - the target input field or division or span
+ * @param settings object - the new settings to use for this date picker instance (anonymous)
+ */
+ _attachDatepicker: function(target, settings) {
+ var nodeName, inline, inst;
+ nodeName = target.nodeName.toLowerCase();
+ inline = (nodeName === "div" || nodeName === "span");
+ if (!target.id) {
+ this.uuid += 1;
+ target.id = "dp" + this.uuid;
+ }
+ inst = this._newInst($(target), inline);
+ inst.settings = $.extend({}, settings || {});
+ if (nodeName === "input") {
+ this._connectDatepicker(target, inst);
+ } else if (inline) {
+ this._inlineDatepicker(target, inst);
+ }
+ },
+
+ /* Create a new instance object. */
+ _newInst: function(target, inline) {
+ var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
+ return {id: id, input: target, // associated target
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
+ drawMonth: 0, drawYear: 0, // month being drawn
+ inline: inline, // is datepicker inline or not
+ dpDiv: (!inline ? this.dpDiv : // presentation div
+ bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
+ },
+
+ /* Attach the date picker to an input field. */
+ _connectDatepicker: function(target, inst) {
+ var input = $(target);
+ inst.append = $([]);
+ inst.trigger = $([]);
+ if (input.hasClass(this.markerClassName)) {
+ return;
+ }
+ this._attachments(input, inst);
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
+ keypress(this._doKeyPress).keyup(this._doKeyUp);
+ this._autoSize(inst);
+ $.data(target, PROP_NAME, inst);
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
+ if( inst.settings.disabled ) {
+ this._disableDatepicker( target );
+ }
+ },
+
+ /* Make attachments based on settings. */
+ _attachments: function(input, inst) {
+ var showOn, buttonText, buttonImage,
+ appendText = this._get(inst, "appendText"),
+ isRTL = this._get(inst, "isRTL");
+
+ if (inst.append) {
+ inst.append.remove();
+ }
+ if (appendText) {
+ inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
+ input[isRTL ? "before" : "after"](inst.append);
+ }
+
+ input.unbind("focus", this._showDatepicker);
+
+ if (inst.trigger) {
+ inst.trigger.remove();
+ }
+
+ showOn = this._get(inst, "showOn");
+ if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
+ input.focus(this._showDatepicker);
+ }
+ if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
+ buttonText = this._get(inst, "buttonText");
+ buttonImage = this._get(inst, "buttonImage");
+ inst.trigger = $(this._get(inst, "buttonImageOnly") ?
+ $("<img/>").addClass(this._triggerClass).
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
+ $("<button type='button'></button>").addClass(this._triggerClass).
+ html(!buttonImage ? buttonText : $("<img/>").attr(
+ { src:buttonImage, alt:buttonText, title:buttonText })));
+ input[isRTL ? "before" : "after"](inst.trigger);
+ inst.trigger.click(function() {
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
+ $.datepicker._hideDatepicker();
+ } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
+ $.datepicker._hideDatepicker();
+ $.datepicker._showDatepicker(input[0]);
+ } else {
+ $.datepicker._showDatepicker(input[0]);
+ }
+ return false;
+ });
+ }
+ },
+
+ /* Apply the maximum length for the date format. */
+ _autoSize: function(inst) {
+ if (this._get(inst, "autoSize") && !inst.inline) {
+ var findMax, max, maxI, i,
+ date = new Date(2009, 12 - 1, 20), // Ensure double digits
+ dateFormat = this._get(inst, "dateFormat");
+
+ if (dateFormat.match(/[DM]/)) {
+ findMax = function(names) {
+ max = 0;
+ maxI = 0;
+ for (i = 0; i < names.length; i++) {
+ if (names[i].length > max) {
+ max = names[i].length;
+ maxI = i;
+ }
+ }
+ return maxI;
+ };
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
+ "monthNames" : "monthNamesShort"))));
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
+ "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
+ }
+ inst.input.attr("size", this._formatDate(inst, date).length);
+ }
+ },
+
+ /* Attach an inline date picker to a div. */
+ _inlineDatepicker: function(target, inst) {
+ var divSpan = $(target);
+ if (divSpan.hasClass(this.markerClassName)) {
+ return;
+ }
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv);
+ $.data(target, PROP_NAME, inst);
+ this._setDate(inst, this._getDefaultDate(inst), true);
+ this._updateDatepicker(inst);
+ this._updateAlternate(inst);
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
+ if( inst.settings.disabled ) {
+ this._disableDatepicker( target );
+ }
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
+ inst.dpDiv.css( "display", "block" );
+ },
+
+ /* Pop-up the date picker in a "dialog" box.
+ * @param input element - ignored
+ * @param date string or Date - the initial date to display
+ * @param onSelect function - the function to call when a date is selected
+ * @param settings object - update the dialog date picker instance's settings (anonymous object)
+ * @param pos int[2] - coordinates for the dialog's position within the screen or
+ * event - with x/y coordinates or
+ * leave empty for default (screen centre)
+ * @return the manager object
+ */
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
+ var id, browserWidth, browserHeight, scrollX, scrollY,
+ inst = this._dialogInst; // internal instance
+
+ if (!inst) {
+ this.uuid += 1;
+ id = "dp" + this.uuid;
+ this._dialogInput = $("<input type='text' id='" + id +
+ "' style='position: absolute; top: -100px; width: 0px;'/>");
+ this._dialogInput.keydown(this._doKeyDown);
+ $("body").append(this._dialogInput);
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
+ inst.settings = {};
+ $.data(this._dialogInput[0], PROP_NAME, inst);
+ }
+ extendRemove(inst.settings, settings || {});
+ date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
+ this._dialogInput.val(date);
+
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+ if (!this._pos) {
+ browserWidth = document.documentElement.clientWidth;
+ browserHeight = document.documentElement.clientHeight;
+ scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
+ scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+ this._pos = // should use actual width/height below
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
+ }
+
+ // move input on screen for focus, but hidden behind dialog
+ this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
+ inst.settings.onSelect = onSelect;
+ this._inDialog = true;
+ this.dpDiv.addClass(this._dialogClass);
+ this._showDatepicker(this._dialogInput[0]);
+ if ($.blockUI) {
+ $.blockUI(this.dpDiv);
+ }
+ $.data(this._dialogInput[0], PROP_NAME, inst);
+ return this;
+ },
+
+ /* Detach a datepicker from its control.
+ * @param target element - the target input field or division or span
+ */
+ _destroyDatepicker: function(target) {
+ var nodeName,
+ $target = $(target),
+ inst = $.data(target, PROP_NAME);
+
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+
+ nodeName = target.nodeName.toLowerCase();
+ $.removeData(target, PROP_NAME);
+ if (nodeName === "input") {
+ inst.append.remove();
+ inst.trigger.remove();
+ $target.removeClass(this.markerClassName).
+ unbind("focus", this._showDatepicker).
+ unbind("keydown", this._doKeyDown).
+ unbind("keypress", this._doKeyPress).
+ unbind("keyup", this._doKeyUp);
+ } else if (nodeName === "div" || nodeName === "span") {
+ $target.removeClass(this.markerClassName).empty();
+ }
+ },
+
+ /* Enable the date picker to a jQuery selection.
+ * @param target element - the target input field or division or span
+ */
+ _enableDatepicker: function(target) {
+ var nodeName, inline,
+ $target = $(target),
+ inst = $.data(target, PROP_NAME);
+
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+
+ nodeName = target.nodeName.toLowerCase();
+ if (nodeName === "input") {
+ target.disabled = false;
+ inst.trigger.filter("button").
+ each(function() { this.disabled = false; }).end().
+ filter("img").css({opacity: "1.0", cursor: ""});
+ } else if (nodeName === "div" || nodeName === "span") {
+ inline = $target.children("." + this._inlineClass);
+ inline.children().removeClass("ui-state-disabled");
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+ prop("disabled", false);
+ }
+ this._disabledInputs = $.map(this._disabledInputs,
+ function(value) { return (value === target ? null : value); }); // delete entry
+ },
+
+ /* Disable the date picker to a jQuery selection.
+ * @param target element - the target input field or division or span
+ */
+ _disableDatepicker: function(target) {
+ var nodeName, inline,
+ $target = $(target),
+ inst = $.data(target, PROP_NAME);
+
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+
+ nodeName = target.nodeName.toLowerCase();
+ if (nodeName === "input") {
+ target.disabled = true;
+ inst.trigger.filter("button").
+ each(function() { this.disabled = true; }).end().
+ filter("img").css({opacity: "0.5", cursor: "default"});
+ } else if (nodeName === "div" || nodeName === "span") {
+ inline = $target.children("." + this._inlineClass);
+ inline.children().addClass("ui-state-disabled");
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+ prop("disabled", true);
+ }
+ this._disabledInputs = $.map(this._disabledInputs,
+ function(value) { return (value === target ? null : value); }); // delete entry
+ this._disabledInputs[this._disabledInputs.length] = target;
+ },
+
+ /* Is the first field in a jQuery collection disabled as a datepicker?
+ * @param target element - the target input field or division or span
+ * @return boolean - true if disabled, false if enabled
+ */
+ _isDisabledDatepicker: function(target) {
+ if (!target) {
+ return false;
+ }
+ for (var i = 0; i < this._disabledInputs.length; i++) {
+ if (this._disabledInputs[i] === target) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /* Retrieve the instance data for the target control.
+ * @param target element - the target input field or division or span
+ * @return object - the associated instance data
+ * @throws error if a jQuery problem getting data
+ */
+ _getInst: function(target) {
+ try {
+ return $.data(target, PROP_NAME);
+ }
+ catch (err) {
+ throw "Missing instance data for this datepicker";
+ }
+ },
+
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
+ * @param target element - the target input field or division or span
+ * @param name object - the new settings to update or
+ * string - the name of the setting to change or retrieve,
+ * when retrieving also "all" for all instance settings or
+ * "defaults" for all global defaults
+ * @param value any - the new value for the setting
+ * (omit if above is an object or to retrieve a value)
+ */
+ _optionDatepicker: function(target, name, value) {
+ var settings, date, minDate, maxDate,
+ inst = this._getInst(target);
+
+ if (arguments.length === 2 && typeof name === "string") {
+ return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
+ (inst ? (name === "all" ? $.extend({}, inst.settings) :
+ this._get(inst, name)) : null));
+ }
+
+ settings = name || {};
+ if (typeof name === "string") {
+ settings = {};
+ settings[name] = value;
+ }
+
+ if (inst) {
+ if (this._curInst === inst) {
+ this._hideDatepicker();
+ }
+
+ date = this._getDateDatepicker(target, true);
+ minDate = this._getMinMaxDate(inst, "min");
+ maxDate = this._getMinMaxDate(inst, "max");
+ extendRemove(inst.settings, settings);
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
+ if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
+ inst.settings.minDate = this._formatDate(inst, minDate);
+ }
+ if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
+ }
+ if ( "disabled" in settings ) {
+ if ( settings.disabled ) {
+ this._disableDatepicker(target);
+ } else {
+ this._enableDatepicker(target);
+ }
+ }
+ this._attachments($(target), inst);
+ this._autoSize(inst);
+ this._setDate(inst, date);
+ this._updateAlternate(inst);
+ this._updateDatepicker(inst);
+ }
+ },
+
+ // change method deprecated
+ _changeDatepicker: function(target, name, value) {
+ this._optionDatepicker(target, name, value);
+ },
+
+ /* Redraw the date picker attached to an input field or division.
+ * @param target element - the target input field or division or span
+ */
+ _refreshDatepicker: function(target) {
+ var inst = this._getInst(target);
+ if (inst) {
+ this._updateDatepicker(inst);
+ }
+ },
+
+ /* Set the dates for a jQuery selection.
+ * @param target element - the target input field or division or span
+ * @param date Date - the new date
+ */
+ _setDateDatepicker: function(target, date) {
+ var inst = this._getInst(target);
+ if (inst) {
+ this._setDate(inst, date);
+ this._updateDatepicker(inst);
+ this._updateAlternate(inst);
+ }
+ },
+
+ /* Get the date(s) for the first entry in a jQuery selection.
+ * @param target element - the target input field or division or span
+ * @param noDefault boolean - true if no default date is to be used
+ * @return Date - the current date
+ */
+ _getDateDatepicker: function(target, noDefault) {
+ var inst = this._getInst(target);
+ if (inst && !inst.inline) {
+ this._setDateFromField(inst, noDefault);
+ }
+ return (inst ? this._getDate(inst) : null);
+ },
+
+ /* Handle keystrokes. */
+ _doKeyDown: function(event) {
+ var onSelect, dateStr, sel,
+ inst = $.datepicker._getInst(event.target),
+ handled = true,
+ isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
+
+ inst._keyEvent = true;
+ if ($.datepicker._datepickerShowing) {
+ switch (event.keyCode) {
+ case 9: $.datepicker._hideDatepicker();
+ handled = false;
+ break; // hide on tab out
+ case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
+ $.datepicker._currentClass + ")", inst.dpDiv);
+ if (sel[0]) {
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+ }
+
+ onSelect = $.datepicker._get(inst, "onSelect");
+ if (onSelect) {
+ dateStr = $.datepicker._formatDate(inst);
+
+ // trigger custom callback
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
+ } else {
+ $.datepicker._hideDatepicker();
+ }
+
+ return false; // don't submit the form
+ case 27: $.datepicker._hideDatepicker();
+ break; // hide on escape
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ -$.datepicker._get(inst, "stepBigMonths") :
+ -$.datepicker._get(inst, "stepMonths")), "M");
+ break; // previous month/year on page up/+ ctrl
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ +$.datepicker._get(inst, "stepBigMonths") :
+ +$.datepicker._get(inst, "stepMonths")), "M");
+ break; // next month/year on page down/+ ctrl
+ case 35: if (event.ctrlKey || event.metaKey) {
+ $.datepicker._clearDate(event.target);
+ }
+ handled = event.ctrlKey || event.metaKey;
+ break; // clear on ctrl or command +end
+ case 36: if (event.ctrlKey || event.metaKey) {
+ $.datepicker._gotoToday(event.target);
+ }
+ handled = event.ctrlKey || event.metaKey;
+ break; // current on ctrl or command +home
+ case 37: if (event.ctrlKey || event.metaKey) {
+ $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
+ }
+ handled = event.ctrlKey || event.metaKey;
+ // -1 day on ctrl or command +left
+ if (event.originalEvent.altKey) {
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ -$.datepicker._get(inst, "stepBigMonths") :
+ -$.datepicker._get(inst, "stepMonths")), "M");
+ }
+ // next month/year on alt +left on Mac
+ break;
+ case 38: if (event.ctrlKey || event.metaKey) {
+ $.datepicker._adjustDate(event.target, -7, "D");
+ }
+ handled = event.ctrlKey || event.metaKey;
+ break; // -1 week on ctrl or command +up
+ case 39: if (event.ctrlKey || event.metaKey) {
+ $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
+ }
+ handled = event.ctrlKey || event.metaKey;
+ // +1 day on ctrl or command +right
+ if (event.originalEvent.altKey) {
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ +$.datepicker._get(inst, "stepBigMonths") :
+ +$.datepicker._get(inst, "stepMonths")), "M");
+ }
+ // next month/year on alt +right
+ break;
+ case 40: if (event.ctrlKey || event.metaKey) {
+ $.datepicker._adjustDate(event.target, +7, "D");
+ }
+ handled = event.ctrlKey || event.metaKey;
+ break; // +1 week on ctrl or command +down
+ default: handled = false;
+ }
+ } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
+ $.datepicker._showDatepicker(this);
+ } else {
+ handled = false;
+ }
+
+ if (handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ },
+
+ /* Filter entered characters - based on date format. */
+ _doKeyPress: function(event) {
+ var chars, chr,
+ inst = $.datepicker._getInst(event.target);
+
+ if ($.datepicker._get(inst, "constrainInput")) {
+ chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
+ chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
+ return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
+ }
+ },
+
+ /* Synchronise manual entry and field/alternate field. */
+ _doKeyUp: function(event) {
+ var date,
+ inst = $.datepicker._getInst(event.target);
+
+ if (inst.input.val() !== inst.lastVal) {
+ try {
+ date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
+ (inst.input ? inst.input.val() : null),
+ $.datepicker._getFormatConfig(inst));
+
+ if (date) { // only if valid
+ $.datepicker._setDateFromField(inst);
+ $.datepicker._updateAlternate(inst);
+ $.datepicker._updateDatepicker(inst);
+ }
+ }
+ catch (err) {
+ }
+ }
+ return true;
+ },
+
+ /* Pop-up the date picker for a given input field.
+ * If false returned from beforeShow event handler do not show.
+ * @param input element - the input field attached to the date picker or
+ * event - if triggered by focus
+ */
+ _showDatepicker: function(input) {
+ input = input.target || input;
+ if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
+ input = $("input", input.parentNode)[0];
+ }
+
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
+ return;
+ }
+
+ var inst, beforeShow, beforeShowSettings, isFixed,
+ offset, showAnim, duration;
+
+ inst = $.datepicker._getInst(input);
+ if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
+ $.datepicker._curInst.dpDiv.stop(true, true);
+ if ( inst && $.datepicker._datepickerShowing ) {
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
+ }
+ }
+
+ beforeShow = $.datepicker._get(inst, "beforeShow");
+ beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
+ if(beforeShowSettings === false){
+ return;
+ }
+ extendRemove(inst.settings, beforeShowSettings);
+
+ inst.lastVal = null;
+ $.datepicker._lastInput = input;
+ $.datepicker._setDateFromField(inst);
+
+ if ($.datepicker._inDialog) { // hide cursor
+ input.value = "";
+ }
+ if (!$.datepicker._pos) { // position below input
+ $.datepicker._pos = $.datepicker._findPos(input);
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
+ }
+
+ isFixed = false;
+ $(input).parents().each(function() {
+ isFixed |= $(this).css("position") === "fixed";
+ return !isFixed;
+ });
+
+ offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
+ $.datepicker._pos = null;
+ //to avoid flashes on Firefox
+ inst.dpDiv.empty();
+ // determine sizing offscreen
+ inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
+ $.datepicker._updateDatepicker(inst);
+ // fix width for dynamic number of date pickers
+ // and adjust position before showing
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
+ "static" : (isFixed ? "fixed" : "absolute")), display: "none",
+ left: offset.left + "px", top: offset.top + "px"});
+
+ if (!inst.inline) {
+ showAnim = $.datepicker._get(inst, "showAnim");
+ duration = $.datepicker._get(inst, "duration");
+ inst.dpDiv.zIndex($(input).zIndex()+1);
+ $.datepicker._datepickerShowing = true;
+
+ if ( $.effects && $.effects.effect[ showAnim ] ) {
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
+ } else {
+ inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
+ }
+
+ if ( $.datepicker._shouldFocusInput( inst ) ) {
+ inst.input.focus();
+ }
+
+ $.datepicker._curInst = inst;
+ }
+ },
+
+ /* Generate the date picker content. */
+ _updateDatepicker: function(inst) {
+ this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
+ instActive = inst; // for delegate hover events
+ inst.dpDiv.empty().append(this._generateHTML(inst));
+ this._attachHandlers(inst);
+ inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
+
+ var origyearshtml,
+ numMonths = this._getNumberOfMonths(inst),
+ cols = numMonths[1],
+ width = 17;
+
+ inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
+ if (cols > 1) {
+ inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
+ }
+ inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
+ "Class"]("ui-datepicker-multi");
+ inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
+ "Class"]("ui-datepicker-rtl");
+
+ if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
+ inst.input.focus();
+ }
+
+ // deffered render of the years select (to avoid flashes on Firefox)
+ if( inst.yearshtml ){
+ origyearshtml = inst.yearshtml;
+ setTimeout(function(){
+ //assure that inst.yearshtml didn't change.
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
+ inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
+ }
+ origyearshtml = inst.yearshtml = null;
+ }, 0);
+ }
+ },
+
+ // #6694 - don't focus the input if it's already focused
+ // this breaks the change event in IE
+ // Support: IE and jQuery <1.9
+ _shouldFocusInput: function( inst ) {
+ return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
+ },
+
+ /* Check positioning to remain on screen. */
+ _checkOffset: function(inst, offset, isFixed) {
+ var dpWidth = inst.dpDiv.outerWidth(),
+ dpHeight = inst.dpDiv.outerHeight(),
+ inputWidth = inst.input ? inst.input.outerWidth() : 0,
+ inputHeight = inst.input ? inst.input.outerHeight() : 0,
+ viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
+ viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
+
+ offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
+ offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
+ offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
+
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
+ Math.abs(dpHeight + inputHeight) : 0);
+
+ return offset;
+ },
+
+ /* Find an object's position on the screen. */
+ _findPos: function(obj) {
+ var position,
+ inst = this._getInst(obj),
+ isRTL = this._get(inst, "isRTL");
+
+ while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
+ obj = obj[isRTL ? "previousSibling" : "nextSibling"];
+ }
+
+ position = $(obj).offset();
+ return [position.left, position.top];
+ },
+
+ /* Hide the date picker from view.
+ * @param input element - the input field attached to the date picker
+ */
+ _hideDatepicker: function(input) {
+ var showAnim, duration, postProcess, onClose,
+ inst = this._curInst;
+
+ if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
+ return;
+ }
+
+ if (this._datepickerShowing) {
+ showAnim = this._get(inst, "showAnim");
+ duration = this._get(inst, "duration");
+ postProcess = function() {
+ $.datepicker._tidyDialog(inst);
+ };
+
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
+ } else {
+ inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
+ (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
+ }
+
+ if (!showAnim) {
+ postProcess();
+ }
+ this._datepickerShowing = false;
+
+ onClose = this._get(inst, "onClose");
+ if (onClose) {
+ onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
+ }
+
+ this._lastInput = null;
+ if (this._inDialog) {
+ this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
+ if ($.blockUI) {
+ $.unblockUI();
+ $("body").append(this.dpDiv);
+ }
+ }
+ this._inDialog = false;
+ }
+ },
+
+ /* Tidy up after a dialog display. */
+ _tidyDialog: function(inst) {
+ inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
+ },
+
+ /* Close date picker if clicked elsewhere. */
+ _checkExternalClick: function(event) {
+ if (!$.datepicker._curInst) {
+ return;
+ }
+
+ var $target = $(event.target),
+ inst = $.datepicker._getInst($target[0]);
+
+ if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
+ $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
+ !$target.hasClass($.datepicker.markerClassName) &&
+ !$target.closest("." + $.datepicker._triggerClass).length &&
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
+ ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
+ $.datepicker._hideDatepicker();
+ }
+ },
+
+ /* Adjust one of the date sub-fields. */
+ _adjustDate: function(id, offset, period) {
+ var target = $(id),
+ inst = this._getInst(target[0]);
+
+ if (this._isDisabledDatepicker(target[0])) {
+ return;
+ }
+ this._adjustInstDate(inst, offset +
+ (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
+ period);
+ this._updateDatepicker(inst);
+ },
+
+ /* Action for current link. */
+ _gotoToday: function(id) {
+ var date,
+ target = $(id),
+ inst = this._getInst(target[0]);
+
+ if (this._get(inst, "gotoCurrent") && inst.currentDay) {
+ inst.selectedDay = inst.currentDay;
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
+ inst.drawYear = inst.selectedYear = inst.currentYear;
+ } else {
+ date = new Date();
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ }
+ this._notifyChange(inst);
+ this._adjustDate(target);
+ },
+
+ /* Action for selecting a new month/year. */
+ _selectMonthYear: function(id, select, period) {
+ var target = $(id),
+ inst = this._getInst(target[0]);
+
+ inst["selected" + (period === "M" ? "Month" : "Year")] =
+ inst["draw" + (period === "M" ? "Month" : "Year")] =
+ parseInt(select.options[select.selectedIndex].value,10);
+
+ this._notifyChange(inst);
+ this._adjustDate(target);
+ },
+
+ /* Action for selecting a day. */
+ _selectDay: function(id, month, year, td) {
+ var inst,
+ target = $(id);
+
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
+ return;
+ }
+
+ inst = this._getInst(target[0]);
+ inst.selectedDay = inst.currentDay = $("a", td).html();
+ inst.selectedMonth = inst.currentMonth = month;
+ inst.selectedYear = inst.currentYear = year;
+ this._selectDate(id, this._formatDate(inst,
+ inst.currentDay, inst.currentMonth, inst.currentYear));
+ },
+
+ /* Erase the input field and hide the date picker. */
+ _clearDate: function(id) {
+ var target = $(id);
+ this._selectDate(target, "");
+ },
+
+ /* Update the input field with the selected date. */
+ _selectDate: function(id, dateStr) {
+ var onSelect,
+ target = $(id),
+ inst = this._getInst(target[0]);
+
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
+ if (inst.input) {
+ inst.input.val(dateStr);
+ }
+ this._updateAlternate(inst);
+
+ onSelect = this._get(inst, "onSelect");
+ if (onSelect) {
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
+ } else if (inst.input) {
+ inst.input.trigger("change"); // fire the change event
+ }
+
+ if (inst.inline){
+ this._updateDatepicker(inst);
+ } else {
+ this._hideDatepicker();
+ this._lastInput = inst.input[0];
+ if (typeof(inst.input[0]) !== "object") {
+ inst.input.focus(); // restore focus
+ }
+ this._lastInput = null;
+ }
+ },
+
+ /* Update any alternate field to synchronise with the main field. */
+ _updateAlternate: function(inst) {
+ var altFormat, date, dateStr,
+ altField = this._get(inst, "altField");
+
+ if (altField) { // update alternate field too
+ altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
+ date = this._getDate(inst);
+ dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
+ $(altField).each(function() { $(this).val(dateStr); });
+ }
+ },
+
+ /* Set as beforeShowDay function to prevent selection of weekends.
+ * @param date Date - the date to customise
+ * @return [boolean, string] - is this date selectable?, what is its CSS class?
+ */
+ noWeekends: function(date) {
+ var day = date.getDay();
+ return [(day > 0 && day < 6), ""];
+ },
+
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
+ * @param date Date - the date to get the week for
+ * @return number - the number of the week within the year that contains this date
+ */
+ iso8601Week: function(date) {
+ var time,
+ checkDate = new Date(date.getTime());
+
+ // Find Thursday of this week starting on Monday
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+
+ time = checkDate.getTime();
+ checkDate.setMonth(0); // Compare with Jan 1
+ checkDate.setDate(1);
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+ },
+
+ /* Parse a string value into a date object.
+ * See formatDate below for the possible formats.
+ *
+ * @param format string - the expected format of the date
+ * @param value string - the date in the above format
+ * @param settings Object - attributes include:
+ * shortYearCutoff number - the cutoff year for determining the century (optional)
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
+ * dayNames string[7] - names of the days from Sunday (optional)
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
+ * monthNames string[12] - names of the months (optional)
+ * @return Date - the extracted date value or null if value is blank
+ */
+ parseDate: function (format, value, settings) {
+ if (format == null || value == null) {
+ throw "Invalid arguments";
+ }
+
+ value = (typeof value === "object" ? value.toString() : value + "");
+ if (value === "") {
+ return null;
+ }
+
+ var iFormat, dim, extra,
+ iValue = 0,
+ shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
+ shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
+ dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
+ dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
+ monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
+ monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
+ year = -1,
+ month = -1,
+ day = -1,
+ doy = -1,
+ literal = false,
+ date,
+ // Check whether a format character is doubled
+ lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
+ if (matches) {
+ iFormat++;
+ }
+ return matches;
+ },
+ // Extract a number from the string value
+ getNumber = function(match) {
+ var isDoubled = lookAhead(match),
+ size = (match === "@" ? 14 : (match === "!" ? 20 :
+ (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
+ digits = new RegExp("^\\d{1," + size + "}"),
+ num = value.substring(iValue).match(digits);
+ if (!num) {
+ throw "Missing number at position " + iValue;
+ }
+ iValue += num[0].length;
+ return parseInt(num[0], 10);
+ },
+ // Extract a name from the string value and convert to an index
+ getName = function(match, shortNames, longNames) {
+ var index = -1,
+ names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
+ return [ [k, v] ];
+ }).sort(function (a, b) {
+ return -(a[1].length - b[1].length);
+ });
+
+ $.each(names, function (i, pair) {
+ var name = pair[1];
+ if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
+ index = pair[0];
+ iValue += name.length;
+ return false;
+ }
+ });
+ if (index !== -1) {
+ return index + 1;
+ } else {
+ throw "Unknown name at position " + iValue;
+ }
+ },
+ // Confirm that a literal character matches the string value
+ checkLiteral = function() {
+ if (value.charAt(iValue) !== format.charAt(iFormat)) {
+ throw "Unexpected literal at position " + iValue;
+ }
+ iValue++;
+ };
+
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
+ if (literal) {
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
+ literal = false;
+ } else {
+ checkLiteral();
+ }
+ } else {
+ switch (format.charAt(iFormat)) {
+ case "d":
+ day = getNumber("d");
+ break;
+ case "D":
+ getName("D", dayNamesShort, dayNames);
+ break;
+ case "o":
+ doy = getNumber("o");
+ break;
+ case "m":
+ month = getNumber("m");
+ break;
+ case "M":
+ month = getName("M", monthNamesShort, monthNames);
+ break;
+ case "y":
+ year = getNumber("y");
+ break;
+ case "@":
+ date = new Date(getNumber("@"));
+ year = date.getFullYear();
+ month = date.getMonth() + 1;
+ day = date.getDate();
+ break;
+ case "!":
+ date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
+ year = date.getFullYear();
+ month = date.getMonth() + 1;
+ day = date.getDate();
+ break;
+ case "'":
+ if (lookAhead("'")){
+ checkLiteral();
+ } else {
+ literal = true;
+ }
+ break;
+ default:
+ checkLiteral();
+ }
+ }
+ }
+
+ if (iValue < value.length){
+ extra = value.substr(iValue);
+ if (!/^\s+/.test(extra)) {
+ throw "Extra/unparsed characters found in date: " + extra;
+ }
+ }
+
+ if (year === -1) {
+ year = new Date().getFullYear();
+ } else if (year < 100) {
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
+ (year <= shortYearCutoff ? 0 : -100);
+ }
+
+ if (doy > -1) {
+ month = 1;
+ day = doy;
+ do {
+ dim = this._getDaysInMonth(year, month - 1);
+ if (day <= dim) {
+ break;
+ }
+ month++;
+ day -= dim;
+ } while (true);
+ }
+
+ date = this._daylightSavingAdjust(new Date(year, month - 1, day));
+ if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
+ throw "Invalid date"; // E.g. 31/02/00
+ }
+ return date;
+ },
+
+ /* Standard date formats. */
+ ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
+ COOKIE: "D, dd M yy",
+ ISO_8601: "yy-mm-dd",
+ RFC_822: "D, d M y",
+ RFC_850: "DD, dd-M-y",
+ RFC_1036: "D, d M y",
+ RFC_1123: "D, d M yy",
+ RFC_2822: "D, d M yy",
+ RSS: "D, d M y", // RFC 822
+ TICKS: "!",
+ TIMESTAMP: "@",
+ W3C: "yy-mm-dd", // ISO 8601
+
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
+
+ /* Format a date object into a string value.
+ * The format can be combinations of the following:
+ * d - day of month (no leading zero)
+ * dd - day of month (two digit)
+ * o - day of year (no leading zeros)
+ * oo - day of year (three digit)
+ * D - day name short
+ * DD - day name long
+ * m - month of year (no leading zero)
+ * mm - month of year (two digit)
+ * M - month name short
+ * MM - month name long
+ * y - year (two digit)
+ * yy - year (four digit)
+ * @ - Unix timestamp (ms since 01/01/1970)
+ * ! - Windows ticks (100ns since 01/01/0001)
+ * "..." - literal text
+ * '' - single quote
+ *
+ * @param format string - the desired format of the date
+ * @param date Date - the date value to format
+ * @param settings Object - attributes include:
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
+ * dayNames string[7] - names of the days from Sunday (optional)
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
+ * monthNames string[12] - names of the months (optional)
+ * @return string - the date in the above format
+ */
+ formatDate: function (format, date, settings) {
+ if (!date) {
+ return "";
+ }
+
+ var iFormat,
+ dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
+ dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
+ monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
+ monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
+ // Check whether a format character is doubled
+ lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
+ if (matches) {
+ iFormat++;
+ }
+ return matches;
+ },
+ // Format a number, with leading zero if necessary
+ formatNumber = function(match, value, len) {
+ var num = "" + value;
+ if (lookAhead(match)) {
+ while (num.length < len) {
+ num = "0" + num;
+ }
+ }
+ return num;
+ },
+ // Format a name, short or long as requested
+ formatName = function(match, value, shortNames, longNames) {
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
+ },
+ output = "",
+ literal = false;
+
+ if (date) {
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
+ if (literal) {
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
+ literal = false;
+ } else {
+ output += format.charAt(iFormat);
+ }
+ } else {
+ switch (format.charAt(iFormat)) {
+ case "d":
+ output += formatNumber("d", date.getDate(), 2);
+ break;
+ case "D":
+ output += formatName("D", date.getDay(), dayNamesShort, dayNames);
+ break;
+ case "o":
+ output += formatNumber("o",
+ Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
+ break;
+ case "m":
+ output += formatNumber("m", date.getMonth() + 1, 2);
+ break;
+ case "M":
+ output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
+ break;
+ case "y":
+ output += (lookAhead("y") ? date.getFullYear() :
+ (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
+ break;
+ case "@":
+ output += date.getTime();
+ break;
+ case "!":
+ output += date.getTime() * 10000 + this._ticksTo1970;
+ break;
+ case "'":
+ if (lookAhead("'")) {
+ output += "'";
+ } else {
+ literal = true;
+ }
+ break;
+ default:
+ output += format.charAt(iFormat);
+ }
+ }
+ }
+ }
+ return output;
+ },
+
+ /* Extract all possible characters from the date format. */
+ _possibleChars: function (format) {
+ var iFormat,
+ chars = "",
+ literal = false,
+ // Check whether a format character is doubled
+ lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
+ if (matches) {
+ iFormat++;
+ }
+ return matches;
+ };
+
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
+ if (literal) {
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
+ literal = false;
+ } else {
+ chars += format.charAt(iFormat);
+ }
+ } else {
+ switch (format.charAt(iFormat)) {
+ case "d": case "m": case "y": case "@":
+ chars += "0123456789";
+ break;
+ case "D": case "M":
+ return null; // Accept anything
+ case "'":
+ if (lookAhead("'")) {
+ chars += "'";
+ } else {
+ literal = true;
+ }
+ break;
+ default:
+ chars += format.charAt(iFormat);
+ }
+ }
+ }
+ return chars;
+ },
+
+ /* Get a setting value, defaulting if necessary. */
+ _get: function(inst, name) {
+ return inst.settings[name] !== undefined ?
+ inst.settings[name] : this._defaults[name];
+ },
+
+ /* Parse existing date and initialise date picker. */
+ _setDateFromField: function(inst, noDefault) {
+ if (inst.input.val() === inst.lastVal) {
+ return;
+ }
+
+ var dateFormat = this._get(inst, "dateFormat"),
+ dates = inst.lastVal = inst.input ? inst.input.val() : null,
+ defaultDate = this._getDefaultDate(inst),
+ date = defaultDate,
+ settings = this._getFormatConfig(inst);
+
+ try {
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+ } catch (event) {
+ dates = (noDefault ? "" : dates);
+ }
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ inst.currentDay = (dates ? date.getDate() : 0);
+ inst.currentMonth = (dates ? date.getMonth() : 0);
+ inst.currentYear = (dates ? date.getFullYear() : 0);
+ this._adjustInstDate(inst);
+ },
+
+ /* Retrieve the default date shown on opening. */
+ _getDefaultDate: function(inst) {
+ return this._restrictMinMax(inst,
+ this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
+ },
+
+ /* A date may be specified as an exact value or a relative one. */
+ _determineDate: function(inst, date, defaultDate) {
+ var offsetNumeric = function(offset) {
+ var date = new Date();
+ date.setDate(date.getDate() + offset);
+ return date;
+ },
+ offsetString = function(offset) {
+ try {
+ return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
+ offset, $.datepicker._getFormatConfig(inst));
+ }
+ catch (e) {
+ // Ignore
+ }
+
+ var date = (offset.toLowerCase().match(/^c/) ?
+ $.datepicker._getDate(inst) : null) || new Date(),
+ year = date.getFullYear(),
+ month = date.getMonth(),
+ day = date.getDate(),
+ pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
+ matches = pattern.exec(offset);
+
+ while (matches) {
+ switch (matches[2] || "d") {
+ case "d" : case "D" :
+ day += parseInt(matches[1],10); break;
+ case "w" : case "W" :
+ day += parseInt(matches[1],10) * 7; break;
+ case "m" : case "M" :
+ month += parseInt(matches[1],10);
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+ break;
+ case "y": case "Y" :
+ year += parseInt(matches[1],10);
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+ break;
+ }
+ matches = pattern.exec(offset);
+ }
+ return new Date(year, month, day);
+ },
+ newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
+ (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
+
+ newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
+ if (newDate) {
+ newDate.setHours(0);
+ newDate.setMinutes(0);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ }
+ return this._daylightSavingAdjust(newDate);
+ },
+
+ /* Handle switch to/from daylight saving.
+ * Hours may be non-zero on daylight saving cut-over:
+ * > 12 when midnight changeover, but then cannot generate
+ * midnight datetime, so jump to 1AM, otherwise reset.
+ * @param date (Date) the date to check
+ * @return (Date) the corrected date
+ */
+ _daylightSavingAdjust: function(date) {
+ if (!date) {
+ return null;
+ }
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+ return date;
+ },
+
+ /* Set the date(s) directly. */
+ _setDate: function(inst, date, noChange) {
+ var clear = !date,
+ origMonth = inst.selectedMonth,
+ origYear = inst.selectedYear,
+ newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
+
+ inst.selectedDay = inst.currentDay = newDate.getDate();
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
+ if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
+ this._notifyChange(inst);
+ }
+ this._adjustInstDate(inst);
+ if (inst.input) {
+ inst.input.val(clear ? "" : this._formatDate(inst));
+ }
+ },
+
+ /* Retrieve the date(s) directly. */
+ _getDate: function(inst) {
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
+ this._daylightSavingAdjust(new Date(
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
+ return startDate;
+ },
+
+ /* Attach the onxxx handlers. These are declared statically so
+ * they work with static code transformers like Caja.
+ */
+ _attachHandlers: function(inst) {
+ var stepMonths = this._get(inst, "stepMonths"),
+ id = "#" + inst.id.replace( /\\\\/g, "\\" );
+ inst.dpDiv.find("[data-handler]").map(function () {
+ var handler = {
+ prev: function () {
+ $.datepicker._adjustDate(id, -stepMonths, "M");
+ },
+ next: function () {
+ $.datepicker._adjustDate(id, +stepMonths, "M");
+ },
+ hide: function () {
+ $.datepicker._hideDatepicker();
+ },
+ today: function () {
+ $.datepicker._gotoToday(id);
+ },
+ selectDay: function () {
+ $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
+ return false;
+ },
+ selectMonth: function () {
+ $.datepicker._selectMonthYear(id, this, "M");
+ return false;
+ },
+ selectYear: function () {
+ $.datepicker._selectMonthYear(id, this, "Y");
+ return false;
+ }
+ };
+ $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
+ });
+ },
+
+ /* Generate the HTML for the current state of the date picker. */
+ _generateHTML: function(inst) {
+ var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
+ controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
+ monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
+ selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
+ cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
+ printDate, dRow, tbody, daySettings, otherMonth, unselectable,
+ tempDate = new Date(),
+ today = this._daylightSavingAdjust(
+ new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
+ isRTL = this._get(inst, "isRTL"),
+ showButtonPanel = this._get(inst, "showButtonPanel"),
+ hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
+ navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
+ numMonths = this._getNumberOfMonths(inst),
+ showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
+ stepMonths = this._get(inst, "stepMonths"),
+ isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
+ currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
+ minDate = this._getMinMaxDate(inst, "min"),
+ maxDate = this._getMinMaxDate(inst, "max"),
+ drawMonth = inst.drawMonth - showCurrentAtPos,
+ drawYear = inst.drawYear;
+
+ if (drawMonth < 0) {
+ drawMonth += 12;
+ drawYear--;
+ }
+ if (maxDate) {
+ maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
+ drawMonth--;
+ if (drawMonth < 0) {
+ drawMonth = 11;
+ drawYear--;
+ }
+ }
+ }
+ inst.drawMonth = drawMonth;
+ inst.drawYear = drawYear;
+
+ prevText = this._get(inst, "prevText");
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
+ this._getFormatConfig(inst)));
+
+ prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
+ "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
+ " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
+ (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
+
+ nextText = this._get(inst, "nextText");
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
+ this._getFormatConfig(inst)));
+
+ next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
+ "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
+ " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
+ (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
+
+ currentText = this._get(inst, "currentText");
+ gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
+ currentText = (!navigationAsDateFormat ? currentText :
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
+
+ controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
+ this._get(inst, "closeText") + "</button>" : "");
+
+ buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
+ (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
+ ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
+
+ firstDay = parseInt(this._get(inst, "firstDay"),10);
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
+
+ showWeek = this._get(inst, "showWeek");
+ dayNames = this._get(inst, "dayNames");
+ dayNamesMin = this._get(inst, "dayNamesMin");
+ monthNames = this._get(inst, "monthNames");
+ monthNamesShort = this._get(inst, "monthNamesShort");
+ beforeShowDay = this._get(inst, "beforeShowDay");
+ showOtherMonths = this._get(inst, "showOtherMonths");
+ selectOtherMonths = this._get(inst, "selectOtherMonths");
+ defaultDate = this._getDefaultDate(inst);
+ html = "";
+ dow;
+ for (row = 0; row < numMonths[0]; row++) {
+ group = "";
+ this.maxRows = 4;
+ for (col = 0; col < numMonths[1]; col++) {
+ selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
+ cornerClass = " ui-corner-all";
+ calender = "";
+ if (isMultiMonth) {
+ calender += "<div class='ui-datepicker-group";
+ if (numMonths[1] > 1) {
+ switch (col) {
+ case 0: calender += " ui-datepicker-group-first";
+ cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
+ case numMonths[1]-1: calender += " ui-datepicker-group-last";
+ cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
+ default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
+ }
+ }
+ calender += "'>";
+ }
+ calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
+ (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
+ (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+ "</div><table class='ui-datepicker-calendar'><thead>" +
+ "<tr>";
+ thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
+ for (dow = 0; dow < 7; dow++) { // days of the week
+ day = (dow + firstDay) % 7;
+ thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
+ "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
+ }
+ calender += thead + "</tr></thead><tbody>";
+ daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
+ if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
+ }
+ leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
+ curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
+ numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
+ this.maxRows = numRows;
+ printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
+ for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
+ calender += "<tr>";
+ tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
+ this._get(inst, "calculateWeek")(printDate) + "</td>");
+ for (dow = 0; dow < 7; dow++) { // create date picker days
+ daySettings = (beforeShowDay ?
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
+ otherMonth = (printDate.getMonth() !== drawMonth);
+ unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
+ tbody += "<td class='" +
+ ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
+ (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
+ ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
+ (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
+ // or defaultDate is current printedDate and defaultDate is selectedDate
+ " " + this._dayOverClass : "") + // highlight selected day
+ (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
+ (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
+ (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
+ (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title
+ (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
+ (otherMonth && !showOtherMonths ? " " : // display for other months
+ (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
+ (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
+ (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
+ (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
+ "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
+ printDate.setDate(printDate.getDate() + 1);
+ printDate = this._daylightSavingAdjust(printDate);
+ }
+ calender += tbody + "</tr>";
+ }
+ drawMonth++;
+ if (drawMonth > 11) {
+ drawMonth = 0;
+ drawYear++;
+ }
+ calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
+ ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
+ group += calender;
+ }
+ html += group;
+ }
+ html += buttonPanel;
+ inst._keyEvent = false;
+ return html;
+ },
+
+ /* Generate the month and year header. */
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
+ secondary, monthNames, monthNamesShort) {
+
+ var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
+ changeMonth = this._get(inst, "changeMonth"),
+ changeYear = this._get(inst, "changeYear"),
+ showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
+ html = "<div class='ui-datepicker-title'>",
+ monthHtml = "";
+
+ // month selection
+ if (secondary || !changeMonth) {
+ monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
+ } else {
+ inMinYear = (minDate && minDate.getFullYear() === drawYear);
+ inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
+ monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
+ for ( month = 0; month < 12; month++) {
+ if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
+ monthHtml += "<option value='" + month + "'" +
+ (month === drawMonth ? " selected='selected'" : "") +
+ ">" + monthNamesShort[month] + "</option>";
+ }
+ }
+ monthHtml += "</select>";
+ }
+
+ if (!showMonthAfterYear) {
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
+ }
+
+ // year selection
+ if ( !inst.yearshtml ) {
+ inst.yearshtml = "";
+ if (secondary || !changeYear) {
+ html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
+ } else {
+ // determine range of years to display
+ years = this._get(inst, "yearRange").split(":");
+ thisYear = new Date().getFullYear();
+ determineYear = function(value) {
+ var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
+ (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
+ parseInt(value, 10)));
+ return (isNaN(year) ? thisYear : year);
+ };
+ year = determineYear(years[0]);
+ endYear = Math.max(year, determineYear(years[1] || ""));
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+ inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
+ for (; year <= endYear; year++) {
+ inst.yearshtml += "<option value='" + year + "'" +
+ (year === drawYear ? " selected='selected'" : "") +
+ ">" + year + "</option>";
+ }
+ inst.yearshtml += "</select>";
+
+ html += inst.yearshtml;
+ inst.yearshtml = null;
+ }
+ }
+
+ html += this._get(inst, "yearSuffix");
+ if (showMonthAfterYear) {
+ html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
+ }
+ html += "</div>"; // Close datepicker_header
+ return html;
+ },
+
+ /* Adjust one of the date sub-fields. */
+ _adjustInstDate: function(inst, offset, period) {
+ var year = inst.drawYear + (period === "Y" ? offset : 0),
+ month = inst.drawMonth + (period === "M" ? offset : 0),
+ day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
+ date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
+
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ if (period === "M" || period === "Y") {
+ this._notifyChange(inst);
+ }
+ },
+
+ /* Ensure a date is within any min/max bounds. */
+ _restrictMinMax: function(inst, date) {
+ var minDate = this._getMinMaxDate(inst, "min"),
+ maxDate = this._getMinMaxDate(inst, "max"),
+ newDate = (minDate && date < minDate ? minDate : date);
+ return (maxDate && newDate > maxDate ? maxDate : newDate);
+ },
+
+ /* Notify change of month/year. */
+ _notifyChange: function(inst) {
+ var onChange = this._get(inst, "onChangeMonthYear");
+ if (onChange) {
+ onChange.apply((inst.input ? inst.input[0] : null),
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
+ }
+ },
+
+ /* Determine the number of months to show. */
+ _getNumberOfMonths: function(inst) {
+ var numMonths = this._get(inst, "numberOfMonths");
+ return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
+ },
+
+ /* Determine the current maximum date - ensure no time components are set. */
+ _getMinMaxDate: function(inst, minMax) {
+ return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
+ },
+
+ /* Find the number of days in a given month. */
+ _getDaysInMonth: function(year, month) {
+ return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
+ },
+
+ /* Find the day of the week of the first of a month. */
+ _getFirstDayOfMonth: function(year, month) {
+ return new Date(year, month, 1).getDay();
+ },
+
+ /* Determines if we should allow a "next/prev" month display change. */
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
+ var numMonths = this._getNumberOfMonths(inst),
+ date = this._daylightSavingAdjust(new Date(curYear,
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
+
+ if (offset < 0) {
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
+ }
+ return this._isInRange(inst, date);
+ },
+
+ /* Is the given date in the accepted range? */
+ _isInRange: function(inst, date) {
+ var yearSplit, currentYear,
+ minDate = this._getMinMaxDate(inst, "min"),
+ maxDate = this._getMinMaxDate(inst, "max"),
+ minYear = null,
+ maxYear = null,
+ years = this._get(inst, "yearRange");
+ if (years){
+ yearSplit = years.split(":");
+ currentYear = new Date().getFullYear();
+ minYear = parseInt(yearSplit[0], 10);
+ maxYear = parseInt(yearSplit[1], 10);
+ if ( yearSplit[0].match(/[+\-].*/) ) {
+ minYear += currentYear;
+ }
+ if ( yearSplit[1].match(/[+\-].*/) ) {
+ maxYear += currentYear;
+ }
+ }
+
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
+ (!maxDate || date.getTime() <= maxDate.getTime()) &&
+ (!minYear || date.getFullYear() >= minYear) &&
+ (!maxYear || date.getFullYear() <= maxYear));
+ },
+
+ /* Provide the configuration settings for formatting/parsing. */
+ _getFormatConfig: function(inst) {
+ var shortYearCutoff = this._get(inst, "shortYearCutoff");
+ shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+ return {shortYearCutoff: shortYearCutoff,
+ dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
+ monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
+ },
+
+ /* Format the given date for display. */
+ _formatDate: function(inst, day, month, year) {
+ if (!day) {
+ inst.currentDay = inst.selectedDay;
+ inst.currentMonth = inst.selectedMonth;
+ inst.currentYear = inst.selectedYear;
+ }
+ var date = (day ? (typeof day === "object" ? day :
+ this._daylightSavingAdjust(new Date(year, month, day))) :
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+ return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
+ }
+});
+
+/*
+ * Bind hover events for datepicker elements.
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
+ */
+function bindHover(dpDiv) {
+ var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
+ return dpDiv.delegate(selector, "mouseout", function() {
+ $(this).removeClass("ui-state-hover");
+ if (this.className.indexOf("ui-datepicker-prev") !== -1) {
+ $(this).removeClass("ui-datepicker-prev-hover");
+ }
+ if (this.className.indexOf("ui-datepicker-next") !== -1) {
+ $(this).removeClass("ui-datepicker-next-hover");
+ }
+ })
+ .delegate(selector, "mouseover", function(){
+ if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
+ $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
+ $(this).addClass("ui-state-hover");
+ if (this.className.indexOf("ui-datepicker-prev") !== -1) {
+ $(this).addClass("ui-datepicker-prev-hover");
+ }
+ if (this.className.indexOf("ui-datepicker-next") !== -1) {
+ $(this).addClass("ui-datepicker-next-hover");
+ }
+ }
+ });
+}
+
+/* jQuery extend now ignores nulls! */
+function extendRemove(target, props) {
+ $.extend(target, props);
+ for (var name in props) {
+ if (props[name] == null) {
+ target[name] = props[name];
+ }
+ }
+ return target;
+}
+
+/* Invoke the datepicker functionality.
+ @param options string - a command, optionally followed by additional parameters or
+ Object - settings for attaching new datepicker functionality
+ @return jQuery object */
+$.fn.datepicker = function(options){
+
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
+ if ( !this.length ) {
+ return this;
+ }
+
+ /* Initialise the date picker. */
+ if (!$.datepicker.initialized) {
+ $(document).mousedown($.datepicker._checkExternalClick);
+ $.datepicker.initialized = true;
+ }
+
+ /* Append datepicker main container to body if not exist. */
+ if ($("#"+$.datepicker._mainDivId).length === 0) {
+ $("body").append($.datepicker.dpDiv);
+ }
+
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
+ if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
+ return $.datepicker["_" + options + "Datepicker"].
+ apply($.datepicker, [this[0]].concat(otherArgs));
+ }
+ if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
+ return $.datepicker["_" + options + "Datepicker"].
+ apply($.datepicker, [this[0]].concat(otherArgs));
+ }
+ return this.each(function() {
+ typeof options === "string" ?
+ $.datepicker["_" + options + "Datepicker"].
+ apply($.datepicker, [this].concat(otherArgs)) :
+ $.datepicker._attachDatepicker(this, options);
+ });
+};
+
+$.datepicker = new Datepicker(); // singleton instance
+$.datepicker.initialized = false;
+$.datepicker.uuid = new Date().getTime();
+$.datepicker.version = "1.10.3";
+
+})(jQuery);
+(function( $, undefined ) {
+
+// number of pages in a slider
+// (how many times can you page up/down to go through the whole range)
+var numPages = 5;
+
+$.widget( "ui.slider", $.ui.mouse, {
+ version: "1.10.3",
+ widgetEventPrefix: "slide",
+
+ options: {
+ animate: false,
+ distance: 0,
+ max: 100,
+ min: 0,
+ orientation: "horizontal",
+ range: false,
+ step: 1,
+ value: 0,
+ values: null,
+
+ // callbacks
+ change: null,
+ slide: null,
+ start: null,
+ stop: null
+ },
+
+ _create: function() {
+ this._keySliding = false;
+ this._mouseSliding = false;
+ this._animateOff = true;
+ this._handleIndex = null;
+ this._detectOrientation();
+ this._mouseInit();
+
+ this.element
+ .addClass( "ui-slider" +
+ " ui-slider-" + this.orientation +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all");
+
+ this._refresh();
+ this._setOption( "disabled", this.options.disabled );
+
+ this._animateOff = false;
+ },
+
+ _refresh: function() {
+ this._createRange();
+ this._createHandles();
+ this._setupEvents();
+ this._refreshValue();
+ },
+
+ _createHandles: function() {
+ var i, handleCount,
+ options = this.options,
+ existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
+ handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
+ handles = [];
+
+ handleCount = ( options.values && options.values.length ) || 1;
+
+ if ( existingHandles.length > handleCount ) {
+ existingHandles.slice( handleCount ).remove();
+ existingHandles = existingHandles.slice( 0, handleCount );
+ }
+
+ for ( i = existingHandles.length; i < handleCount; i++ ) {
+ handles.push( handle );
+ }
+
+ this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
+
+ this.handle = this.handles.eq( 0 );
+
+ this.handles.each(function( i ) {
+ $( this ).data( "ui-slider-handle-index", i );
+ });
+ },
+
+ _createRange: function() {
+ var options = this.options,
+ classes = "";
+
+ if ( options.range ) {
+ if ( options.range === true ) {
+ if ( !options.values ) {
+ options.values = [ this._valueMin(), this._valueMin() ];
+ } else if ( options.values.length && options.values.length !== 2 ) {
+ options.values = [ options.values[0], options.values[0] ];
+ } else if ( $.isArray( options.values ) ) {
+ options.values = options.values.slice(0);
+ }
+ }
+
+ if ( !this.range || !this.range.length ) {
+ this.range = $( "<div></div>" )
+ .appendTo( this.element );
+
+ classes = "ui-slider-range" +
+ // note: this isn't the most fittingly semantic framework class for this element,
+ // but worked best visually with a variety of themes
+ " ui-widget-header ui-corner-all";
+ } else {
+ this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
+ // Handle range switching from true to min/max
+ .css({
+ "left": "",
+ "bottom": ""
+ });
+ }
+
+ this.range.addClass( classes +
+ ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
+ } else {
+ this.range = $([]);
+ }
+ },
+
+ _setupEvents: function() {
+ var elements = this.handles.add( this.range ).filter( "a" );
+ this._off( elements );
+ this._on( elements, this._handleEvents );
+ this._hoverable( elements );
+ this._focusable( elements );
+ },
+
+ _destroy: function() {
+ this.handles.remove();
+ this.range.remove();
+
+ this.element
+ .removeClass( "ui-slider" +
+ " ui-slider-horizontal" +
+ " ui-slider-vertical" +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" );
+
+ this._mouseDestroy();
+ },
+
+ _mouseCapture: function( event ) {
+ var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
+ that = this,
+ o = this.options;
+
+ if ( o.disabled ) {
+ return false;
+ }
+
+ this.elementSize = {
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight()
+ };
+ this.elementOffset = this.element.offset();
+
+ position = { x: event.pageX, y: event.pageY };
+ normValue = this._normValueFromMouse( position );
+ distance = this._valueMax() - this._valueMin() + 1;
+ this.handles.each(function( i ) {
+ var thisDistance = Math.abs( normValue - that.values(i) );
+ if (( distance > thisDistance ) ||
+ ( distance === thisDistance &&
+ (i === that._lastChangedValue || that.values(i) === o.min ))) {
+ distance = thisDistance;
+ closestHandle = $( this );
+ index = i;
+ }
+ });
+
+ allowed = this._start( event, index );
+ if ( allowed === false ) {
+ return false;
+ }
+ this._mouseSliding = true;
+
+ this._handleIndex = index;
+
+ closestHandle
+ .addClass( "ui-state-active" )
+ .focus();
+
+ offset = closestHandle.offset();
+ mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
+ this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
+ top: event.pageY - offset.top -
+ ( closestHandle.height() / 2 ) -
+ ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
+ ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
+ ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
+ };
+
+ if ( !this.handles.hasClass( "ui-state-hover" ) ) {
+ this._slide( event, index, normValue );
+ }
+ this._animateOff = true;
+ return true;
+ },
+
+ _mouseStart: function() {
+ return true;
+ },
+
+ _mouseDrag: function( event ) {
+ var position = { x: event.pageX, y: event.pageY },
+ normValue = this._normValueFromMouse( position );
+
+ this._slide( event, this._handleIndex, normValue );
+
+ return false;
+ },
+
+ _mouseStop: function( event ) {
+ this.handles.removeClass( "ui-state-active" );
+ this._mouseSliding = false;
+
+ this._stop( event, this._handleIndex );
+ this._change( event, this._handleIndex );
+
+ this._handleIndex = null;
+ this._clickOffset = null;
+ this._animateOff = false;
+
+ return false;
+ },
+
+ _detectOrientation: function() {
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
+ },
+
+ _normValueFromMouse: function( position ) {
+ var pixelTotal,
+ pixelMouse,
+ percentMouse,
+ valueTotal,
+ valueMouse;
+
+ if ( this.orientation === "horizontal" ) {
+ pixelTotal = this.elementSize.width;
+ pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
+ } else {
+ pixelTotal = this.elementSize.height;
+ pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
+ }
+
+ percentMouse = ( pixelMouse / pixelTotal );
+ if ( percentMouse > 1 ) {
+ percentMouse = 1;
+ }
+ if ( percentMouse < 0 ) {
+ percentMouse = 0;
+ }
+ if ( this.orientation === "vertical" ) {
+ percentMouse = 1 - percentMouse;
+ }
+
+ valueTotal = this._valueMax() - this._valueMin();
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
+
+ return this._trimAlignValue( valueMouse );
+ },
+
+ _start: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+ return this._trigger( "start", event, uiHash );
+ },
+
+ _slide: function( event, index, newVal ) {
+ var otherVal,
+ newValues,
+ allowed;
+
+ if ( this.options.values && this.options.values.length ) {
+ otherVal = this.values( index ? 0 : 1 );
+
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
+ ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
+ ) {
+ newVal = otherVal;
+ }
+
+ if ( newVal !== this.values( index ) ) {
+ newValues = this.values();
+ newValues[ index ] = newVal;
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal,
+ values: newValues
+ } );
+ otherVal = this.values( index ? 0 : 1 );
+ if ( allowed !== false ) {
+ this.values( index, newVal, true );
+ }
+ }
+ } else {
+ if ( newVal !== this.value() ) {
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal
+ } );
+ if ( allowed !== false ) {
+ this.value( newVal );
+ }
+ }
+ }
+ },
+
+ _stop: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "stop", event, uiHash );
+ },
+
+ _change: function( event, index ) {
+ if ( !this._keySliding && !this._mouseSliding ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ //store the last changed value index for reference when handles overlap
+ this._lastChangedValue = index;
+
+ this._trigger( "change", event, uiHash );
+ }
+ },
+
+ value: function( newValue ) {
+ if ( arguments.length ) {
+ this.options.value = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, 0 );
+ return;
+ }
+
+ return this._value();
+ },
+
+ values: function( index, newValue ) {
+ var vals,
+ newValues,
+ i;
+
+ if ( arguments.length > 1 ) {
+ this.options.values[ index ] = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, index );
+ return;
+ }
+
+ if ( arguments.length ) {
+ if ( $.isArray( arguments[ 0 ] ) ) {
+ vals = this.options.values;
+ newValues = arguments[ 0 ];
+ for ( i = 0; i < vals.length; i += 1 ) {
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
+ this._change( null, i );
+ }
+ this._refreshValue();
+ } else {
+ if ( this.options.values && this.options.values.length ) {
+ return this._values( index );
+ } else {
+ return this.value();
+ }
+ }
+ } else {
+ return this._values();
+ }
+ },
+
+ _setOption: function( key, value ) {
+ var i,
+ valsLength = 0;
+
+ if ( key === "range" && this.options.range === true ) {
+ if ( value === "min" ) {
+ this.options.value = this._values( 0 );
+ this.options.values = null;
+ } else if ( value === "max" ) {
+ this.options.value = this._values( this.options.values.length-1 );
+ this.options.values = null;
+ }
+ }
+
+ if ( $.isArray( this.options.values ) ) {
+ valsLength = this.options.values.length;
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+
+ switch ( key ) {
+ case "orientation":
+ this._detectOrientation();
+ this.element
+ .removeClass( "ui-slider-horizontal ui-slider-vertical" )
+ .addClass( "ui-slider-" + this.orientation );
+ this._refreshValue();
+ break;
+ case "value":
+ this._animateOff = true;
+ this._refreshValue();
+ this._change( null, 0 );
+ this._animateOff = false;
+ break;
+ case "values":
+ this._animateOff = true;
+ this._refreshValue();
+ for ( i = 0; i < valsLength; i += 1 ) {
+ this._change( null, i );
+ }
+ this._animateOff = false;
+ break;
+ case "min":
+ case "max":
+ this._animateOff = true;
+ this._refreshValue();
+ this._animateOff = false;
+ break;
+ case "range":
+ this._animateOff = true;
+ this._refresh();
+ this._animateOff = false;
+ break;
+ }
+ },
+
+ //internal value getter
+ // _value() returns value trimmed by min and max, aligned by step
+ _value: function() {
+ var val = this.options.value;
+ val = this._trimAlignValue( val );
+
+ return val;
+ },
+
+ //internal values getter
+ // _values() returns array of values trimmed by min and max, aligned by step
+ // _values( index ) returns single value trimmed by min and max, aligned by step
+ _values: function( index ) {
+ var val,
+ vals,
+ i;
+
+ if ( arguments.length ) {
+ val = this.options.values[ index ];
+ val = this._trimAlignValue( val );
+
+ return val;
+ } else if ( this.options.values && this.options.values.length ) {
+ // .slice() creates a copy of the array
+ // this copy gets trimmed by min and max and then returned
+ vals = this.options.values.slice();
+ for ( i = 0; i < vals.length; i+= 1) {
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
+ }
+
+ return vals;
+ } else {
+ return [];
+ }
+ },
+
+ // returns the step-aligned value that val is closest to, between (inclusive) min and max
+ _trimAlignValue: function( val ) {
+ if ( val <= this._valueMin() ) {
+ return this._valueMin();
+ }
+ if ( val >= this._valueMax() ) {
+ return this._valueMax();
+ }
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
+ valModStep = (val - this._valueMin()) % step,
+ alignValue = val - valModStep;
+
+ if ( Math.abs(valModStep) * 2 >= step ) {
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
+ }
+
+ // Since JavaScript has problems with large floats, round
+ // the final value to 5 digits after the decimal point (see #4124)
+ return parseFloat( alignValue.toFixed(5) );
+ },
+
+ _valueMin: function() {
+ return this.options.min;
+ },
+
+ _valueMax: function() {
+ return this.options.max;
+ },
+
+ _refreshValue: function() {
+ var lastValPercent, valPercent, value, valueMin, valueMax,
+ oRange = this.options.range,
+ o = this.options,
+ that = this,
+ animate = ( !this._animateOff ) ? o.animate : false,
+ _set = {};
+
+ if ( this.options.values && this.options.values.length ) {
+ this.handles.each(function( i ) {
+ valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
+ _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+ if ( that.options.range === true ) {
+ if ( that.orientation === "horizontal" ) {
+ if ( i === 0 ) {
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ } else {
+ if ( i === 0 ) {
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ }
+ lastValPercent = valPercent;
+ });
+ } else {
+ value = this.value();
+ valueMin = this._valueMin();
+ valueMax = this._valueMax();
+ valPercent = ( valueMax !== valueMin ) ?
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
+ 0;
+ _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
+ this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ if ( oRange === "min" && this.orientation === "vertical" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "vertical" ) {
+ this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ },
+
+ _handleEvents: {
+ keydown: function( event ) {
+ /*jshint maxcomplexity:25*/
+ var allowed, curVal, newVal, step,
+ index = $( event.target ).data( "ui-slider-handle-index" );
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ case $.ui.keyCode.END:
+ case $.ui.keyCode.PAGE_UP:
+ case $.ui.keyCode.PAGE_DOWN:
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ event.preventDefault();
+ if ( !this._keySliding ) {
+ this._keySliding = true;
+ $( event.target ).addClass( "ui-state-active" );
+ allowed = this._start( event, index );
+ if ( allowed === false ) {
+ return;
+ }
+ }
+ break;
+ }
+
+ step = this.options.step;
+ if ( this.options.values && this.options.values.length ) {
+ curVal = newVal = this.values( index );
+ } else {
+ curVal = newVal = this.value();
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ newVal = this._valueMin();
+ break;
+ case $.ui.keyCode.END:
+ newVal = this._valueMax();
+ break;
+ case $.ui.keyCode.PAGE_UP:
+ newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ if ( curVal === this._valueMax() ) {
+ return;
+ }
+ newVal = this._trimAlignValue( curVal + step );
+ break;
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ if ( curVal === this._valueMin() ) {
+ return;
+ }
+ newVal = this._trimAlignValue( curVal - step );
+ break;
+ }
+
+ this._slide( event, index, newVal );
+ },
+ click: function( event ) {
+ event.preventDefault();
+ },
+ keyup: function( event ) {
+ var index = $( event.target ).data( "ui-slider-handle-index" );
+
+ if ( this._keySliding ) {
+ this._keySliding = false;
+ this._stop( event, index );
+ this._change( event, index );
+ $( event.target ).removeClass( "ui-state-active" );
+ }
+ }
+ }
+
+});
+
+}(jQuery));
+(function( $ ) {
+
+function modifier( fn ) {
+ return function() {
+ var previous = this.element.val();
+ fn.apply( this, arguments );
+ this._refresh();
+ if ( previous !== this.element.val() ) {
+ this._trigger( "change" );
+ }
+ };
+}
+
+$.widget( "ui.spinner", {
+ version: "1.10.3",
+ defaultElement: "<input>",
+ widgetEventPrefix: "spin",
+ options: {
+ culture: null,
+ icons: {
+ down: "ui-icon-triangle-1-s",
+ up: "ui-icon-triangle-1-n"
+ },
+ incremental: true,
+ max: null,
+ min: null,
+ numberFormat: null,
+ page: 10,
+ step: 1,
+
+ change: null,
+ spin: null,
+ start: null,
+ stop: null
+ },
+
+ _create: function() {
+ // handle string values that need to be parsed
+ this._setOption( "max", this.options.max );
+ this._setOption( "min", this.options.min );
+ this._setOption( "step", this.options.step );
+
+ // format the value, but don't constrain
+ this._value( this.element.val(), true );
+
+ this._draw();
+ this._on( this._events );
+ this._refresh();
+
+ // turning off autocomplete prevents the browser from remembering the
+ // value when navigating through history, so we re-enable autocomplete
+ // if the page is unloaded before the widget is destroyed. #7790
+ this._on( this.window, {
+ beforeunload: function() {
+ this.element.removeAttr( "autocomplete" );
+ }
+ });
+ },
+
+ _getCreateOptions: function() {
+ var options = {},
+ element = this.element;
+
+ $.each( [ "min", "max", "step" ], function( i, option ) {
+ var value = element.attr( option );
+ if ( value !== undefined && value.length ) {
+ options[ option ] = value;
+ }
+ });
+
+ return options;
+ },
+
+ _events: {
+ keydown: function( event ) {
+ if ( this._start( event ) && this._keydown( event ) ) {
+ event.preventDefault();
+ }
+ },
+ keyup: "_stop",
+ focus: function() {
+ this.previous = this.element.val();
+ },
+ blur: function( event ) {
+ if ( this.cancelBlur ) {
+ delete this.cancelBlur;
+ return;
+ }
+
+ this._stop();
+ this._refresh();
+ if ( this.previous !== this.element.val() ) {
+ this._trigger( "change", event );
+ }
+ },
+ mousewheel: function( event, delta ) {
+ if ( !delta ) {
+ return;
+ }
+ if ( !this.spinning && !this._start( event ) ) {
+ return false;
+ }
+
+ this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
+ clearTimeout( this.mousewheelTimer );
+ this.mousewheelTimer = this._delay(function() {
+ if ( this.spinning ) {
+ this._stop( event );
+ }
+ }, 100 );
+ event.preventDefault();
+ },
+ "mousedown .ui-spinner-button": function( event ) {
+ var previous;
+
+ // We never want the buttons to have focus; whenever the user is
+ // interacting with the spinner, the focus should be on the input.
+ // If the input is focused then this.previous is properly set from
+ // when the input first received focus. If the input is not focused
+ // then we need to set this.previous based on the value before spinning.
+ previous = this.element[0] === this.document[0].activeElement ?
+ this.previous : this.element.val();
+ function checkFocus() {
+ var isActive = this.element[0] === this.document[0].activeElement;
+ if ( !isActive ) {
+ this.element.focus();
+ this.previous = previous;
+ // support: IE
+ // IE sets focus asynchronously, so we need to check if focus
+ // moved off of the input because the user clicked on the button.
+ this._delay(function() {
+ this.previous = previous;
+ });
+ }
+ }
+
+ // ensure focus is on (or stays on) the text field
+ event.preventDefault();
+ checkFocus.call( this );
+
+ // support: IE
+ // IE doesn't prevent moving focus even with event.preventDefault()
+ // so we set a flag to know when we should ignore the blur event
+ // and check (again) if focus moved off of the input.
+ this.cancelBlur = true;
+ this._delay(function() {
+ delete this.cancelBlur;
+ checkFocus.call( this );
+ });
+
+ if ( this._start( event ) === false ) {
+ return;
+ }
+
+ this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
+ },
+ "mouseup .ui-spinner-button": "_stop",
+ "mouseenter .ui-spinner-button": function( event ) {
+ // button will add ui-state-active if mouse was down while mouseleave and kept down
+ if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
+ return;
+ }
+
+ if ( this._start( event ) === false ) {
+ return false;
+ }
+ this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
+ },
+ // TODO: do we really want to consider this a stop?
+ // shouldn't we just stop the repeater and wait until mouseup before
+ // we trigger the stop event?
+ "mouseleave .ui-spinner-button": "_stop"
+ },
+
+ _draw: function() {
+ var uiSpinner = this.uiSpinner = this.element
+ .addClass( "ui-spinner-input" )
+ .attr( "autocomplete", "off" )
+ .wrap( this._uiSpinnerHtml() )
+ .parent()
+ // add buttons
+ .append( this._buttonHtml() );
+
+ this.element.attr( "role", "spinbutton" );
+
+ // button bindings
+ this.buttons = uiSpinner.find( ".ui-spinner-button" )
+ .attr( "tabIndex", -1 )
+ .button()
+ .removeClass( "ui-corner-all" );
+
+ // IE 6 doesn't understand height: 50% for the buttons
+ // unless the wrapper has an explicit height
+ if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
+ uiSpinner.height() > 0 ) {
+ uiSpinner.height( uiSpinner.height() );
+ }
+
+ // disable spinner if element was already disabled
+ if ( this.options.disabled ) {
+ this.disable();
+ }
+ },
+
+ _keydown: function( event ) {
+ var options = this.options,
+ keyCode = $.ui.keyCode;
+
+ switch ( event.keyCode ) {
+ case keyCode.UP:
+ this._repeat( null, 1, event );
+ return true;
+ case keyCode.DOWN:
+ this._repeat( null, -1, event );
+ return true;
+ case keyCode.PAGE_UP:
+ this._repeat( null, options.page, event );
+ return true;
+ case keyCode.PAGE_DOWN:
+ this._repeat( null, -options.page, event );
+ return true;
+ }
+
+ return false;
+ },
+
+ _uiSpinnerHtml: function() {
+ return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
+ },
+
+ _buttonHtml: function() {
+ return "" +
+ "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
+ "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" +
+ "</a>" +
+ "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
+ "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" +
+ "</a>";
+ },
+
+ _start: function( event ) {
+ if ( !this.spinning && this._trigger( "start", event ) === false ) {
+ return false;
+ }
+
+ if ( !this.counter ) {
+ this.counter = 1;
+ }
+ this.spinning = true;
+ return true;
+ },
+
+ _repeat: function( i, steps, event ) {
+ i = i || 500;
+
+ clearTimeout( this.timer );
+ this.timer = this._delay(function() {
+ this._repeat( 40, steps, event );
+ }, i );
+
+ this._spin( steps * this.options.step, event );
+ },
+
+ _spin: function( step, event ) {
+ var value = this.value() || 0;
+
+ if ( !this.counter ) {
+ this.counter = 1;
+ }
+
+ value = this._adjustValue( value + step * this._increment( this.counter ) );
+
+ if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
+ this._value( value );
+ this.counter++;
+ }
+ },
+
+ _increment: function( i ) {
+ var incremental = this.options.incremental;
+
+ if ( incremental ) {
+ return $.isFunction( incremental ) ?
+ incremental( i ) :
+ Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
+ }
+
+ return 1;
+ },
+
+ _precision: function() {
+ var precision = this._precisionOf( this.options.step );
+ if ( this.options.min !== null ) {
+ precision = Math.max( precision, this._precisionOf( this.options.min ) );
+ }
+ return precision;
+ },
+
+ _precisionOf: function( num ) {
+ var str = num.toString(),
+ decimal = str.indexOf( "." );
+ return decimal === -1 ? 0 : str.length - decimal - 1;
+ },
+
+ _adjustValue: function( value ) {
+ var base, aboveMin,
+ options = this.options;
+
+ // make sure we're at a valid step
+ // - find out where we are relative to the base (min or 0)
+ base = options.min !== null ? options.min : 0;
+ aboveMin = value - base;
+ // - round to the nearest step
+ aboveMin = Math.round(aboveMin / options.step) * options.step;
+ // - rounding is based on 0, so adjust back to our base
+ value = base + aboveMin;
+
+ // fix precision from bad JS floating point math
+ value = parseFloat( value.toFixed( this._precision() ) );
+
+ // clamp the value
+ if ( options.max !== null && value > options.max) {
+ return options.max;
+ }
+ if ( options.min !== null && value < options.min ) {
+ return options.min;
+ }
+
+ return value;
+ },
+
+ _stop: function( event ) {
+ if ( !this.spinning ) {
+ return;
+ }
+
+ clearTimeout( this.timer );
+ clearTimeout( this.mousewheelTimer );
+ this.counter = 0;
+ this.spinning = false;
+ this._trigger( "stop", event );
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "culture" || key === "numberFormat" ) {
+ var prevValue = this._parse( this.element.val() );
+ this.options[ key ] = value;
+ this.element.val( this._format( prevValue ) );
+ return;
+ }
+
+ if ( key === "max" || key === "min" || key === "step" ) {
+ if ( typeof value === "string" ) {
+ value = this._parse( value );
+ }
+ }
+ if ( key === "icons" ) {
+ this.buttons.first().find( ".ui-icon" )
+ .removeClass( this.options.icons.up )
+ .addClass( value.up );
+ this.buttons.last().find( ".ui-icon" )
+ .removeClass( this.options.icons.down )
+ .addClass( value.down );
+ }
+
+ this._super( key, value );
+
+ if ( key === "disabled" ) {
+ if ( value ) {
+ this.element.prop( "disabled", true );
+ this.buttons.button( "disable" );
+ } else {
+ this.element.prop( "disabled", false );
+ this.buttons.button( "enable" );
+ }
+ }
+ },
+
+ _setOptions: modifier(function( options ) {
+ this._super( options );
+ this._value( this.element.val() );
+ }),
+
+ _parse: function( val ) {
+ if ( typeof val === "string" && val !== "" ) {
+ val = window.Globalize && this.options.numberFormat ?
+ Globalize.parseFloat( val, 10, this.options.culture ) : +val;
+ }
+ return val === "" || isNaN( val ) ? null : val;
+ },
+
+ _format: function( value ) {
+ if ( value === "" ) {
+ return "";
+ }
+ return window.Globalize && this.options.numberFormat ?
+ Globalize.format( value, this.options.numberFormat, this.options.culture ) :
+ value;
+ },
+
+ _refresh: function() {
+ this.element.attr({
+ "aria-valuemin": this.options.min,
+ "aria-valuemax": this.options.max,
+ // TODO: what should we do with values that can't be parsed?
+ "aria-valuenow": this._parse( this.element.val() )
+ });
+ },
+
+ // update the value without triggering change
+ _value: function( value, allowAny ) {
+ var parsed;
+ if ( value !== "" ) {
+ parsed = this._parse( value );
+ if ( parsed !== null ) {
+ if ( !allowAny ) {
+ parsed = this._adjustValue( parsed );
+ }
+ value = this._format( parsed );
+ }
+ }
+ this.element.val( value );
+ this._refresh();
+ },
+
+ _destroy: function() {
+ this.element
+ .removeClass( "ui-spinner-input" )
+ .prop( "disabled", false )
+ .removeAttr( "autocomplete" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-valuemin" )
+ .removeAttr( "aria-valuemax" )
+ .removeAttr( "aria-valuenow" );
+ this.uiSpinner.replaceWith( this.element );
+ },
+
+ stepUp: modifier(function( steps ) {
+ this._stepUp( steps );
+ }),
+ _stepUp: function( steps ) {
+ if ( this._start() ) {
+ this._spin( (steps || 1) * this.options.step );
+ this._stop();
+ }
+ },
+
+ stepDown: modifier(function( steps ) {
+ this._stepDown( steps );
+ }),
+ _stepDown: function( steps ) {
+ if ( this._start() ) {
+ this._spin( (steps || 1) * -this.options.step );
+ this._stop();
+ }
+ },
+
+ pageUp: modifier(function( pages ) {
+ this._stepUp( (pages || 1) * this.options.page );
+ }),
+
+ pageDown: modifier(function( pages ) {
+ this._stepDown( (pages || 1) * this.options.page );
+ }),
+
+ value: function( newVal ) {
+ if ( !arguments.length ) {
+ return this._parse( this.element.val() );
+ }
+ modifier( this._value ).call( this, newVal );
+ },
+
+ widget: function() {
+ return this.uiSpinner;
+ }
+});
+
+}( jQuery ) );
+(function( $, undefined ) {
+
+var tabId = 0,
+ rhash = /#.*$/;
+
+function getNextTabId() {
+ return ++tabId;
+}
+
+function isLocal( anchor ) {
+ return anchor.hash.length > 1 &&
+ decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
+ decodeURIComponent( location.href.replace( rhash, "" ) );
+}
+
+$.widget( "ui.tabs", {
+ version: "1.10.3",
+ delay: 300,
+ options: {
+ active: null,
+ collapsible: false,
+ event: "click",
+ heightStyle: "content",
+ hide: null,
+ show: null,
+
+ // callbacks
+ activate: null,
+ beforeActivate: null,
+ beforeLoad: null,
+ load: null
+ },
+
+ _create: function() {
+ var that = this,
+ options = this.options;
+
+ this.running = false;
+
+ this.element
+ .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
+ .toggleClass( "ui-tabs-collapsible", options.collapsible )
+ // Prevent users from focusing disabled tabs via click
+ .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
+ if ( $( this ).is( ".ui-state-disabled" ) ) {
+ event.preventDefault();
+ }
+ })
+ // support: IE <9
+ // Preventing the default action in mousedown doesn't prevent IE
+ // from focusing the element, so if the anchor gets focused, blur.
+ // We don't have to worry about focusing the previously focused
+ // element since clicking on a non-focusable element should focus
+ // the body anyway.
+ .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
+ if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
+ this.blur();
+ }
+ });
+
+ this._processTabs();
+ options.active = this._initialActive();
+
+ // Take disabling tabs via class attribute from HTML
+ // into account and update option properly.
+ if ( $.isArray( options.disabled ) ) {
+ options.disabled = $.unique( options.disabled.concat(
+ $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
+ return that.tabs.index( li );
+ })
+ ) ).sort();
+ }
+
+ // check for length avoids error when initializing empty list
+ if ( this.options.active !== false && this.anchors.length ) {
+ this.active = this._findActive( options.active );
+ } else {
+ this.active = $();
+ }
+
+ this._refresh();
+
+ if ( this.active.length ) {
+ this.load( options.active );
+ }
+ },
+
+ _initialActive: function() {
+ var active = this.options.active,
+ collapsible = this.options.collapsible,
+ locationHash = location.hash.substring( 1 );
+
+ if ( active === null ) {
+ // check the fragment identifier in the URL
+ if ( locationHash ) {
+ this.tabs.each(function( i, tab ) {
+ if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
+ active = i;
+ return false;
+ }
+ });
+ }
+
+ // check for a tab marked active via a class
+ if ( active === null ) {
+ active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
+ }
+
+ // no active tab, set to false
+ if ( active === null || active === -1 ) {
+ active = this.tabs.length ? 0 : false;
+ }
+ }
+
+ // handle numbers: negative, out of range
+ if ( active !== false ) {
+ active = this.tabs.index( this.tabs.eq( active ) );
+ if ( active === -1 ) {
+ active = collapsible ? false : 0;
+ }
+ }
+
+ // don't allow collapsible: false and active: false
+ if ( !collapsible && active === false && this.anchors.length ) {
+ active = 0;
+ }
+
+ return active;
+ },
+
+ _getCreateEventData: function() {
+ return {
+ tab: this.active,
+ panel: !this.active.length ? $() : this._getPanelForTab( this.active )
+ };
+ },
+
+ _tabKeydown: function( event ) {
+ /*jshint maxcomplexity:15*/
+ var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
+ selectedIndex = this.tabs.index( focusedTab ),
+ goingForward = true;
+
+ if ( this._handlePageNav( event ) ) {
+ return;
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.RIGHT:
+ case $.ui.keyCode.DOWN:
+ selectedIndex++;
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.LEFT:
+ goingForward = false;
+ selectedIndex--;
+ break;
+ case $.ui.keyCode.END:
+ selectedIndex = this.anchors.length - 1;
+ break;
+ case $.ui.keyCode.HOME:
+ selectedIndex = 0;
+ break;
+ case $.ui.keyCode.SPACE:
+ // Activate only, no collapsing
+ event.preventDefault();
+ clearTimeout( this.activating );
+ this._activate( selectedIndex );
+ return;
+ case $.ui.keyCode.ENTER:
+ // Toggle (cancel delayed activation, allow collapsing)
+ event.preventDefault();
+ clearTimeout( this.activating );
+ // Determine if we should collapse or activate
+ this._activate( selectedIndex === this.options.active ? false : selectedIndex );
+ return;
+ default:
+ return;
+ }
+
+ // Focus the appropriate tab, based on which key was pressed
+ event.preventDefault();
+ clearTimeout( this.activating );
+ selectedIndex = this._focusNextTab( selectedIndex, goingForward );
+
+ // Navigating with control key will prevent automatic activation
+ if ( !event.ctrlKey ) {
+ // Update aria-selected immediately so that AT think the tab is already selected.
+ // Otherwise AT may confuse the user by stating that they need to activate the tab,
+ // but the tab will already be activated by the time the announcement finishes.
+ focusedTab.attr( "aria-selected", "false" );
+ this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
+
+ this.activating = this._delay(function() {
+ this.option( "active", selectedIndex );
+ }, this.delay );
+ }
+ },
+
+ _panelKeydown: function( event ) {
+ if ( this._handlePageNav( event ) ) {
+ return;
+ }
+
+ // Ctrl+up moves focus to the current tab
+ if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
+ event.preventDefault();
+ this.active.focus();
+ }
+ },
+
+ // Alt+page up/down moves focus to the previous/next tab (and activates)
+ _handlePageNav: function( event ) {
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
+ this._activate( this._focusNextTab( this.options.active - 1, false ) );
+ return true;
+ }
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
+ this._activate( this._focusNextTab( this.options.active + 1, true ) );
+ return true;
+ }
+ },
+
+ _findNextTab: function( index, goingForward ) {
+ var lastTabIndex = this.tabs.length - 1;
+
+ function constrain() {
+ if ( index > lastTabIndex ) {
+ index = 0;
+ }
+ if ( index < 0 ) {
+ index = lastTabIndex;
+ }
+ return index;
+ }
+
+ while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
+ index = goingForward ? index + 1 : index - 1;
+ }
+
+ return index;
+ },
+
+ _focusNextTab: function( index, goingForward ) {
+ index = this._findNextTab( index, goingForward );
+ this.tabs.eq( index ).focus();
+ return index;
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "active" ) {
+ // _activate() will handle invalid values and update this.options
+ this._activate( value );
+ return;
+ }
+
+ if ( key === "disabled" ) {
+ // don't use the widget factory's disabled handling
+ this._setupDisabled( value );
+ return;
+ }
+
+ this._super( key, value);
+
+ if ( key === "collapsible" ) {
+ this.element.toggleClass( "ui-tabs-collapsible", value );
+ // Setting collapsible: false while collapsed; open first panel
+ if ( !value && this.options.active === false ) {
+ this._activate( 0 );
+ }
+ }
+
+ if ( key === "event" ) {
+ this._setupEvents( value );
+ }
+
+ if ( key === "heightStyle" ) {
+ this._setupHeightStyle( value );
+ }
+ },
+
+ _tabId: function( tab ) {
+ return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
+ },
+
+ _sanitizeSelector: function( hash ) {
+ return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
+ },
+
+ refresh: function() {
+ var options = this.options,
+ lis = this.tablist.children( ":has(a[href])" );
+
+ // get disabled tabs from class attribute from HTML
+ // this will get converted to a boolean if needed in _refresh()
+ options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
+ return lis.index( tab );
+ });
+
+ this._processTabs();
+
+ // was collapsed or no tabs
+ if ( options.active === false || !this.anchors.length ) {
+ options.active = false;
+ this.active = $();
+ // was active, but active tab is gone
+ } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
+ // all remaining tabs are disabled
+ if ( this.tabs.length === options.disabled.length ) {
+ options.active = false;
+ this.active = $();
+ // activate previous tab
+ } else {
+ this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
+ }
+ // was active, active tab still exists
+ } else {
+ // make sure active index is correct
+ options.active = this.tabs.index( this.active );
+ }
+
+ this._refresh();
+ },
+
+ _refresh: function() {
+ this._setupDisabled( this.options.disabled );
+ this._setupEvents( this.options.event );
+ this._setupHeightStyle( this.options.heightStyle );
+
+ this.tabs.not( this.active ).attr({
+ "aria-selected": "false",
+ tabIndex: -1
+ });
+ this.panels.not( this._getPanelForTab( this.active ) )
+ .hide()
+ .attr({
+ "aria-expanded": "false",
+ "aria-hidden": "true"
+ });
+
+ // Make sure one tab is in the tab order
+ if ( !this.active.length ) {
+ this.tabs.eq( 0 ).attr( "tabIndex", 0 );
+ } else {
+ this.active
+ .addClass( "ui-tabs-active ui-state-active" )
+ .attr({
+ "aria-selected": "true",
+ tabIndex: 0
+ });
+ this._getPanelForTab( this.active )
+ .show()
+ .attr({
+ "aria-expanded": "true",
+ "aria-hidden": "false"
+ });
+ }
+ },
+
+ _processTabs: function() {
+ var that = this;
+
+ this.tablist = this._getList()
+ .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
+ .attr( "role", "tablist" );
+
+ this.tabs = this.tablist.find( "> li:has(a[href])" )
+ .addClass( "ui-state-default ui-corner-top" )
+ .attr({
+ role: "tab",
+ tabIndex: -1
+ });
+
+ this.anchors = this.tabs.map(function() {
+ return $( "a", this )[ 0 ];
+ })
+ .addClass( "ui-tabs-anchor" )
+ .attr({
+ role: "presentation",
+ tabIndex: -1
+ });
+
+ this.panels = $();
+
+ this.anchors.each(function( i, anchor ) {
+ var selector, panel, panelId,
+ anchorId = $( anchor ).uniqueId().attr( "id" ),
+ tab = $( anchor ).closest( "li" ),
+ originalAriaControls = tab.attr( "aria-controls" );
+
+ // inline tab
+ if ( isLocal( anchor ) ) {
+ selector = anchor.hash;
+ panel = that.element.find( that._sanitizeSelector( selector ) );
+ // remote tab
+ } else {
+ panelId = that._tabId( tab );
+ selector = "#" + panelId;
+ panel = that.element.find( selector );
+ if ( !panel.length ) {
+ panel = that._createPanel( panelId );
+ panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
+ }
+ panel.attr( "aria-live", "polite" );
+ }
+
+ if ( panel.length) {
+ that.panels = that.panels.add( panel );
+ }
+ if ( originalAriaControls ) {
+ tab.data( "ui-tabs-aria-controls", originalAriaControls );
+ }
+ tab.attr({
+ "aria-controls": selector.substring( 1 ),
+ "aria-labelledby": anchorId
+ });
+ panel.attr( "aria-labelledby", anchorId );
+ });
+
+ this.panels
+ .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+ .attr( "role", "tabpanel" );
+ },
+
+ // allow overriding how to find the list for rare usage scenarios (#7715)
+ _getList: function() {
+ return this.element.find( "ol,ul" ).eq( 0 );
+ },
+
+ _createPanel: function( id ) {
+ return $( "<div>" )
+ .attr( "id", id )
+ .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+ .data( "ui-tabs-destroy", true );
+ },
+
+ _setupDisabled: function( disabled ) {
+ if ( $.isArray( disabled ) ) {
+ if ( !disabled.length ) {
+ disabled = false;
+ } else if ( disabled.length === this.anchors.length ) {
+ disabled = true;
+ }
+ }
+
+ // disable tabs
+ for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
+ if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
+ $( li )
+ .addClass( "ui-state-disabled" )
+ .attr( "aria-disabled", "true" );
+ } else {
+ $( li )
+ .removeClass( "ui-state-disabled" )
+ .removeAttr( "aria-disabled" );
+ }
+ }
+
+ this.options.disabled = disabled;
+ },
+
+ _setupEvents: function( event ) {
+ var events = {
+ click: function( event ) {
+ event.preventDefault();
+ }
+ };
+ if ( event ) {
+ $.each( event.split(" "), function( index, eventName ) {
+ events[ eventName ] = "_eventHandler";
+ });
+ }
+
+ this._off( this.anchors.add( this.tabs ).add( this.panels ) );
+ this._on( this.anchors, events );
+ this._on( this.tabs, { keydown: "_tabKeydown" } );
+ this._on( this.panels, { keydown: "_panelKeydown" } );
+
+ this._focusable( this.tabs );
+ this._hoverable( this.tabs );
+ },
+
+ _setupHeightStyle: function( heightStyle ) {
+ var maxHeight,
+ parent = this.element.parent();
+
+ if ( heightStyle === "fill" ) {
+ maxHeight = parent.height();
+ maxHeight -= this.element.outerHeight() - this.element.height();
+
+ this.element.siblings( ":visible" ).each(function() {
+ var elem = $( this ),
+ position = elem.css( "position" );
+
+ if ( position === "absolute" || position === "fixed" ) {
+ return;
+ }
+ maxHeight -= elem.outerHeight( true );
+ });
+
+ this.element.children().not( this.panels ).each(function() {
+ maxHeight -= $( this ).outerHeight( true );
+ });
+
+ this.panels.each(function() {
+ $( this ).height( Math.max( 0, maxHeight -
+ $( this ).innerHeight() + $( this ).height() ) );
+ })
+ .css( "overflow", "auto" );
+ } else if ( heightStyle === "auto" ) {
+ maxHeight = 0;
+ this.panels.each(function() {
+ maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
+ }).height( maxHeight );
+ }
+ },
+
+ _eventHandler: function( event ) {
+ var options = this.options,
+ active = this.active,
+ anchor = $( event.currentTarget ),
+ tab = anchor.closest( "li" ),
+ clickedIsActive = tab[ 0 ] === active[ 0 ],
+ collapsing = clickedIsActive && options.collapsible,
+ toShow = collapsing ? $() : this._getPanelForTab( tab ),
+ toHide = !active.length ? $() : this._getPanelForTab( active ),
+ eventData = {
+ oldTab: active,
+ oldPanel: toHide,
+ newTab: collapsing ? $() : tab,
+ newPanel: toShow
+ };
+
+ event.preventDefault();
+
+ if ( tab.hasClass( "ui-state-disabled" ) ||
+ // tab is already loading
+ tab.hasClass( "ui-tabs-loading" ) ||
+ // can't switch durning an animation
+ this.running ||
+ // click on active header, but not collapsible
+ ( clickedIsActive && !options.collapsible ) ||
+ // allow canceling activation
+ ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
+ return;
+ }
+
+ options.active = collapsing ? false : this.tabs.index( tab );
+
+ this.active = clickedIsActive ? $() : tab;
+ if ( this.xhr ) {
+ this.xhr.abort();
+ }
+
+ if ( !toHide.length && !toShow.length ) {
+ $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
+ }
+
+ if ( toShow.length ) {
+ this.load( this.tabs.index( tab ), event );
+ }
+ this._toggle( event, eventData );
+ },
+
+ // handles show/hide for selecting tabs
+ _toggle: function( event, eventData ) {
+ var that = this,
+ toShow = eventData.newPanel,
+ toHide = eventData.oldPanel;
+
+ this.running = true;
+
+ function complete() {
+ that.running = false;
+ that._trigger( "activate", event, eventData );
+ }
+
+ function show() {
+ eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
+
+ if ( toShow.length && that.options.show ) {
+ that._show( toShow, that.options.show, complete );
+ } else {
+ toShow.show();
+ complete();
+ }
+ }
+
+ // start out by hiding, then showing, then completing
+ if ( toHide.length && this.options.hide ) {
+ this._hide( toHide, this.options.hide, function() {
+ eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+ show();
+ });
+ } else {
+ eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+ toHide.hide();
+ show();
+ }
+
+ toHide.attr({
+ "aria-expanded": "false",
+ "aria-hidden": "true"
+ });
+ eventData.oldTab.attr( "aria-selected", "false" );
+ // If we're switching tabs, remove the old tab from the tab order.
+ // If we're opening from collapsed state, remove the previous tab from the tab order.
+ // If we're collapsing, then keep the collapsing tab in the tab order.
+ if ( toShow.length && toHide.length ) {
+ eventData.oldTab.attr( "tabIndex", -1 );
+ } else if ( toShow.length ) {
+ this.tabs.filter(function() {
+ return $( this ).attr( "tabIndex" ) === 0;
+ })
+ .attr( "tabIndex", -1 );
+ }
+
+ toShow.attr({
+ "aria-expanded": "true",
+ "aria-hidden": "false"
+ });
+ eventData.newTab.attr({
+ "aria-selected": "true",
+ tabIndex: 0
+ });
+ },
+
+ _activate: function( index ) {
+ var anchor,
+ active = this._findActive( index );
+
+ // trying to activate the already active panel
+ if ( active[ 0 ] === this.active[ 0 ] ) {
+ return;
+ }
+
+ // trying to collapse, simulate a click on the current active header
+ if ( !active.length ) {
+ active = this.active;
+ }
+
+ anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
+ this._eventHandler({
+ target: anchor,
+ currentTarget: anchor,
+ preventDefault: $.noop
+ });
+ },
+
+ _findActive: function( index ) {
+ return index === false ? $() : this.tabs.eq( index );
+ },
+
+ _getIndex: function( index ) {
+ // meta-function to give users option to provide a href string instead of a numerical index.
+ if ( typeof index === "string" ) {
+ index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
+ }
+
+ return index;
+ },
+
+ _destroy: function() {
+ if ( this.xhr ) {
+ this.xhr.abort();
+ }
+
+ this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
+
+ this.tablist
+ .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
+ .removeAttr( "role" );
+
+ this.anchors
+ .removeClass( "ui-tabs-anchor" )
+ .removeAttr( "role" )
+ .removeAttr( "tabIndex" )
+ .removeUniqueId();
+
+ this.tabs.add( this.panels ).each(function() {
+ if ( $.data( this, "ui-tabs-destroy" ) ) {
+ $( this ).remove();
+ } else {
+ $( this )
+ .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
+ "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
+ .removeAttr( "tabIndex" )
+ .removeAttr( "aria-live" )
+ .removeAttr( "aria-busy" )
+ .removeAttr( "aria-selected" )
+ .removeAttr( "aria-labelledby" )
+ .removeAttr( "aria-hidden" )
+ .removeAttr( "aria-expanded" )
+ .removeAttr( "role" );
+ }
+ });
+
+ this.tabs.each(function() {
+ var li = $( this ),
+ prev = li.data( "ui-tabs-aria-controls" );
+ if ( prev ) {
+ li
+ .attr( "aria-controls", prev )
+ .removeData( "ui-tabs-aria-controls" );
+ } else {
+ li.removeAttr( "aria-controls" );
+ }
+ });
+
+ this.panels.show();
+
+ if ( this.options.heightStyle !== "content" ) {
+ this.panels.css( "height", "" );
+ }
+ },
+
+ enable: function( index ) {
+ var disabled = this.options.disabled;
+ if ( disabled === false ) {
+ return;
+ }
+
+ if ( index === undefined ) {
+ disabled = false;
+ } else {
+ index = this._getIndex( index );
+ if ( $.isArray( disabled ) ) {
+ disabled = $.map( disabled, function( num ) {
+ return num !== index ? num : null;
+ });
+ } else {
+ disabled = $.map( this.tabs, function( li, num ) {
+ return num !== index ? num : null;
+ });
+ }
+ }
+ this._setupDisabled( disabled );
+ },
+
+ disable: function( index ) {
+ var disabled = this.options.disabled;
+ if ( disabled === true ) {
+ return;
+ }
+
+ if ( index === undefined ) {
+ disabled = true;
+ } else {
+ index = this._getIndex( index );
+ if ( $.inArray( index, disabled ) !== -1 ) {
+ return;
+ }
+ if ( $.isArray( disabled ) ) {
+ disabled = $.merge( [ index ], disabled ).sort();
+ } else {
+ disabled = [ index ];
+ }
+ }
+ this._setupDisabled( disabled );
+ },
+
+ load: function( index, event ) {
+ index = this._getIndex( index );
+ var that = this,
+ tab = this.tabs.eq( index ),
+ anchor = tab.find( ".ui-tabs-anchor" ),
+ panel = this._getPanelForTab( tab ),
+ eventData = {
+ tab: tab,
+ panel: panel
+ };
+
+ // not remote
+ if ( isLocal( anchor[ 0 ] ) ) {
+ return;
+ }
+
+ this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
+
+ // support: jQuery <1.8
+ // jQuery <1.8 returns false if the request is canceled in beforeSend,
+ // but as of 1.8, $.ajax() always returns a jqXHR object.
+ if ( this.xhr && this.xhr.statusText !== "canceled" ) {
+ tab.addClass( "ui-tabs-loading" );
+ panel.attr( "aria-busy", "true" );
+
+ this.xhr
+ .success(function( response ) {
+ // support: jQuery <1.8
+ // http://bugs.jquery.com/ticket/11778
+ setTimeout(function() {
+ panel.html( response );
+ that._trigger( "load", event, eventData );
+ }, 1 );
+ })
+ .complete(function( jqXHR, status ) {
+ // support: jQuery <1.8
+ // http://bugs.jquery.com/ticket/11778
+ setTimeout(function() {
+ if ( status === "abort" ) {
+ that.panels.stop( false, true );
+ }
+
+ tab.removeClass( "ui-tabs-loading" );
+ panel.removeAttr( "aria-busy" );
+
+ if ( jqXHR === that.xhr ) {
+ delete that.xhr;
+ }
+ }, 1 );
+ });
+ }
+ },
+
+ _ajaxSettings: function( anchor, event, eventData ) {
+ var that = this;
+ return {
+ url: anchor.attr( "href" ),
+ beforeSend: function( jqXHR, settings ) {
+ return that._trigger( "beforeLoad", event,
+ $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
+ }
+ };
+ },
+
+ _getPanelForTab: function( tab ) {
+ var id = $( tab ).attr( "aria-controls" );
+ return this.element.find( this._sanitizeSelector( "#" + id ) );
+ }
+});
+
+})( jQuery );
+(function( $ ) {
+
+var increments = 0;
+
+function addDescribedBy( elem, id ) {
+ var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
+ describedby.push( id );
+ elem
+ .data( "ui-tooltip-id", id )
+ .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
+}
+
+function removeDescribedBy( elem ) {
+ var id = elem.data( "ui-tooltip-id" ),
+ describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
+ index = $.inArray( id, describedby );
+ if ( index !== -1 ) {
+ describedby.splice( index, 1 );
+ }
+
+ elem.removeData( "ui-tooltip-id" );
+ describedby = $.trim( describedby.join( " " ) );
+ if ( describedby ) {
+ elem.attr( "aria-describedby", describedby );
+ } else {
+ elem.removeAttr( "aria-describedby" );
+ }
+}
+
+$.widget( "ui.tooltip", {
+ version: "1.10.3",
+ options: {
+ content: function() {
+ // support: IE<9, Opera in jQuery <1.7
+ // .text() can't accept undefined, so coerce to a string
+ var title = $( this ).attr( "title" ) || "";
+ // Escape title, since we're going from an attribute to raw HTML
+ return $( "<a>" ).text( title ).html();
+ },
+ hide: true,
+ // Disabled elements have inconsistent behavior across browsers (#8661)
+ items: "[title]:not([disabled])",
+ position: {
+ my: "left top+15",
+ at: "left bottom",
+ collision: "flipfit flip"
+ },
+ show: true,
+ tooltipClass: null,
+ track: false,
+
+ // callbacks
+ close: null,
+ open: null
+ },
+
+ _create: function() {
+ this._on({
+ mouseover: "open",
+ focusin: "open"
+ });
+
+ // IDs of generated tooltips, needed for destroy
+ this.tooltips = {};
+ // IDs of parent tooltips where we removed the title attribute
+ this.parents = {};
+
+ if ( this.options.disabled ) {
+ this._disable();
+ }
+ },
+
+ _setOption: function( key, value ) {
+ var that = this;
+
+ if ( key === "disabled" ) {
+ this[ value ? "_disable" : "_enable" ]();
+ this.options[ key ] = value;
+ // disable element style changes
+ return;
+ }
+
+ this._super( key, value );
+
+ if ( key === "content" ) {
+ $.each( this.tooltips, function( id, element ) {
+ that._updateContent( element );
+ });
+ }
+ },
+
+ _disable: function() {
+ var that = this;
+
+ // close open tooltips
+ $.each( this.tooltips, function( id, element ) {
+ var event = $.Event( "blur" );
+ event.target = event.currentTarget = element[0];
+ that.close( event, true );
+ });
+
+ // remove title attributes to prevent native tooltips
+ this.element.find( this.options.items ).addBack().each(function() {
+ var element = $( this );
+ if ( element.is( "[title]" ) ) {
+ element
+ .data( "ui-tooltip-title", element.attr( "title" ) )
+ .attr( "title", "" );
+ }
+ });
+ },
+
+ _enable: function() {
+ // restore title attributes
+ this.element.find( this.options.items ).addBack().each(function() {
+ var element = $( this );
+ if ( element.data( "ui-tooltip-title" ) ) {
+ element.attr( "title", element.data( "ui-tooltip-title" ) );
+ }
+ });
+ },
+
+ open: function( event ) {
+ var that = this,
+ target = $( event ? event.target : this.element )
+ // we need closest here due to mouseover bubbling,
+ // but always pointing at the same event target
+ .closest( this.options.items );
+
+ // No element to show a tooltip for or the tooltip is already open
+ if ( !target.length || target.data( "ui-tooltip-id" ) ) {
+ return;
+ }
+
+ if ( target.attr( "title" ) ) {
+ target.data( "ui-tooltip-title", target.attr( "title" ) );
+ }
+
+ target.data( "ui-tooltip-open", true );
+
+ // kill parent tooltips, custom or native, for hover
+ if ( event && event.type === "mouseover" ) {
+ target.parents().each(function() {
+ var parent = $( this ),
+ blurEvent;
+ if ( parent.data( "ui-tooltip-open" ) ) {
+ blurEvent = $.Event( "blur" );
+ blurEvent.target = blurEvent.currentTarget = this;
+ that.close( blurEvent, true );
+ }
+ if ( parent.attr( "title" ) ) {
+ parent.uniqueId();
+ that.parents[ this.id ] = {
+ element: this,
+ title: parent.attr( "title" )
+ };
+ parent.attr( "title", "" );
+ }
+ });
+ }
+
+ this._updateContent( target, event );
+ },
+
+ _updateContent: function( target, event ) {
+ var content,
+ contentOption = this.options.content,
+ that = this,
+ eventType = event ? event.type : null;
+
+ if ( typeof contentOption === "string" ) {
+ return this._open( event, target, contentOption );
+ }
+
+ content = contentOption.call( target[0], function( response ) {
+ // ignore async response if tooltip was closed already
+ if ( !target.data( "ui-tooltip-open" ) ) {
+ return;
+ }
+ // IE may instantly serve a cached response for ajax requests
+ // delay this call to _open so the other call to _open runs first
+ that._delay(function() {
+ // jQuery creates a special event for focusin when it doesn't
+ // exist natively. To improve performance, the native event
+ // object is reused and the type is changed. Therefore, we can't
+ // rely on the type being correct after the event finished
+ // bubbling, so we set it back to the previous value. (#8740)
+ if ( event ) {
+ event.type = eventType;
+ }
+ this._open( event, target, response );
+ });
+ });
+ if ( content ) {
+ this._open( event, target, content );
+ }
+ },
+
+ _open: function( event, target, content ) {
+ var tooltip, events, delayedShow,
+ positionOption = $.extend( {}, this.options.position );
+
+ if ( !content ) {
+ return;
+ }
+
+ // Content can be updated multiple times. If the tooltip already
+ // exists, then just update the content and bail.
+ tooltip = this._find( target );
+ if ( tooltip.length ) {
+ tooltip.find( ".ui-tooltip-content" ).html( content );
+ return;
+ }
+
+ // if we have a title, clear it to prevent the native tooltip
+ // we have to check first to avoid defining a title if none exists
+ // (we don't want to cause an element to start matching [title])
+ //
+ // We use removeAttr only for key events, to allow IE to export the correct
+ // accessible attributes. For mouse events, set to empty string to avoid
+ // native tooltip showing up (happens only when removing inside mouseover).
+ if ( target.is( "[title]" ) ) {
+ if ( event && event.type === "mouseover" ) {
+ target.attr( "title", "" );
+ } else {
+ target.removeAttr( "title" );
+ }
+ }
+
+ tooltip = this._tooltip( target );
+ addDescribedBy( target, tooltip.attr( "id" ) );
+ tooltip.find( ".ui-tooltip-content" ).html( content );
+
+ function position( event ) {
+ positionOption.of = event;
+ if ( tooltip.is( ":hidden" ) ) {
+ return;
+ }
+ tooltip.position( positionOption );
+ }
+ if ( this.options.track && event && /^mouse/.test( event.type ) ) {
+ this._on( this.document, {
+ mousemove: position
+ });
+ // trigger once to override element-relative positioning
+ position( event );
+ } else {
+ tooltip.position( $.extend({
+ of: target
+ }, this.options.position ) );
+ }
+
+ tooltip.hide();
+
+ this._show( tooltip, this.options.show );
+ // Handle tracking tooltips that are shown with a delay (#8644). As soon
+ // as the tooltip is visible, position the tooltip using the most recent
+ // event.
+ if ( this.options.show && this.options.show.delay ) {
+ delayedShow = this.delayedShow = setInterval(function() {
+ if ( tooltip.is( ":visible" ) ) {
+ position( positionOption.of );
+ clearInterval( delayedShow );
+ }
+ }, $.fx.interval );
+ }
+
+ this._trigger( "open", event, { tooltip: tooltip } );
+
+ events = {
+ keyup: function( event ) {
+ if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
+ var fakeEvent = $.Event(event);
+ fakeEvent.currentTarget = target[0];
+ this.close( fakeEvent, true );
+ }
+ },
+ remove: function() {
+ this._removeTooltip( tooltip );
+ }
+ };
+ if ( !event || event.type === "mouseover" ) {
+ events.mouseleave = "close";
+ }
+ if ( !event || event.type === "focusin" ) {
+ events.focusout = "close";
+ }
+ this._on( true, target, events );
+ },
+
+ close: function( event ) {
+ var that = this,
+ target = $( event ? event.currentTarget : this.element ),
+ tooltip = this._find( target );
+
+ // disabling closes the tooltip, so we need to track when we're closing
+ // to avoid an infinite loop in case the tooltip becomes disabled on close
+ if ( this.closing ) {
+ return;
+ }
+
+ // Clear the interval for delayed tracking tooltips
+ clearInterval( this.delayedShow );
+
+ // only set title if we had one before (see comment in _open())
+ if ( target.data( "ui-tooltip-title" ) ) {
+ target.attr( "title", target.data( "ui-tooltip-title" ) );
+ }
+
+ removeDescribedBy( target );
+
+ tooltip.stop( true );
+ this._hide( tooltip, this.options.hide, function() {
+ that._removeTooltip( $( this ) );
+ });
+
+ target.removeData( "ui-tooltip-open" );
+ this._off( target, "mouseleave focusout keyup" );
+ // Remove 'remove' binding only on delegated targets
+ if ( target[0] !== this.element[0] ) {
+ this._off( target, "remove" );
+ }
+ this._off( this.document, "mousemove" );
+
+ if ( event && event.type === "mouseleave" ) {
+ $.each( this.parents, function( id, parent ) {
+ $( parent.element ).attr( "title", parent.title );
+ delete that.parents[ id ];
+ });
+ }
+
+ this.closing = true;
+ this._trigger( "close", event, { tooltip: tooltip } );
+ this.closing = false;
+ },
+
+ _tooltip: function( element ) {
+ var id = "ui-tooltip-" + increments++,
+ tooltip = $( "<div>" )
+ .attr({
+ id: id,
+ role: "tooltip"
+ })
+ .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
+ ( this.options.tooltipClass || "" ) );
+ $( "<div>" )
+ .addClass( "ui-tooltip-content" )
+ .appendTo( tooltip );
+ tooltip.appendTo( this.document[0].body );
+ this.tooltips[ id ] = element;
+ return tooltip;
+ },
+
+ _find: function( target ) {
+ var id = target.data( "ui-tooltip-id" );
+ return id ? $( "#" + id ) : $();
+ },
+
+ _removeTooltip: function( tooltip ) {
+ tooltip.remove();
+ delete this.tooltips[ tooltip.attr( "id" ) ];
+ },
+
+ _destroy: function() {
+ var that = this;
+
+ // close open tooltips
+ $.each( this.tooltips, function( id, element ) {
+ // Delegate to close method to handle common cleanup
+ var event = $.Event( "blur" );
+ event.target = event.currentTarget = element[0];
+ that.close( event, true );
+
+ // Remove immediately; destroying an open tooltip doesn't use the
+ // hide animation
+ $( "#" + id ).remove();
+
+ // Restore the title
+ if ( element.data( "ui-tooltip-title" ) ) {
+ element.attr( "title", element.data( "ui-tooltip-title" ) );
+ element.removeData( "ui-tooltip-title" );
+ }
+ });
+ }
+});
+
+}( jQuery ) );
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.min.js
new file mode 100755
index 0000000..8ececa0
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-ui-1.10.3.custom.min.js
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.10.3 - 2013-05-11
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
+* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
+
+(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(
){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.ex
pr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(thi
s,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][
1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){
var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a
);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.o
wnerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=
0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=t
ypeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.el
ement[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName
+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.t
arget,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0)
,this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?
/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow?"":e.element.css("overflow-x"),s=e.isWindow?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]);return{element:i,isWindow:s,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)r
eturn f.apply(this,arguments);e=t.extend({},e);var a,p,m,g,v,b,_=t(e.of),y=t.position.getWithinInfo(e.within),w=t.position.getScrollInfo(y),x=(e.collision||"flip").split(" "),k={};return b=n(_),_[0].preventDefault&&(e.at="left top"),p=b.width,m=b.height,g=b.offset,v=t.extend({},g),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=l.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=l.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),k[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===x.length&&(x[1]=x[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=m:"center"===e.at[1]&&(v.top+=m/2),a=i(k.at,p,m),v.left+=a[0],v.top+=a[1],this.each(function(){var n,l,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),b=s(this,"marginTop"),D=u+f+s(this,"marginRight")+w.width,T=d+b+s(this,"marginBottom"
)+w.height,C=t.extend({},v),M=i(k.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?C.left-=u:"center"===e.my[0]&&(C.left-=u/2),"bottom"===e.my[1]?C.top-=d:"center"===e.my[1]&&(C.top-=d/2),C.left+=M[0],C.top+=M[1],t.support.offsetFractions||(C.left=h(C.left),C.top=h(C.top)),n={marginLeft:f,marginTop:b},t.each(["left","top"],function(i,s){t.ui.position[x[i]]&&t.ui.position[x[i]][s](C,{targetWidth:p,targetHeight:m,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:D,collisionHeight:T,offset:[a[0]+M[0],a[1]+M[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(l=function(t){var i=g.left-C.left,s=i+p-u,n=g.top-C.top,a=n+m-d,h={target:{element:_,left:g.left,top:g.top,width:p,height:m},element:{element:c,left:C.left,top:C.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(h.horizontal="center"),d>m&&m>r(n+a)&&(h.vertical="middle"),h.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.
call(this,t,h)}),c.offset(t.extend(C,{using:l}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-o-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemW
idth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-o-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-o-a,t.top+p+f+m>c&&(0>s||r(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,t.top+p+f+m>u&&(i>0||u>r(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,
arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(t){var e,i,s,n,a="ui-button ui-widget ui-state-default ui-corner-all",o="ui-state-hover ui-state-active ",r="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",h=function(){var e=t(this);setTimeout(function(){e.find(":ui-button").button("refresh")},1)},l=function(e){var i=e.name,s=e.form,n=t([]);return i&&(i=i.replace(/'/g,
"\\'"),n=s?t(s).find("[name='"+i+"']"):t("[name='"+i+"']",e.ownerDocument).filter(function(){return!this.form})),n};t.widget("ui.button",{version:"1.10.3",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,h),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var o=this,r=this.options,c="checkbox"===this.type||"radio"===this.type,u=c?"":"ui-state-active",d="ui-state-focus";null===r.label&&(r.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(a).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){r.disabled||this===e&&t(this).addCl
ass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){r.disabled||t(this).removeClass(u)}).bind("click"+this.eventNamespace,function(t){r.disabled&&(t.preventDefault(),t.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){o.buttonElement.addClass(d)}).bind("blur"+this.eventNamespace,function(){o.buttonElement.removeClass(d)}),c&&(this.element.bind("change"+this.eventNamespace,function(){n||o.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(t){r.disabled||(n=!1,i=t.pageX,s=t.pageY)}).bind("mouseup"+this.eventNamespace,function(t){r.disabled||(i!==t.pageX||s!==t.pageY)&&(n=!0)})),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return r.disabled||n?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(r.disabled||n)return!1;t(this).addClass("ui-state-active"),o.buttonElement.attr("aria-pressed","true");var e=o.el
ement[0];l(e).not(e).map(function(){return t(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return r.disabled?!1:(t(this).addClass("ui-state-active"),e=this,o.document.one("mouseup",function(){e=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return r.disabled?!1:(t(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(e){return r.disabled?!1:((e.keyCode===t.ui.keyCode.SPACE||e.keyCode===t.ui.keyCode.ENTER)&&t(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){t(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(e){e.keyCode===t.ui.keyCode.SPACE&&t(this).click()})),this._setOption("disabled",r.disabled),this._resetButton()},_determineButtonType:function(){var t,e,i;this.type=this.element.is("[
type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(t=this.element.parents().last(),e="label[for='"+this.element.attr("id")+"']",this.buttonElement=t.find(e),this.buttonElement.length||(t=t.length?t.siblings():this.element.siblings(),this.buttonElement=t.filter(e),this.buttonElement.length||(this.buttonElement=t.find(e))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(a+" "+o+" "+r).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(t,e){retu
rn this._super(t,e),"disabled"===t?(e?this.element.prop("disabled",!0):this.element.prop("disabled",!1),undefined):(this._resetButton(),undefined)},refresh:function(){var e=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");e!==this.options.disabled&&this._setOption("disabled",e),"radio"===this.type?l(this.element[0]).each(function(){t(this).is(":checked")?t(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):t(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var e=this.buttonElement.removeClass(r),i=t("<span></span>",this.document[0])
.addClass("ui-button-text").html(this.options.label).appendTo(e.empty()).text(),s=this.options.icons,n=s.primary&&s.secondary,a=[];s.primary||s.secondary?(this.options.text&&a.push("ui-button-text-icon"+(n?"s":s.primary?"-primary":"-secondary")),s.primary&&e.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&e.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(a.push(n?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||e.attr("title",t.trim(i)))):a.push("ui-button-text-only"),e.addClass(a.join(" "))}}),t.widget("ui.buttonset",{version:"1.10.3",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(t,e){"disabled"===t&&this.buttons.button("option",t,e),this._super(t,e)},refresh:f
unction(){var e="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(e?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(e?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(t,e){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",thi
s._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,goto
Current:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.dpDiv=s(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function s(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(i,"mouseout",function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datep
icker-next-hover")}).delegate(i,"mouseover",function(){t.datepicker._isDisabledDatepicker(a.inline?e.parent()[0]:a.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))})}function n(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}t.extend(t.ui,{datepicker:{version:"1.10.3"}});var a,r="datepicker";t.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return n(this._defaults,t||{}),this},_attachDatepicker:function(e,i){var s,n,a;s=e.nodeName.toLowerCase(),n="div"===s||"span"===s,e.id||(this.uuid+=1,e.id="dp"+this.uuid),a=this._newInst(t(e),n),a.settings=t.extend({},i||{}),"input"===s?this._connectDatepicker(e,a):n
&&this._inlineDatepicker(e,a)},_newInst:function(e,i){var n=e[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?s(t("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(e,i){var s=t(e);i.append=t([]),i.trigger=t([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),t.data(e,r,i),i.settings.disabled&&this._disableDatepicker(e))},_attachments:function(e,i){var s,n,a,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=t("<span class='"+this._appendClass+"'>"+r+"</span>"),e[o?"before":"after"](i.append)),e.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"=
==s||"both"===s)&&e.focus(this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),a=this._get(i,"buttonImage"),i.trigger=t(this._get(i,"buttonImageOnly")?t("<img/>").addClass(this._triggerClass).attr({src:a,alt:n,title:n}):t("<button type='button'></button>").addClass(this._triggerClass).html(a?t("<img/>").attr({src:a,alt:n,title:n}):n)),e[o?"before":"after"](i.trigger),i.trigger.click(function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,a=new Date(2009,11,20),r=this._get(t,"dateFormat");r.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},a.setMonth(e(this._get(t,r.match(/MM/)?"monthNames":"month
NamesShort"))),a.setDate(e(this._get(t,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),t.input.attr("size",this._formatDate(t,a).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,a,o){var h,l,c,u,d,p=this._dialogInst;return p||(this.uuid+=1,h="dp"+this.uuid,this._dialogInput=t("<input type='text' id='"+h+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),t("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},t.data(this._dialogInput[0],r,p)),n(p.settings,a||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o
.pageX,o.pageY]:null,this._pos||(l=document.documentElement.clientWidth,c=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[l/2-100+u,c/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,r);s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,r),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty())},_enableDate
picker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),t
his._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,s,a){var r,o,h,l,c=this._getInst(i);return 2===arguments.length&&"string"==typeof s?"defaults"===s?t.extend({},t.datepicker._defaults):c?"all"===s?t.extend({},c.settings):this._get(c,s):null:(r=s||{},"string"==typeof s&&(r={},r[s]=a),c&&(this._curInst===c&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),h=this._getMinMaxDate(c,"min"),l=this._getMinMaxDate(c,"max"),n(c.settings,r),null!==h&&r.dateFormat!==e&&r.minDate===e&&(c.settings.minDate=this._formatDate(c,h)),null!==l&&r.dateFormat!==e&&r.maxDate===e&&(c.settings.maxDate=this._formatDate(c,l)),"disabled"in r
&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(t(i),c),this._autoSize(c),this._setDate(c,o),this._updateAlternate(c),this._updateDatepicker(c)),e)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,a=t.datepicker._getInst(e.target),r=!0,o=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),r=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",a.dpDiv),n[0]&&t.datepicker._selectDay(e.target,a.selectedMonth,a.selectedY
ear,n[0]),i=t.datepicker._get(a,"onSelect"),i?(s=t.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),r=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),r=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?1:-1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),r=e.
ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?-1:1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),r=e.ctrlKey||e.metaKey;break;default:r=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):r=!1;r&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(i){var s,n,a=t.datepicker._getInst(i.target);return t.datepicker._get(a,"constrainInput")?(s=t.datepicker._possibleChars(t.datepicker._get(a,"dateFormat")),n=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">n||!s||s.indexOf(n)>-1):e},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepic
ker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var i,s,a,r,o,h,l;i=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==i&&(t.datepicker._curInst.dpDiv.stop(!0,!0),i&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),s=t.datepicker._get(i,"beforeShow"),a=s?s.apply(e,[e,i]):{},a!==!1&&(n(i.settings,a),i.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(i),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),r=!1,t(e).parents().each(function(){return r|="fixed"===t(this).css("position"),!r}),o={left:t.datepicker._pos[0],top:t.datep
icker._pos[1]},t.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(i),o=t.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(h=t.datepicker._get(i,"showAnim"),l=t.datepicker._get(i,"duration"),i.dpDiv.zIndex(t(e).zIndex()+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[h]?i.dpDiv.show(h,t.datepicker._get(i,"showOptions"),l):i.dpDiv[h||"show"](h?l:null),t.datepicker._shouldFocusInput(i)&&i.input.focus(),t.datepicker._curInst=i))}},_updateDatepicker:function(e){this.maxRows=4,a=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,s=this._getNumberOfMonths(e),n=s[1],r=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dp
Div.addClass("ui-datepicker-multi-"+n).css("width",r*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.focus(),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),a=e.dpDiv.outerHeight(),r=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-r:0,i.left-=s&&i.left===e.input.offset().le
ft?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+o?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+o):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,a,o=this._curInst;!o||e&&o!==t.data(e,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){t.datepicker._tidyDialog(o)},t.effects&&(t.effects.effect[i]||t.effects[i])?o.dpDiv.hide(i,t.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogI
nput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.
selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(e,i,s,n){var a,r=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(a=this._getInst(r[0]),a.selectedDay=a.currentDay=t("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(e,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.inp
ut&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,a=this._get(e,"altField");a&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(a).each(function(){t(this).val(n)}))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(i,s,n){if(null==i||null==s)throw"Invalid arguments";if(s="object"==typeof s?""+s:s+"",""===s)return null;var a,r,o,h,l=0,c=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=t
ypeof c?c:(new Date).getFullYear()%100+parseInt(c,10),d=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,p=(n?n.dayNames:null)||this._defaults.dayNames,f=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,m=(n?n.monthNames:null)||this._defaults.monthNames,g=-1,v=-1,_=-1,b=-1,y=!1,x=function(t){var e=i.length>a+1&&i.charAt(a+1)===t;return e&&a++,e},k=function(t){var e=x(t),i="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n=RegExp("^\\d{1,"+i+"}"),a=s.substring(l).match(n);if(!a)throw"Missing number at position "+l;return l+=a[0].length,parseInt(a[0],10)},w=function(i,n,a){var r=-1,o=t.map(x(i)?a:n,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(o,function(t,i){var n=i[1];return s.substr(l,n.length).toLowerCase()===n.toLowerCase()?(r=i[0],l+=n.length,!1):e}),-1!==r)return r+1;throw"Unknown name at position "+l},D=function(){if(s.charAt(l)!==i.charAt(a))throw"Unexpected literal at position "+l;l++};for(a=0;i.length>a;a
++)if(y)"'"!==i.charAt(a)||x("'")?D():y=!1;else switch(i.charAt(a)){case"d":_=k("d");break;case"D":w("D",d,p);break;case"o":b=k("o");break;case"m":v=k("m");break;case"M":v=w("M",f,m);break;case"y":g=k("y");break;case"@":h=new Date(k("@")),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"!":h=new Date((k("!")-this._ticksTo1970)/1e4),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"'":x("'")?D():y=!0;break;default:D()}if(s.length>l&&(o=s.substr(l),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===g?g=(new Date).getFullYear():100>g&&(g+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=g?0:-100)),b>-1)for(v=1,_=b;;){if(r=this._getDaysInMonth(g,v-1),r>=_)break;v++,_-=r}if(h=this._daylightSavingAdjust(new Date(g,v-1,_)),h.getFullYear()!==g||h.getMonth()+1!==v||h.getDate()!==_)throw"Invalid date";return h},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1
123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,a);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMo
nth()+1,2);break;case"M":u+=c("M",e.getMonth(),r,o);break;case"y":u+=h("y")?e.getFullYear():(10>e.getYear()%100?"0":"")+e.getYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,i){return t.settings[i]!==e?t.settings[i]:this._defaults[i]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),a=n,r=this._getFormatConfig(t);try{a=this.parseDate(i,s,r)||n}catch(o){s=e?"":s}t.selectedDay=a.getDate(),
t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),t.currentDay=s?a.getDate():0,t.currentMonth=s?a.getMonth():0,t.currentYear=s?a.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},a=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,a=n.getFullYear(),r=n.getMonth(),o=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":o+=parseInt(l[1],10);break;case"w":case"W":o+=7*parseInt(l[1],10);break;case"m":case"M":r+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r));break;case"y":case"Y":a+=parseInt(l[1],10),o=Math.min(o,t.datepi
cker._getDaysInMonth(a,r))}l=h.exec(i)}return new Date(a,r,o)},r=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?s:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,a=t.selectedYear,r=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=r.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=r.getMonth(),t.drawYear=t.selectedYear=t.currentYear=r.getFullYear(),n===t.selectedMonth&&a===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_at
tachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,a,r,o,h,l,c,u,d,p,f,m,g,v,_,b,y,x,k,w,D,T,C,M,S,N,I,P,A,z,H,E,F,O,W,j,R=new Date,L=this._daylightSavingAdjust(new Date(R.getFullYear(),R.getMonth(),R.getDate())),Y=this._get(t,"isRTL"),B=this._get(t,"showButtonPanel"),J=this._get(t,"hideIfNoPre
vNext"),K=this._get(t,"navigationAsDateFormat"),Q=this._getNumberOfMonths(t),V=this._get(t,"showCurrentAtPos"),U=this._get(t,"stepMonths"),q=1!==Q[0]||1!==Q[1],X=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(t,"min"),$=this._getMinMaxDate(t,"max"),Z=t.drawMonth-V,te=t.drawYear;if(0>Z&&(Z+=12,te--),$)for(e=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-Q[0]*Q[1]+1,$.getDate())),e=G&&G>e?G:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-U,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":J?"":"<a class='ui-datepicker-prev ui-corner-all ui-st
ate-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+U,1)),this._getFormatConfig(t)):n,a=this._canAdjustMonth(t,1,te,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":J?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",r=this._get(t,"currentText"),o=this._get(t,"gotoCurrent")&&t.currentDay?X:L,r=K?this.formatDate(r,o,this._getFormatConfig(t)):r,h=t.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(t,"closeText")+"</button>",l=B?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+
(Y?h:"")+(this._isInRange(t,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(Y?"":h)+"</div>":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),m=this._get(t,"monthNamesShort"),g=this._get(t,"beforeShowDay"),v=this._get(t,"showOtherMonths"),_=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",k=0;Q[0]>k;k++){for(w="",this.maxRows=4,D=0;Q[1]>D;D++){if(T=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),C=" ui-corner-all",M="",q){if(M+="<div class='ui-datepicker-group",Q[1]>1)switch(D){case 0:M+=" ui-datepicker-group-first",C=" ui-corner-"+(Y?"right":"left");break;case Q[1]-1:M+=" ui-datepicker-group-last",C=" ui-corner-"+(Y?"left":"right");break;default:M+=" ui-datepicker-group-middle",C=""}M+="'>"}for(M+="<div class='ui-da
tepicker-header ui-widget-header ui-helper-clearfix"+C+"'>"+(/all|left/.test(C)&&0===k?Y?a:s:"")+(/all|right/.test(C)&&0===k?Y?s:a:"")+this._generateMonthYearHeader(t,Z,te,G,$,k>0||D>0,f,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",S=u?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",x=0;7>x;x++)N=(x+c)%7,S+="<th"+((x+c+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[N]+"'>"+p[N]+"</span></th>";for(M+=S+"</tr></thead><tbody>",I=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,I)),P=(this._getFirstDayOfMonth(te,Z)-c+7)%7,A=Math.ceil((P+I)/7),z=q?this.maxRows>A?this.maxRows:A:A,this.maxRows=z,H=this._daylightSavingAdjust(new Date(te,Z,1-P)),E=0;z>E;E++){for(M+="<tr>",F=u?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(H)+"</td>":"",x=0;7>x;x++)O=g?g.apply(t.input?t.input[0]:null,[H]):[!0,""],W=H.getMonth()!==Z,j=W&&!_||!O[0]||G&&G>H||$&&
H>$,F+="<td class='"+((x+c+6)%7>=5?" ui-datepicker-week-end":"")+(W?" ui-datepicker-other-month":"")+(H.getTime()===T.getTime()&&Z===t.selectedMonth&&t._keyEvent||b.getTime()===H.getTime()&&b.getTime()===T.getTime()?" "+this._dayOverClass:"")+(j?" "+this._unselectableClass+" ui-state-disabled":"")+(W&&!v?"":" "+O[1]+(H.getTime()===X.getTime()?" "+this._currentClass:"")+(H.getTime()===L.getTime()?" ui-datepicker-today":""))+"'"+(W&&!v||!O[2]?"":" title='"+O[2].replace(/'/g,"'")+"'")+(j?"":" data-handler='selectDay' data-event='click' data-month='"+H.getMonth()+"' data-year='"+H.getFullYear()+"'")+">"+(W&&!v?" ":j?"<span class='ui-state-default'>"+H.getDate()+"</span>":"<a class='ui-state-default"+(H.getTime()===L.getTime()?" ui-state-highlight":"")+(H.getTime()===X.getTime()?" ui-state-active":"")+(W?" ui-priority-secondary":"")+"' href='#'>"+H.getDate()+"</a>")+"</td>",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);M+=F+"</tr>"}Z++,Z>11&&(Z=0,te++),M+="</t
body></table>"+(q?"</div>"+(Q[0]>0&&D===Q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=M}y+=w}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,a,r,o){var h,l,c,u,d,p,f,m,g=this._get(t,"changeMonth"),v=this._get(t,"changeYear"),_=this._get(t,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",y="";if(a||!g)y+="<span class='ui-datepicker-month'>"+r[e]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",c=0;12>c;c++)(!h||c>=s.getMonth())&&(!l||n.getMonth()>=c)&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+o[c]+"</option>");y+="</select>"}if(_||(b+=y+(!a&&g&&v?"":" ")),!t.yearshtml)if(t.yearshtml="",a||!v)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.m
atch(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10);
+return isNaN(e)?d:e},f=p(u[0]),m=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,t.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=f;f++)t.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),_&&(b+=(!a&&g&&v?"":" ")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.drawYear+("Y"===i?e:0),n=t.drawMonth+("M"===i?e:0),a=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),r=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,a)));t.selectedDay=r.getDate(),t.drawMonth=t.selectedMonth=r.getMonth(),t.drawYear=t.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(
t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),a=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(t,a)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),a=this._getMinMaxDate(t,"max"),r=null,o=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=s),i[1].match(/[+\-].*/)
&&(o+=s)),(!n||e.getTime()>=n.getTime())&&(!a||e.getTime()<=a.getTime())&&(!r||e.getFullYear()>=r)&&(!o||o>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).mousedown(t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepic
ker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new i,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.10.3"})(jQuery);(function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._anima
teOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)o.push(a);this.handles=n.add(t(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?
e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):this.range=t([])},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,o,r,h,l,u=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHe
ight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-u.values(e));(n>i||n===i&&(e===u._lastChangedValue||u.values(e)===c.min))&&(n=i,a=t(this),o=e)}),r=this._start(e,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),h=a.offset(),l=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:e.pageX-h.left-a.width()/2,top:e.pageY-h.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeCla
ss("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,a;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,a;this.options.values&&this
.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,a=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),a!==!1&&this.values(e,i,!0))):i!==this.value()&&(a=this._trigger("slide",t,{handle:this.handles[e],value:i}),a!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0)
,undefined):this._value()},values:function(e,i){var s,n,a;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.o
rientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e
:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,a,o=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),u["horizontal"===h.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[l?"animate":"css"](u,r.animate),h.options.range===!0&&("horizontal"===h.orientation?(0===s&&h.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+
"%",this.handle.stop(1,1)[l?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[l?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[l?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,a,o,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(o=this.options.step,n=a=
this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:a=this._valueMin();break;case t.ui.keyCode.END:a=this._valueMax();break;case t.ui.keyCode.PAGE_UP:a=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:a=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;a=this._trimAlignValue(n+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;a=this._trimAlignValue(n-o)}this._slide(i,r,a)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})})(jQuery);(function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._tr
igger("change")}}t.widget("ui.spinner",{version:"1.10.3",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void
0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._s
tart(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(
){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>▲</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>▼</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.m
in&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(t
his.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-val
uemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.3",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activa
te:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.eac
h(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;defau
lt:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDi
sabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event)
,this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr
("id"),l=t(n).closest("li"),u=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),u&&l.data("ui-tabs-aria-controls",u),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").remov
eAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i)
)},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),u={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,u))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab
.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner
-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.o
ptions.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return
{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.3",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this.
_on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip
-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,a=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=a),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function a(t){l.of=t,o.is(":hidden")||o.position(l)}var o,r,h,l=t.extend({},this.options.position);if(n){if(o=this._find(s),o.length)return o.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),o=this._tooltip(s),e(s,o.attr("id")),o.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._
on(this.document,{mousemove:a}),a(i)):o.position(t.extend({of:s},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){o.is(":visible")&&(a(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:o}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(o)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),a=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),a.stop(!0),this._hide(a,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),th
is._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:a}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.1.1.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.1.1.min.js
new file mode 100644
index 0000000..02c6970
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.1.1.min.js
@@ -0,0 +1,5 @@
+/* jquery.sparkline 2.1 - http://omnipotent.net/jquery.sparkline/
+** Licensed under the New BSD License - see above site for details */
+
+(function(a){typeof define=="function"&&define.amd?define(["jquery"],a):a(jQuery)})(function(a){"use strict";var b={},c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I=0;c=function(){return{common:{type:"line",lineColor:"#00f",fillColor:"#cdf",defaultPixelsPerValue:3,width:"auto",height:"auto",composite:!1,tagValuesAttribute:"values",tagOptionsPrefix:"spark",enableTagOptions:!1,enableHighlight:!0,highlightLighten:1.4,tooltipSkipNull:!0,tooltipPrefix:"",tooltipSuffix:"",disableHiddenCheck:!1,numberFormatter:!1,numberDigitGroupCount:3,numberDigitGroupSep:",",numberDecimalMark:".",disableTooltips:!1,disableInteraction:!1},line:{spotColor:"#f80",highlightSpotColor:"#5f5",highlightLineColor:"#f22",spotRadius:1.5,minSpotColor:"#f80",maxSpotColor:"#f80",lineWidth:1,normalRangeMin:undefined,normalRangeMax:undefined,normalRangeColor:"#ccc",drawNormalOnTop:!1,chartRangeMin:undefined,chartRangeMax:undefined,chartRangeMinX:undefined,chartRangeMaxX:undefined,tooltipFormat
:new e('<span style="color: {{color}}">●</span> {{prefix}}{{y}}{{suffix}}')},bar:{barColor:"#3366cc",negBarColor:"#f44",stackedBarColor:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],zeroColor:undefined,nullColor:undefined,zeroAxis:!0,barWidth:4,barSpacing:1,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,colorMap:undefined,tooltipFormat:new e('<span style="color: {{color}}">●</span> {{prefix}}{{value}}{{suffix}}')},tristate:{barWidth:4,barSpacing:1,posBarColor:"#6f6",negBarColor:"#f44",zeroBarColor:"#999",colorMap:{},tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value:map}}'),tooltipValueLookups:{map:{"-1":"Loss",0:"Draw",1:"Win"}}},discrete:{lineHeight:"auto",thresholdColor:undefined,thresholdValue:0,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,tooltipFormat:new e("{{prefix}}{{value}}{{suffix}}")},bullet:{targetColor:"#f33",targetWidth:3,performanceColor:"#33f",rang
eColors:["#d3dafe","#a8b6ff","#7f94ff"],base:undefined,tooltipFormat:new e("{{fieldkey:fields}} - {{value}}"),tooltipValueLookups:{fields:{r:"Range",p:"Performance",t:"Target"}}},pie:{offset:0,sliceColors:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],borderWidth:0,borderColor:"#000",tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value}} ({{percent.1}}%)')},box:{raw:!1,boxLineColor:"#000",boxFillColor:"#cdf",whiskerColor:"#000",outlierLineColor:"#333",outlierFillColor:"#fff",medianColor:"#f00",showOutliers:!0,outlierIQR:1.5,spotRadius:1.5,target:undefined,targetColor:"#4a2",chartRangeMax:undefined,chartRangeMin:undefined,tooltipFormat:new e("{{field:fields}}: {{value}}"),tooltipFormatFieldlistKey:"field",tooltipValueLookups:{fields:{lq:"Lower Quartile",med:"Median",uq:"Upper Quartile",lo:"Left Outlier",ro:"Right Outlier",lw:"Left Whisker",rw:"Right Whisker"}}}}},B='.jqstooltip { position: absolute;left: 0px;top: 0px;vi
sibility: hidden;background: rgb(0, 0, 0) transparent;background-color: rgba(0,0,0,0.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";color: white;font: 10px arial, san serif;text-align: left;white-space: nowrap;padding: 5px;border: 1px solid white;z-index: 10000;}.jqsfield { color: white;font: 10px arial, san serif;text-align: left;}',d=function(){var b,c;return b=function(){this.init.apply(this,arguments)},arguments.length>1?(arguments[0]?(b.prototype=a.extend(new arguments[0],arguments[arguments.length-1]),b._super=arguments[0].prototype):b.prototype=arguments[arguments.length-1],arguments.length>2&&(c=Array.prototype.slice.call(arguments,1,-1),c.unshift(b.prototype),a.extend.apply(a,c))):b.prototype=arguments[0],b.prototype.cls=b,b},a.SPFormatClass=e=d({fre:/\{\{([\w.]+?)(:(.+?))?\}\}/g,precre:/(\w+)\.(\d+)/,init:fun
ction(a,b){this.format=a,this.fclass=b},render:function(a,b,c){var d=this,e=a,f,g,h,i,j;return this.format.replace(this.fre,function(){var a;return g=arguments[1],h=arguments[3],f=d.precre.exec(g),f?(j=f[2],g=f[1]):j=!1,i=e[g],i===undefined?"":h&&b&&b[h]?(a=b[h],a.get?b[h].get(i)||i:b[h][i]||i):(k(i)&&(c.get("numberFormatter")?i=c.get("numberFormatter")(i):i=p(i,j,c.get("numberDigitGroupCount"),c.get("numberDigitGroupSep"),c.get("numberDecimalMark"))),i)})}}),a.spformat=function(a,b){return new e(a,b)},f=function(a,b,c){return a<b?b:a>c?c:a},g=function(a,b){var c;return b===2?(c=Math.floor(a.length/2),a.length%2?a[c]:(a[c-1]+a[c])/2):a.length%2?(c=(a.length*b+b)/4,c%1?(a[Math.floor(c)]+a[Math.floor(c)-1])/2:a[c-1]):(c=(a.length*b+2)/4,c%1?(a[Math.floor(c)]+a[Math.floor(c)-1])/2:a[c-1])},h=function(a){var b;switch(a){case"undefined":a=undefined;break;case"null":a=null;break;case"true":a=!0;break;case"false":a=!1;break;default:b=parseFloat(a),a==b&&(a=b)}return a},i=function(a
){var b,c=[];for(b=a.length;b--;)c[b]=h(a[b]);return c},j=function(a,b){var c,d,e=[];for(c=0,d=a.length;c<d;c++)a[c]!==b&&e.push(a[c]);return e},k=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},p=function(b,c,d,e,f){var g,h;b=(c===!1?parseFloat(b).toString():b.toFixed(c)).split(""),g=(g=a.inArray(".",b))<0?b.length:g,g<b.length&&(b[g]=f);for(h=g-d;h>0;h-=d)b.splice(h,0,e);return b.join("")},l=function(a,b,c){var d;for(d=b.length;d--;){if(c&&b[d]===null)continue;if(b[d]!==a)return!1}return!0},m=function(a){var b=0,c;for(c=a.length;c--;)b+=typeof a[c]=="number"?a[c]:0;return b},o=function(b){return a.isArray(b)?b:[b]},n=function(a){var b;document.createStyleSheet?document.createStyleSheet().cssText=a:(b=document.createElement("style"),b.type="text/css",document.getElementsByTagName("head")[0].appendChild(b),b[typeof document.body.style.WebkitAppearance=="string"?"innerText":"innerHTML"]=a)},a.fn.simpledraw=function(b,c,d,e){var f,g;if(d&&(f=this.data("_jqs_vcanvas")))re
turn f;b===undefined&&(b=a(this).innerWidth()),c===undefined&&(c=a(this).innerHeight());if(a.browser.hasCanvas)f=new F(b,c,this,e);else{if(!a.browser.msie)return!1;f=new G(b,c,this)}return g=a(this).data("_jqs_mhandler"),g&&g.registerCanvas(f),f},a.fn.cleardraw=function(){var a=this.data("_jqs_vcanvas");a&&a.reset()},a.RangeMapClass=q=d({init:function(a){var b,c,d=[];for(b in a)a.hasOwnProperty(b)&&typeof b=="string"&&b.indexOf(":")>-1&&(c=b.split(":"),c[0]=c[0].length===0?-Infinity:parseFloat(c[0]),c[1]=c[1].length===0?Infinity:parseFloat(c[1]),c[2]=a[b],d.push(c));this.map=a,this.rangelist=d||!1},get:function(a){var b=this.rangelist,c,d,e;if((e=this.map[a])!==undefined)return e;if(b)for(c=b.length;c--;){d=b[c];if(d[0]<=a&&d[1]>=a)return d[2]}return undefined}}),a.range_map=function(a){return new q(a)},r=d({init:function(b,c){var d=a(b);this.$el=d,this.options=c,this.currentPageX=0,this.currentPageY=0,this.el=b,this.splist=[],this.tooltip=null,this.over=!1,this.displayToolt
ips=!c.get("disableTooltips"),this.highlightEnabled=!c.get("disableHighlight")},registerSparkline:function(a){this.splist.push(a),this.over&&this.updateDisplay()},registerCanvas:function(b){var c=a(b.canvas);this.canvas=b,this.$canvas=c,c.mouseenter(a.proxy(this.mouseenter,this)),c.mouseleave(a.proxy(this.mouseleave,this)),c.click(a.proxy(this.mouseclick,this))},reset:function(a){this.splist=[],this.tooltip&&a&&(this.tooltip.remove(),this.tooltip=undefined)},mouseclick:function(b){var c=a.Event("sparklineClick");c.originalEvent=b,c.sparklines=this.splist,this.$el.trigger(c)},mouseenter:function(b){a(document.body).unbind("mousemove.jqs"),a(document.body).bind("mousemove.jqs",a.proxy(this.mousemove,this)),this.over=!0,this.currentPageX=b.pageX,this.currentPageY=b.pageY,this.currentEl=b.target,!this.tooltip&&this.displayTooltips&&(this.tooltip=new s(this.options),this.tooltip.updatePosition(b.pageX,b.pageY)),this.updateDisplay()},mouseleave:function(){a(document.body).unbind("
mousemove.jqs");var b=this.splist,c=b.length,d=!1,e,f;this.over=!1,this.currentEl=null,this.tooltip&&(this.tooltip.remove(),this.tooltip=null);for(f=0;f<c;f++)e=b[f],e.clearRegionHighlight()&&(d=!0);d&&this.canvas.render()},mousemove:function(a){this.currentPageX=a.pageX,this.currentPageY=a.pageY,this.currentEl=a.target,this.tooltip&&this.tooltip.updatePosition(a.pageX,a.pageY),this.updateDisplay()},updateDisplay:function(){var b=this.splist,c=b.length,d=!1,e=this.$canvas.offset(),f=this.currentPageX-e.left,g=this.currentPageY-e.top,h,i,j,k,l;if(!this.over)return;for(j=0;j<c;j++)i=b[j],k=i.setRegionHighlight(this.currentEl,f,g),k&&(d=!0);if(d){l=a.Event("sparklineRegionChange"),l.sparklines=this.splist,this.$el.trigger(l);if(this.tooltip){h="";for(j=0;j<c;j++)i=b[j],h+=i.getCurrentRegionTooltip();this.tooltip.setContent(h)}this.disableHighlight||this.canvas.render()}k===null&&this.mouseleave()}}),s=d({sizeStyle:"position: static !important;display: block !important;visibilit
y: hidden !important;float: left !important;",init:function(b){var c=b.get("tooltipClassname","jqstooltip"),d=this.sizeStyle,e;this.container=b.get("tooltipContainer")||document.body,this.tooltipOffsetX=b.get("tooltipOffsetX",10),this.tooltipOffsetY=b.get("tooltipOffsetY",12),a("#jqssizetip").remove(),a("#jqstooltip").remove(),this.sizetip=a("<div/>",{id:"jqssizetip",style:d,"class":c}),this.tooltip=a("<div/>",{id:"jqstooltip","class":c}).appendTo(this.container),e=this.tooltip.offset(),this.offsetLeft=e.left,this.offsetTop=e.top,this.hidden=!0,a(window).unbind("resize.jqs scroll.jqs"),a(window).bind("resize.jqs scroll.jqs",a.proxy(this.updateWindowDims,this)),this.updateWindowDims()},updateWindowDims:function(){this.scrollTop=a(window).scrollTop(),this.scrollLeft=a(window).scrollLeft(),this.scrollRight=this.scrollLeft+a(window).width(),this.updatePosition()},getSize:function(a){this.sizetip.html(a).appendTo(this.container),this.width=this.sizetip.width()+1,this.height=this.
sizetip.height(),this.sizetip.remove()},setContent:function(a){if(!a){this.tooltip.css("visibility","hidden"),this.hidden=!0;return}this.getSize(a),this.tooltip.html(a).css({width:this.width,height:this.height,visibility:"visible"}),this.hidden&&(this.hidden=!1,this.updatePosition())},updatePosition:function(a,b){if(a===undefined){if(this.mousex===undefined)return;a=this.mousex-this.offsetLeft,b=this.mousey-this.offsetTop}else this.mousex=a-=this.offsetLeft,this.mousey=b-=this.offsetTop;if(!this.height||!this.width||this.hidden)return;b-=this.height+this.tooltipOffsetY,a+=this.tooltipOffsetX,b<this.scrollTop&&(b=this.scrollTop),a<this.scrollLeft?a=this.scrollLeft:a+this.width>this.scrollRight&&(a=this.scrollRight-this.width),this.tooltip.css({left:a,top:b})},remove:function(){this.tooltip.remove(),this.sizetip.remove(),this.sizetip=this.tooltip=undefined,a(window).unbind("resize.jqs scroll.jqs")}}),C=function(){n(B)},a(C),H=[],a.fn.sparkline=function(b,c){return this.each(fu
nction(){var d=new a.fn.sparkline.options(this,c),e=a(this),f,g;f=function(){var c,f,g,h,i,j,k;if(b==="html"||b===undefined){k=this.getAttribute(d.get("tagValuesAttribute"));if(k===undefined||k===null)k=e.html();c=k.replace(/(^\s*<!--)|(-->\s*$)|\s+/g,"").split(",")}else c=b;f=d.get("width")==="auto"?c.length*d.get("defaultPixelsPerValue"):d.get("width");if(d.get("height")==="auto"){if(!d.get("composite")||!a.data(this,"_jqs_vcanvas"))h=document.createElement("span"),h.innerHTML="a",e.html(h),g=a(h).innerHeight()||a(h).height(),a(h).remove(),h=null}else g=d.get("height");d.get("disableInteraction")?i=!1:(i=a.data(this,"_jqs_mhandler"),i?d.get("composite")||i.reset():(i=new r(this,d),a.data(this,"_jqs_mhandler",i)));if(d.get("composite")&&!a.data(this,"_jqs_vcanvas")){a.data(this,"_jqs_errnotify")||(alert("Attempted to attach a composite sparkline to an element with no existing sparkline"),a.data(this,"_jqs_errnotify",!0));return}j=new(a.fn.sparkline[d.get("type")])(this,c,d,
f,g),j.render(),i&&i.registerSparkline(j)};if(a(this).html()&&!d.get("disableHiddenCheck")&&a(this).is(":hidden")||a.fn.jquery<"1.3.0"&&a(this).parents().is(":hidden")||!a(this).parents("body").length){if(!d.get("composite")&&a.data(this,"_jqs_pending"))for(g=H.length;g;g--)H[g-1][0]==this&&H.splice(g-1,1);H.push([this,f]),a.data(this,"_jqs_pending",!0)}else f.call(this)})},a.fn.sparkline.defaults=c(),a.sparkline_display_visible=function(){var b,c,d,e=[];for(c=0,d=H.length;c<d;c++)b=H[c][0],a(b).is(":visible")&&!a(b).parents().is(":hidden")?(H[c][1].call(b),a.data(H[c][0],"_jqs_pending",!1),e.push(c)):!a(b).closest("html").length&&!a.data(b,"_jqs_pending")&&(a.data(H[c][0],"_jqs_pending",!1),e.push(c));for(c=e.length;c;c--)H.splice(e[c-1],1)},a.fn.sparkline.options=d({init:function(c,d){var e,f,g,h;this.userOptions=d=d||{},this.tag=c,this.tagValCache={},f=a.fn.sparkline.defaults,g=f.common,this.tagOptionsPrefix=d.enableTagOptions&&(d.tagOptionsPrefix||g.tagOptionsPrefix),h=t
his.getTagSetting("type"),h===b?e=f[d.type||g.type]:e=f[h],this.mergedOptions=a.extend({},g,e,d)},getTagSetting:function(a){var c=this.tagOptionsPrefix,d,e,f,g;if(c===!1||c===undefined)return b;if(this.tagValCache.hasOwnProperty(a))d=this.tagValCache.key;else{d=this.tag.getAttribute(c+a);if(d===undefined||d===null)d=b;else if(d.substr(0,1)==="["){d=d.substr(1,d.length-2).split(",");for(e=d.length;e--;)d[e]=h(d[e].replace(/(^\s*)|(\s*$)/g,""))}else if(d.substr(0,1)==="{"){f=d.substr(1,d.length-2).split(","),d={};for(e=f.length;e--;)g=f[e].split(":",2),d[g[0].replace(/(^\s*)|(\s*$)/g,"")]=h(g[1].replace(/(^\s*)|(\s*$)/g,""))}else d=h(d);this.tagValCache.key=d}return d},get:function(a,c){var d=this.getTagSetting(a),e;return d!==b?d:(e=this.mergedOptions[a])===undefined?c:e}}),a.fn.sparkline._base=d({disabled:!1,init:function(b,c,d,e,f){this.el=b,this.$el=a(b),this.values=c,this.options=d,this.width=e,this.height=f,this.currentRegion=undefined},initTarget:function(){var a=!this.
options.get("disableInteraction");(this.target=this.$el.simpledraw(this.width,this.height,this.options.get("composite"),a))?(this.canvasWidth=this.target.pixelWidth,this.canvasHeight=this.target.pixelHeight):this.disabled=!0},render:function(){return this.disabled?(this.el.innerHTML="",!1):!0},getRegion:function(a,b){},setRegionHighlight:function(a,b,c){var d=this.currentRegion,e=!this.options.get("disableHighlight"),f;return b>this.canvasWidth||c>this.canvasHeight||b<0||c<0?null:(f=this.getRegion(a,b,c),d!==f?(d!==undefined&&e&&this.removeHighlight(),this.currentRegion=f,f!==undefined&&e&&this.renderHighlight(),!0):!1)},clearRegionHighlight:function(){return this.currentRegion!==undefined?(this.removeHighlight(),this.currentRegion=undefined,!0):!1},renderHighlight:function(){this.changeHighlight(!0)},removeHighlight:function(){this.changeHighlight(!1)},changeHighlight:function(a){},getCurrentRegionTooltip:function(){var b=this.options,c="",d=[],f,g,h,i,j,k,l,m,n,o,p,q,r,s;i
f(this.currentRegion===undefined)return"";f=this.getCurrentRegionFields(),p=b.get("tooltipFormatter");if(p)return p(this,b,f);b.get("tooltipChartTitle")&&(c+='<div class="jqs jqstitle">'+b.get("tooltipChartTitle")+"</div>\n"),g=this.options.get("tooltipFormat");if(!g)return"";a.isArray(g)||(g=[g]),a.isArray(f)||(f=[f]),l=this.options.get("tooltipFormatFieldlist"),m=this.options.get("tooltipFormatFieldlistKey");if(l&&m){n=[];for(k=f.length;k--;)o=f[k][m],(s=a.inArray(o,l))!=-1&&(n[s]=f[k]);f=n}h=g.length,r=f.length;for(k=0;k<h;k++){q=g[k],typeof q=="string"&&(q=new e(q)),i=q.fclass||"jqsfield";for(s=0;s<r;s++)if(!f[s].isNull||!b.get("tooltipSkipNull"))a.extend(f[s],{prefix:b.get("tooltipPrefix"),suffix:b.get("tooltipSuffix")}),j=q.render(f[s],b.get("tooltipValueLookups"),b),d.push('<div class="'+i+'">'+j+"</div>")}return d.length?c+d.join("\n"):""},getCurrentRegionFields:function(){},calcHighlightColor:function(a,b){var c=b.get("highlightColor"),d=b.get("highlightLighten"),e,
g,h,i;if(c)return c;if(d){e=/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a)||/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(a);if(e){h=[],g=a.length===4?16:1;for(i=0;i<3;i++)h[i]=f(Math.round(parseInt(e[i+1],16)*g*d),0,255);return"rgb("+h.join(",")+")"}}return a}}),t={changeHighlight:function(b){var c=this.currentRegion,d=this.target,e=this.regionShapes[c],f;e&&(f=this.renderRegion(c,b),a.isArray(f)||a.isArray(e)?(d.replaceWithShapes(e,f),this.regionShapes[c]=a.map(f,function(a){return a.id})):(d.replaceWithShape(e,f),this.regionShapes[c]=f.id))},render:function(){var b=this.values,c=this.target,d=this.regionShapes,e,f,g,h;if(!this.cls._super.render.call(this))return;for(g=b.length;g--;){e=this.renderRegion(g);if(e)if(a.isArray(e)){f=[];for(h=e.length;h--;)e[h].append(),f.push(e[h].id);d[g]=f}else e.append(),d[g]=e.id;else d[g]=null}c.render()}},a.fn.sparkline.line=u=d(a.fn.sparkline._base,{type:"line",init:function(a,b,c,d,e){u._super.init.call(this,a,b,c,d,e),this.vertice
s=[],this.regionMap=[],this.xvalues=[],this.yvalues=[],this.yminmax=[],this.hightlightSpotId=null,this.lastShapeId=null,this.initTarget()},getRegion:function(a,b,c){var d,e=this.regionMap;for(d=e.length;d--;)if(e[d]!==null&&b>=e[d][0]&&b<=e[d][1])return e[d][2];return undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.yvalues[a]===null,x:this.xvalues[a],y:this.yvalues[a],color:this.options.get("lineColor"),fillColor:this.options.get("fillColor"),offset:a}},renderHighlight:function(){var a=this.currentRegion,b=this.target,c=this.vertices[a],d=this.options,e=d.get("spotRadius"),f=d.get("highlightSpotColor"),g=d.get("highlightLineColor"),h,i;if(!c)return;e&&f&&(h=b.drawCircle(c[0],c[1],e,undefined,f),this.highlightSpotId=h.id,b.insertAfterShape(this.lastShapeId,h)),g&&(i=b.drawLine(c[0],this.canvasTop,c[0],this.canvasTop+this.canvasHeight,g),this.highlightLineId=i.id,b.insertAfterShape(this.lastShapeId,i))},removeHighlight:function(){var a=
this.target;this.highlightSpotId&&(a.removeShapeId(this.highlightSpotId),this.highlightSpotId=null),this.highlightLineId&&(a.removeShapeId(this.highlightLineId),this.highlightLineId=null)},scanValues:function(){var a=this.values,b=a.length,c=this.xvalues,d=this.yvalues,e=this.yminmax,f,g,h,i,j;for(f=0;f<b;f++)g=a[f],h=typeof a[f]=="string",i=typeof a[f]=="object"&&a[f]instanceof Array,j=h&&a[f].split(":"),h&&j.length===2?(c.push(Number(j[0])),d.push(Number(j[1])),e.push(Number(j[1]))):i?(c.push(g[0]),d.push(g[1]),e.push(g[1])):(c.push(f),a[f]===null||a[f]==="null"?d.push(null):(d.push(Number(g)),e.push(Number(g))));this.options.get("xvalues")&&(c=this.options.get("xvalues")),this.maxy=this.maxyorg=Math.max.apply(Math,e),this.miny=this.minyorg=Math.min.apply(Math,e),this.maxx=Math.max.apply(Math,c),this.minx=Math.min.apply(Math,c),this.xvalues=c,this.yvalues=d,this.yminmax=e},processRangeOptions:function(){var a=this.options,b=a.get("normalRangeMin"),c=a.get("normalRangeMax")
;b!==undefined&&(b<this.miny&&(this.miny=b),c>this.maxy&&(this.maxy=c)),a.get("chartRangeMin")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMin")<this.miny)&&(this.miny=a.get("chartRangeMin")),a.get("chartRangeMax")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMax")>this.maxy)&&(this.maxy=a.get("chartRangeMax")),a.get("chartRangeMinX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMinX")<this.minx)&&(this.minx=a.get("chartRangeMinX")),a.get("chartRangeMaxX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMaxX")>this.maxx)&&(this.maxx=a.get("chartRangeMaxX"))},drawNormalRange:function(a,b,c,d,e){var f=this.options.get("normalRangeMin"),g=this.options.get("normalRangeMax"),h=b+Math.round(c-c*((g-this.miny)/e)),i=Math.round(c*(g-f)/e);this.target.drawRect(a,h,d,i,undefined,this.options.get("normalRangeColor")).append()},render:function(){var b=this.options,c=this.target,d=this.canvasWidth,e=this.canvasHeight,f=this.vertices,g=b.get("sp
otRadius"),h=this.regionMap,i,j,k,l,m,n,o,p,r,s,t,v,w,x,y,z,A,B,C,D,E,F,G,H,I;if(!u._super.render.call(this))return;this.scanValues(),this.processRangeOptions(),G=this.xvalues,H=this.yvalues;if(!this.yminmax.length||this.yvalues.length<2)return;l=m=0,i=this.maxx-this.minx===0?1:this.maxx-this.minx,j=this.maxy-this.miny===0?1:this.maxy-this.miny,k=this.yvalues.length-1,g&&(d<g*4||e<g*4)&&(g=0);if(g){E=b.get("highlightSpotColor")&&!b.get("disableInteraction");if(E||b.get("minSpotColor")||b.get("spotColor")&&H[k]===this.miny)e-=Math.ceil(g);if(E||b.get("maxSpotColor")||b.get("spotColor")&&H[k]===this.maxy)e-=Math.ceil(g),l+=Math.ceil(g);if(E||(b.get("minSpotColor")||b.get("maxSpotColor"))&&(H[0]===this.miny||H[0]===this.maxy))m+=Math.ceil(g),d-=Math.ceil(g);if(E||b.get("spotColor")||b.get("minSpotColor")||b.get("maxSpotColor")&&(H[k]===this.miny||H[k]===this.maxy))d-=Math.ceil(g)}e--,b.get("normalRangeMin")!==undefined&&!b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j)
,o=[],p=[o],x=y=null,z=H.length;for(I=0;I<z;I++)r=G[I],t=G[I+1],s=H[I],v=m+Math.round((r-this.minx)*(d/i)),w=I<z-1?m+Math.round((t-this.minx)*(d/i)):d,y=v+(w-v)/2,h[I]=[x||0,y,I],x=y,s===null?I&&(H[I-1]!==null&&(o=[],p.push(o)),f.push(null)):(s<this.miny&&(s=this.miny),s>this.maxy&&(s=this.maxy),o.length||o.push([v,l+e]),n=[v,l+Math.round(e-e*((s-this.miny)/j))],o.push(n),f.push(n));A=[],B=[],C=p.length;for(I=0;I<C;I++)o=p[I],o.length&&(b.get("fillColor")&&(o.push([o[o.length-1][0],l+e]),B.push(o.slice(0)),o.pop()),o.length>2&&(o[0]=[o[0][0],o[1][1]]),A.push(o));C=B.length;for(I=0;I<C;I++)c.drawShape(B[I],b.get("fillColor"),b.get("fillColor")).append();b.get("normalRangeMin")!==undefined&&b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j),C=A.length;for(I=0;I<C;I++)c.drawShape(A[I],b.get("lineColor"),undefined,b.get("lineWidth")).append();if(g&&b.get("valueSpots")){D=b.get("valueSpots"),D.get===undefined&&(D=new q(D));for(I=0;I<z;I++)F=D.get(H[I]),F&&c.drawCircle(m+Ma
th.round((G[I]-this.minx)*(d/i)),l+Math.round(e-e*((H[I]-this.miny)/j)),g,undefined,F).append()}g&&b.get("spotColor")&&c.drawCircle(m+Math.round((G[G.length-1]-this.minx)*(d/i)),l+Math.round(e-e*((H[k]-this.miny)/j)),g,undefined,b.get("spotColor")).append(),this.maxy!==this.minyorg&&(g&&b.get("minSpotColor")&&(r=G[a.inArray(this.minyorg,H)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.minyorg-this.miny)/j)),g,undefined,b.get("minSpotColor")).append()),g&&b.get("maxSpotColor")&&(r=G[a.inArray(this.maxyorg,H)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.maxyorg-this.miny)/j)),g,undefined,b.get("maxSpotColor")).append())),this.lastShapeId=c.getLastShapeId(),this.canvasTop=l,c.render()}}),a.fn.sparkline.bar=v=d(a.fn.sparkline._base,t,{type:"bar",init:function(b,c,d,e,g){var k=parseInt(d.get("barWidth"),10),l=parseInt(d.get("barSpacing"),10),m=d.get("chartRangeMin"),n=d.get("chartRangeMax"),o=d.get("chartRangeClip"),p=Infinity,
r=-Infinity,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P;v._super.init.call(this,b,c,d,e,g);for(y=0,z=c.length;y<z;y++){M=c[y],s=typeof M=="string"&&M.indexOf(":")>-1;if(s||a.isArray(M))H=!0,s&&(M=c[y]=i(M.split(":"))),M=j(M,null),t=Math.min.apply(Math,M),u=Math.max.apply(Math,M),t<p&&(p=t),u>r&&(r=u)}this.stacked=H,this.regionShapes={},this.barWidth=k,this.barSpacing=l,this.totalBarWidth=k+l,this.width=e=c.length*k+(c.length-1)*l,this.initTarget(),o&&(F=m===undefined?-Infinity:m,G=n===undefined?Infinity:n),x=[],w=H?[]:x;var Q=[],R=[];for(y=0,z=c.length;y<z;y++)if(H){I=c[y],c[y]=L=[],Q[y]=0,w[y]=R[y]=0;for(J=0,K=I.length;J<K;J++)M=L[J]=o?f(I[J],F,G):I[J],M!==null&&(M>0&&(Q[y]+=M),p<0&&r>0?M<0?R[y]+=Math.abs(M):w[y]+=M:w[y]+=Math.abs(M-(M<0?r:p)),x.push(M))}else M=o?f(c[y],F,G):c[y],M=c[y]=h(M),M!==null&&x.push(M);this.max=E=Math.max.apply(Math,x),this.min=D=Math.min.apply(Math,x),this.stackMax=r=H?Math.max.apply(Math,Q):E,this.stackMin=p=H?Math.min.apply(Math,x):D,d.get("ch
artRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<D)&&(D=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMax")>E)&&(E=d.get("chartRangeMax")),this.zeroAxis=B=d.get("zeroAxis",!0),D<=0&&E>=0&&B?C=0:B==0?C=D:D>0?C=D:C=E,this.xaxisOffset=C,A=H?Math.max.apply(Math,w)+Math.max.apply(Math,R):E-D,this.canvasHeightEf=B&&D<0?this.canvasHeight-2:this.canvasHeight-1,D<C?(O=H&&E>=0?r:E,N=(O-C)/A*this.canvasHeight,N!==Math.ceil(N)&&(this.canvasHeightEf-=2,N=Math.ceil(N))):N=this.canvasHeight,this.yoffset=N,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.range=A},getRegion:function(a,b,c){var d=Math.floor(b/this.totalBarWidth);return d<0||d>=this.values.length?undefined:d},getCurren
tRegionFields:function(){var a=this.currentRegion,b=o(this.values[a]),c=[],d,e;for(e=b.length;e--;)d=b[e],c.push({isNull:d===null,value:d,color:this.calcColor(e,d,a),offset:a});return c},calcColor:function(b,c,d){var e=this.colorMapByIndex,f=this.colorMapByValue,g=this.options,h,i;return this.stacked?h=g.get("stackedBarColor"):h=c<0?g.get("negBarColor"):g.get("barColor"),c===0&&g.get("zeroColor")!==undefined&&(h=g.get("zeroColor")),f&&(i=f.get(c))?h=i:e&&e.length>d&&(h=e[d]),a.isArray(h)?h[b%h.length]:h},renderRegion:function(b,c){var d=this.values[b],e=this.options,f=this.xaxisOffset,g=[],h=this.range,i=this.stacked,j=this.target,k=b*this.totalBarWidth,m=this.canvasHeightEf,n=this.yoffset,o,p,q,r,s,t,u,v,w,x;d=a.isArray(d)?d:[d],u=d.length,v=d[0],r=l(null,d),x=l(f,d,!0);if(r)return e.get("nullColor")?(q=c?e.get("nullColor"):this.calcHighlightColor(e.get("nullColor"),e),o=n>0?n-1:n,j.drawRect(k,o,this.barWidth-1,0,q,q)):undefined;s=n;for(t=0;t<u;t++){v=d[t];if(i&&v===f){if(!
x||w)continue;w=!0}h>0?p=Math.floor(m*(Math.abs(v-f)/h))+1:p=1,v<f||v===f&&n===0?(o=s,s+=p):(o=n-p,n-=p),q=this.calcColor(t,v,b),c&&(q=this.calcHighlightColor(q,e)),g.push(j.drawRect(k,o,this.barWidth-1,p-1,q,q))}return g.length===1?g[0]:g}}),a.fn.sparkline.tristate=w=d(a.fn.sparkline._base,t,{type:"tristate",init:function(b,c,d,e,f){var g=parseInt(d.get("barWidth"),10),h=parseInt(d.get("barSpacing"),10);w._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.barWidth=g,this.barSpacing=h,this.totalBarWidth=g+h,this.values=a.map(c,Number),this.width=e=c.length*g+(c.length-1)*h,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.initTarget()},getRegion:function(a,b,c){return Math.floor(b/this.totalBarWidth)},getCurrentRegionFields:function(){var a=t
his.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],color:this.calcColor(this.values[a],a),offset:a}},calcColor:function(a,b){var c=this.values,d=this.options,e=this.colorMapByIndex,f=this.colorMapByValue,g,h;return f&&(h=f.get(a))?g=h:e&&e.length>b?g=e[b]:c[b]<0?g=d.get("negBarColor"):c[b]>0?g=d.get("posBarColor"):g=d.get("zeroBarColor"),g},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.target,f,g,h,i,j,k;f=e.pixelHeight,h=Math.round(f/2),i=a*this.totalBarWidth,c[a]<0?(j=h,g=h-1):c[a]>0?(j=0,g=h-1):(j=h-1,g=2),k=this.calcColor(c[a],a);if(k===null)return;return b&&(k=this.calcHighlightColor(k,d)),e.drawRect(i,j,this.barWidth-1,g-1,k,k)}}),a.fn.sparkline.discrete=x=d(a.fn.sparkline._base,t,{type:"discrete",init:function(b,c,d,e,f){x._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.values=c=a.map(c,Number),this.min=Math.min.apply(Math,c),this.max=Math.max.apply(Math,c),this.range=this.max-this.min,this.width=e=d.get("wi
dth")==="auto"?c.length*2:this.width,this.interval=Math.floor(e/c.length),this.itemWidth=e/c.length,d.get("chartRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<this.min)&&(this.min=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMax")>this.max)&&(this.max=d.get("chartRangeMax")),this.initTarget(),this.target&&(this.lineHeight=d.get("lineHeight")==="auto"?Math.round(this.canvasHeight*.3):d.get("lineHeight"))},getRegion:function(a,b,c){return Math.floor(b/this.itemWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],offset:a}},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.min,g=this.max,h=this.range,i=this.interval,j=this.target,k=this.canvasHeight,l=this.lineHeight,m=k-l,n,o,p,q;return o=f(c[a],e,g),q=a*i,n=Math.round(m-m*((o-e)/h)),p=d.get("thresholdColor")&&o<d.get("thresholdValue")?d.get("thresholdC
olor"):d.get("lineColor"),b&&(p=this.calcHighlightColor(p,d)),j.drawLine(q,n,q,n+l,p)}}),a.fn.sparkline.bullet=y=d(a.fn.sparkline._base,{type:"bullet",init:function(a,b,c,d,e){var f,g,h;y._super.init.call(this,a,b,c,d,e),this.values=b=i(b),h=b.slice(),h[0]=h[0]===null?h[2]:h[0],h[1]=b[1]===null?h[2]:h[1],f=Math.min.apply(Math,b),g=Math.max.apply(Math,b),c.get("base")===undefined?f=f<0?f:0:f=c.get("base"),this.min=f,this.max=g,this.range=g-f,this.shapes={},this.valueShapes={},this.regiondata={},this.width=d=c.get("width")==="auto"?"4.0em":d,this.target=this.$el.simpledraw(d,e,c.get("composite")),b.length||(this.disabled=!0),this.initTarget()},getRegion:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{fieldkey:a.substr(0,1),value:this.values[a.substr(1)],region:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.valueShapes
[b],d;delete this.shapes[c];switch(b.substr(0,1)){case"r":d=this.renderRange(b.substr(1),a);break;case"p":d=this.renderPerformance(a);break;case"t":d=this.renderTarget(a)}this.valueShapes[b]=d.id,this.shapes[d.id]=b,this.target.replaceWithShape(c,d)},renderRange:function(a,b){var c=this.values[a],d=Math.round(this.canvasWidth*((c-this.min)/this.range)),e=this.options.get("rangeColors")[a-2];return b&&(e=this.calcHighlightColor(e,this.options)),this.target.drawRect(0,0,d-1,this.canvasHeight-1,e,e)},renderPerformance:function(a){var b=this.values[1],c=Math.round(this.canvasWidth*((b-this.min)/this.range)),d=this.options.get("performanceColor");return a&&(d=this.calcHighlightColor(d,this.options)),this.target.drawRect(0,Math.round(this.canvasHeight*.3),c-1,Math.round(this.canvasHeight*.4)-1,d,d)},renderTarget:function(a){var b=this.values[0],c=Math.round(this.canvasWidth*((b-this.min)/this.range)-this.options.get("targetWidth")/2),d=Math.round(this.canvasHeight*.1),e=this.canva
sHeight-d*2,f=this.options.get("targetColor");return a&&(f=this.calcHighlightColor(f,this.options)),this.target.drawRect(c,d,this.options.get("targetWidth")-1,e-1,f,f)},render:function(){var a=this.values.length,b=this.target,c,d;if(!y._super.render.call(this))return;for(c=2;c<a;c++)d=this.renderRange(c).append(),this.shapes[d.id]="r"+c,this.valueShapes["r"+c]=d.id;this.values[1]!==null&&(d=this.renderPerformance().append(),this.shapes[d.id]="p1",this.valueShapes.p1=d.id),this.values[0]!==null&&(d=this.renderTarget().append(),this.shapes[d.id]="t0",this.valueShapes.t0=d.id),b.render()}}),a.fn.sparkline.pie=z=d(a.fn.sparkline._base,{type:"pie",init:function(b,c,d,e,f){var g=0,h;z._super.init.call(this,b,c,d,e,f),this.shapes={},this.valueShapes={},this.values=c=a.map(c,Number),d.get("width")==="auto"&&(this.width=this.height);if(c.length>0)for(h=c.length;h--;)g+=c[h];this.total=g,this.initTarget(),this.radius=Math.floor(Math.min(this.canvasWidth,this.canvasHeight)/2)},getRegio
n:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],percent:this.values[a]/this.total*100,color:this.options.get("sliceColors")[a%this.options.get("sliceColors").length],offset:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.renderSlice(b,a),d=this.valueShapes[b];delete this.shapes[d],this.target.replaceWithShape(d,c),this.valueShapes[b]=c.id,this.shapes[c.id]=b},renderSlice:function(a,b){var c=this.target,d=this.options,e=this.radius,f=d.get("borderWidth"),g=d.get("offset"),h=2*Math.PI,i=this.values,j=this.total,k=g?2*Math.PI*(g/360):0,l,m,n,o,p;o=i.length;for(n=0;n<o;n++){l=k,m=k,j>0&&(m=k+h*(i[n]/j));if(a===n)return p=d.get("sliceColors")[n%d.get("sliceColors").length],b&&(p=this.calcHighlightColor(p,d)),c.drawPieSlice(e,e,e-f,l,m,undefined,p);k=m}},render:funct
ion(){var a=this.target,b=this.values,c=this.options,d=this.radius,e=c.get("borderWidth"),f,g;if(!z._super.render.call(this))return;
+e&&a.drawCircle(d,d,Math.floor(d-e/2),c.get("borderColor"),undefined,e).append();for(g=b.length;g--;)b[g]&&(f=this.renderSlice(g).append(),this.valueShapes[g]=f.id,this.shapes[f.id]=g);a.render()}}),a.fn.sparkline.box=A=d(a.fn.sparkline._base,{type:"box",init:function(b,c,d,e,f){A._super.init.call(this,b,c,d,e,f),this.values=a.map(c,Number),this.width=d.get("width")==="auto"?"4.0em":e,this.initTarget(),this.values.length||(this.disabled=1)},getRegion:function(){return 1},getCurrentRegionFields:function(){var a=[{field:"lq",value:this.quartiles[0]},{field:"med",value:this.quartiles[1]},{field:"uq",value:this.quartiles[2]}];return this.loutlier!==undefined&&a.push({field:"lo",value:this.loutlier}),this.routlier!==undefined&&a.push({field:"ro",value:this.routlier}),this.lwhisker!==undefined&&a.push({field:"lw",value:this.lwhisker}),this.rwhisker!==undefined&&a.push({field:"rw",value:this.rwhisker}),a},render:function(){var a=this.target,b=this.values,c=b.length,d=this.options,e
=this.canvasWidth,f=this.canvasHeight,h=d.get("chartRangeMin")===undefined?Math.min.apply(Math,b):d.get("chartRangeMin"),i=d.get("chartRangeMax")===undefined?Math.max.apply(Math,b):d.get("chartRangeMax"),j=0,k,l,m,n,o,p,q,r,s,t,u;if(!A._super.render.call(this))return;if(d.get("raw"))d.get("showOutliers")&&b.length>5?(l=b[0],k=b[1],n=b[2],o=b[3],p=b[4],q=b[5],r=b[6]):(k=b[0],n=b[1],o=b[2],p=b[3],q=b[4]);else{b.sort(function(a,b){return a-b}),n=g(b,1),o=g(b,2),p=g(b,3),m=p-n;if(d.get("showOutliers")){k=q=undefined;for(s=0;s<c;s++)k===undefined&&b[s]>n-m*d.get("outlierIQR")&&(k=b[s]),b[s]<p+m*d.get("outlierIQR")&&(q=b[s]);l=b[0],r=b[c-1]}else k=b[0],q=b[c-1]}this.quartiles=[n,o,p],this.lwhisker=k,this.rwhisker=q,this.loutlier=l,this.routlier=r,u=e/(i-h+1),d.get("showOutliers")&&(j=Math.ceil(d.get("spotRadius")),e-=2*Math.ceil(d.get("spotRadius")),u=e/(i-h+1),l<k&&a.drawCircle((l-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append(),r>q&&a.
drawCircle((r-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append()),a.drawRect(Math.round((n-h)*u+j),Math.round(f*.1),Math.round((p-n)*u),Math.round(f*.8),d.get("boxLineColor"),d.get("boxFillColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/2),Math.round((n-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/4),Math.round((k-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math.round((q-h)*u+j),Math.round(f/2),Math.round((p-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((q-h)*u+j),Math.round(f/4),Math.round((q-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math.round((o-h)*u+j),Math.round(f*.1),Math.round((o-h)*u+j),Math.round(f*.9),d.get("medianColor")).append(),d.get("target")&&(t=Math.ceil(d.get("spotRadius")),a.drawLine(Math.round((d.get("target")-h)*u+j),Math.round(f/2-t),Math.round((d.get("target")-h)
*u+j),Math.round(f/2+t),d.get("targetColor")).append(),a.drawLine(Math.round((d.get("target")-h)*u+j-t),Math.round(f/2),Math.round((d.get("target")-h)*u+j+t),Math.round(f/2),d.get("targetColor")).append()),a.render()}}),a.browser.msie&&document.namespaces&&!document.namespaces.v&&document.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"),a.browser.hasCanvas===undefined&&(a.browser.hasCanvas=document.createElement("canvas").getContext!==undefined),D=d({init:function(a,b,c,d){this.target=a,this.id=b,this.type=c,this.args=d},append:function(){return this.target.appendShape(this),this}}),E=d({_pxregex:/(\d+)(px)?\s*$/i,init:function(b,c,d){if(!b)return;this.width=b,this.height=c,this.target=d,this.lastShapeId=null,d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this)},drawLine:function(a,b,c,d,e,f){return this.drawShape([[a,b],[c,d]],e,f)},drawShape:function(a,b,c,d){return this._genShape("Shape",[a,b,c,d])},drawCircle:function(a,b,c,d,e,f){return this._genShape("Circle"
,[a,b,c,d,e,f])},drawPieSlice:function(a,b,c,d,e,f,g){return this._genShape("PieSlice",[a,b,c,d,e,f,g])},drawRect:function(a,b,c,d,e,f){return this._genShape("Rect",[a,b,c,d,e,f])},getElement:function(){return this.canvas},getLastShapeId:function(){return this.lastShapeId},reset:function(){alert("reset not implemented")},_insert:function(b,c){a(c).html(b)},_calculatePixelDims:function(b,c,d){var e;e=this._pxregex.exec(c),e?this.pixelHeight=e[1]:this.pixelHeight=a(d).height(),e=this._pxregex.exec(b),e?this.pixelWidth=e[1]:this.pixelWidth=a(d).width()},_genShape:function(a,b){var c=I++;return b.unshift(c),new D(this,c,a,b)},appendShape:function(a){alert("appendShape not implemented")},replaceWithShape:function(a,b){alert("replaceWithShape not implemented")},insertAfterShape:function(a,b){alert("insertAfterShape not implemented")},removeShapeId:function(a){alert("removeShapeId not implemented")},getShapeAt:function(a,b,c){alert("getShapeAt not implemented")},render:function(){a
lert("render not implemented")}}),F=d(E,{init:function(b,c,d,e){F._super.init.call(this,b,c,d),this.canvas=document.createElement("canvas"),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),a(this.canvas).css({display:"inline-block",width:b,height:c,verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,this.interact=e,this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined,a(this.canvas).css({width:this.pixelWidth,height:this.pixelHeight})},_getContext:function(a,b,c){var d=this.canvas.getContext("2d");return a!==undefined&&(d.strokeStyle=a),d.lineWidth=c===undefined?1:c,b!==undefined&&(d.fillStyle=b),d},reset:function(){var a=this._getContext();a.clearRect(0,0,this.pixelWidth,this.pixelHeight),this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined},_drawShape:function(a,b,c,d,e){var f=this._getContext(c,d,e),g,h;f.beginPath(),f.moveTo(b[0][0]+.5,b[
0][1]+.5);for(g=1,h=b.length;g<h;g++)f.lineTo(b[g][0]+.5,b[g][1]+.5);c!==undefined&&f.stroke(),d!==undefined&&f.fill(),this.targetX!==undefined&&this.targetY!==undefined&&f.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawCircle:function(a,b,c,d,e,f,g){var h=this._getContext(e,f,g);h.beginPath(),h.arc(b,c,d,0,2*Math.PI,!1),this.targetX!==undefined&&this.targetY!==undefined&&h.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a),e!==undefined&&h.stroke(),f!==undefined&&h.fill()},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i=this._getContext(g,h);i.beginPath(),i.moveTo(b,c),i.arc(b,c,d,e,f,!1),i.lineTo(b,c),i.closePath(),g!==undefined&&i.stroke(),h&&i.fill(),this.targetX!==undefined&&this.targetY!==undefined&&i.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b+d,c],[b+d,c+e],[b,c+e],[b,c]],f,g)},appendShape:function(a){return this.shapes[a
.id]=a,this.shapeseq.push(a.id),this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=this.shapeseq,d;this.shapes[b.id]=b;for(d=c.length;d--;)c[d]==a&&(c[d]=b.id);delete this.shapes[a]},replaceWithShapes:function(a,b){var c=this.shapeseq,d={},e,f,g;for(f=a.length;f--;)d[a[f]]=!0;for(f=c.length;f--;)e=c[f],d[e]&&(c.splice(f,1),delete this.shapes[e],g=f);for(f=b.length;f--;)c.splice(g,0,b[f].id),this.shapes[b[f].id]=b[f]},insertAfterShape:function(a,b){var c=this.shapeseq,d;for(d=c.length;d--;)if(c[d]===a){c.splice(d+1,0,b.id),this.shapes[b.id]=b;return}},removeShapeId:function(a){var b=this.shapeseq,c;for(c=b.length;c--;)if(b[c]===a){b.splice(c,1);break}delete this.shapes[a]},getShapeAt:function(a,b,c){return this.targetX=b,this.targetY=c,this.render(),this.currentTargetShapeId},render:function(){var a=this.shapeseq,b=this.shapes,c=a.length,d=this._getContext(),e,f,g;d.clearRect(0,0,this.pixelWidth,this.pixelHeight);for(g=0;g<c;g++)e=a[g],f=b[e],this["_draw"+f.type
].apply(this,f.args);this.interact||(this.shapes={},this.shapeseq=[])}}),G=d(E,{init:function(b,c,d){var e;G._super.init.call(this,b,c,d),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),this.canvas=document.createElement("span"),a(this.canvas).css({display:"inline-block",position:"relative",overflow:"hidden",width:b,height:c,margin:"0px",padding:"0px",verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,e='<v:group coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'"'+' style="position:absolute;top:0;left:0;width:'+this.pixelWidth+"px;height="+this.pixelHeight+'px;"></v:group>',this.canvas.insertAdjacentHTML("beforeEnd",e),this.group=a(this.canvas).children()[0],this.rendered=!1,this.prerender=""},_drawShape:function(a,b,c,d,e){var f=[],g,h,i,j,k,l,m;for(m=0,l=b.length;m<l;m++)f[m]=""+b[m][0]+","+b[m][1];return g=f.splice(0,1),e=e===undefined?1:e,h=c===
undefined?' stroked="false" ':' strokeWeight="'+e+'px" strokeColor="'+c+'" ',i=d===undefined?' filled="false"':' fillColor="'+d+'" filled="true" ',j=f[0]===f[f.length-1]?"x ":"",k='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+h+i+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+g+" l "+f.join(", ")+" "+j+'e">'+" </v:shape>",k},_drawCircle:function(a,b,c,d,e,f,g){var h,i,j;return b-=d,c-=d,h=e===undefined?' stroked="false" ':' strokeWeight="'+g+'px" strokeColor="'+e+'" ',i=f===undefined?' filled="false"':' fillColor="'+f+'" filled="true" ',j='<v:oval id="jqsshape'+a+'" '+h+i+' style="position:absolute;top:'+c+"px; left:"+b+"px; width:"+d*2+"px; height:"+d*2+'px"></v:oval>',j},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i,j,k,l,m,n,o,p;if(e===f)return;f-e===2*Math.PI&&(e=0,f=2*Math.PI),j=b+Math.round(Math.cos(e)*d),k=c+Math.ro
und(Math.sin(e)*d),l=b+Math.round(Math.cos(f)*d),m=c+Math.round(Math.sin(f)*d);if(j===l&&k===m&&f-e<Math.PI)return;return i=[b-d,c-d,b+d,c+d,j,k,l,m],n=g===undefined?' stroked="false" ':' strokeWeight="1px" strokeColor="'+g+'" ',o=h===undefined?' filled="false"':' fillColor="'+h+'" filled="true" ',p='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+n+o+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+b+","+c+" wa "+i.join(", ")+' x e">'+" </v:shape>",p},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b,c+e],[b+d,c+e],[b+d,c],[b,c]],f,g)},reset:function(){this.group.innerHTML=""},appendShape:function(a){var b=this["_draw"+a.type].apply(this,a.args);return this.rendered?this.group.insertAdjacentHTML("beforeEnd",b):this.prerender+=b,this.lastShapeId=a.id,a.id},replaceWithShape:function(b,c){var d=a("#jqsshape"+b),
e=this["_draw"+c.type].apply(this,c.args);d[0].outerHTML=e},replaceWithShapes:function(b,c){var d=a("#jqsshape"+b[0]),e="",f=c.length,g;for(g=0;g<f;g++)e+=this["_draw"+c[g].type].apply(this,c[g].args);d[0].outerHTML=e;for(g=1;g<b.length;g++)a("#jqsshape"+b[g]).remove()},insertAfterShape:function(b,c){var d=a("#jqsshape"+b),e=this["_draw"+c.type].apply(this,c.args);d[0].insertAdjacentHTML("afterEnd",e)},removeShapeId:function(b){var c=a("#jqsshape"+b);this.group.removeChild(c[0])},getShapeAt:function(a,b,c){var d=a.id.substr(8);return d},render:function(){this.rendered||(this.group.innerHTML=this.prerender,this.rendered=!0)}})});
\ No newline at end of file
10 years, 11 months
[rhq] Changes to 'mtho11/d3-slider'
by mike thompson
New branch 'mtho11/d3-slider' available with the following commits:
commit 8b1385965c523bfefb2686b63257883a1b51d2b9
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 14:59:22 2013 -0700
Remove old style Date Range control from MeasurementTableView.
10 years, 11 months
[rhq] 4 commits - .classpath modules/enterprise
by snegrea
.classpath | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/DownloadsView.java | 56
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/SystemGWTService.java | 17
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SystemGWTServiceImpl.java | 29
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 4
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties | 4
modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml | 8
modules/enterprise/server/data-migration/src/test/java/org/rhq/server/metrics/DataSourceTest.java | 169 ++
modules/enterprise/server/data-migration/src/test/resources/log4j.properties | 42
modules/enterprise/server/data-migration/tools/create_test_data.py | 213 +++
modules/enterprise/server/data-migration/tools/plugin_descriptor_metrics.py | 65
modules/enterprise/server/jar/pom.xml | 26
modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/RHQControl.java | 2
modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java | 52
modules/enterprise/server/server-metrics/pom.xml | 84 -
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java | 309 ----
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java | 672 ----------
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java | 124 -
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java | 58
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java | 64
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java | 36
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java | 80 -
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java | 156 --
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java | 57
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java | 123 -
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java | 262 ---
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java | 38
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java | 89 -
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java | 167 --
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java | 71 -
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java | 250 ---
modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/DataSourceTest.java | 169 --
modules/enterprise/server/server-metrics/tools/create_test_data.py | 213 ---
modules/enterprise/server/server-metrics/tools/plugin_descriptor_metrics.py | 65
34 files changed, 538 insertions(+), 3237 deletions(-)
New commits:
commit 3ca9f219182ff73472fc55587374a7fb4d6f8d61
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Jun 19 14:54:37 2013 -0500
Update the data migration upgrade option to use the newly created data-migration module and starting scripts.
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
index 5d4fd54..2abdd0f 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
@@ -208,13 +208,13 @@ public class Upgrade extends AbstractInstall {
}
- private void runDataMigration(CommandLine rhqCtlCommandLine) {
+ private void runDataMigration(CommandLine rhqctlCommandLine) {
- String migrationOption = rhqCtlCommandLine.getOptionValue(RUN_DATA_MIGRATION);
+ String migrationOption = rhqctlCommandLine.getOptionValue(RUN_DATA_MIGRATION);
if (migrationOption.equals("none")) {
log.info("No data migration will run");
- if (!isRhq48OrLater(rhqCtlCommandLine)) {
+ if (!isRhq48OrLater(rhqctlCommandLine)) {
printDataMigrationNotice();
}
return;
@@ -238,54 +238,34 @@ public class Upgrade extends AbstractInstall {
dbType = "postgres";
} else if (dbType.toLowerCase().contains("oracle")) {
dbType = "oracle";
- throw new RHQControlException("Can not migrate oracle databases yet");
} else {
throw new RHQControlException("Unknown database type " + dbType + " can not migrate data");
}
- // Password in the properties file is obfuscated
- String dbPassword = deobfuscatePassword(dbPasswordProperty);
-
- File dataMigratorJar = getFileDownload("data-migrator", "rhq-data-migrator");
+ org.apache.commons.exec.CommandLine commandLine = getCommandLine("rhq-data-migration");
String cassandraHost = InetAddress.getLocalHost().getCanonicalHostName();
- org.apache.commons.exec.CommandLine commandLine = new org.apache.commons.exec.CommandLine("java")
- //
- .addArgument("-jar")
- .addArgument(dataMigratorJar.getAbsolutePath())
- //
-
- .addArgument("--sql-user").addArgument(dbUser).addArgument("--sql-db").addArgument(dbName)
- .addArgument("--sql-host").addArgument(dbServerName).addArgument("--sql-port")
- .addArgument(dbServerPort).addArgument("--sql-server-type").addArgument(dbType)
- .addArgument("--cassandra-hosts").addArgument(cassandraHost);
-
- String commandLineString = commandLine.toString();
- if (migrationOption.equals("print-command")) {
- log.info(commandLineString);
- return;
- }
+ // Password in the properties file is obfuscated
+ String dbPassword = deobfuscatePassword(dbPasswordProperty);
- // Add the password after generating commandLineString to
- // not print the password on stdout
- commandLine.addArgument("--sql-password ").addArgument(dbPassword);
+ commandLine.addArgument("--sql-user").addArgument(dbUser)
+ .addArgument("--sql-db").addArgument(dbName)
+ .addArgument("--sql-host").addArgument(dbServerName)
+ .addArgument("--sql-port").addArgument(dbServerPort)
+ .addArgument("--sql-server-type").addArgument(dbType)
+ .addArgument("--cassandra-hosts").addArgument(cassandraHost)
+ .addArgument("--sql-password ").addArgument(dbPassword);
if (migrationOption.equals("estimate")) {
commandLine.addArgument("--estimate-only");
}
Executor executor = new DefaultExecutor();
- executor.setWorkingDirectory(getBaseDir());
+ executor.setWorkingDirectory(getBinDir());
executor.setStreamHandler(new PumpStreamHandler());
int exitValue = executor.execute(commandLine);
log.info("The data migrator finished with exit value " + exitValue);
-
- if (migrationOption.equals("estimate")) {
- log.info("You can use this command line as a start to later run the data migrator\n\n"
- + commandLineString);
- }
-
} catch (Exception e) {
log.error("Running the data migrator failed - please try to run it from the command line: "
+ e.getMessage());
@@ -731,8 +711,8 @@ public class Upgrade extends AbstractInstall {
+ "you need to run the data migration job to transfer stored (historic)\n"
+ "metrics data from the relational database into the new storage.\n"
+ "Until the migration has run, that historic data is not available \n" + "in e.g. the charting views.\n\n"
- + "To run the data migration, you can download the migration app from the\n"
- + "server and run it on the command line.\n" + "================\n");
+ + "To run the data migration, just run rhq-data-migration.{sh|bat}\n"
+ + "script located in the server bin folder.\n" + "================\n");
}
}
commit 15bb71d42c8ba35161f8de4307aef341368caeae
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Jun 19 14:48:49 2013 -0500
Avoid packaging sigar.zip since the maven ear plugin does not know what to do with it and errors out.
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 6732dad..71a997d 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -64,6 +64,32 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-cassandra-schema</artifactId>
<version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hyperic</groupId>
+ <artifactId>sigar-dist</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.datastax.cassandra</groupId>
+ <artifactId>cassandra-driver-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-plugin-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-plugin-api</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hyperic</groupId>
+ <artifactId>sigar-dist</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
commit cd3fd289dc7ef470218576a591a3c4e6ea4434a9
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Jun 19 12:37:00 2013 -0500
Revert "Mention the data migrator after install and provide it in the server downloads section."
This reverts commit 19518a7912a965bdc7d7583ed2d1c73a35abb3a2.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/DownloadsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/DownloadsView.java
index e839460..950b57d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/DownloadsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/DownloadsView.java
@@ -43,7 +43,7 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
/**
* A simple page to view the downloads the server provides (like
* the agent update binary and the CLI distro).
- *
+ *
* @author John Mazzitelli
*/
public class DownloadsView extends EnhancedVLayout {
@@ -60,7 +60,6 @@ public class DownloadsView extends EnhancedVLayout {
private SectionStackSection cliSection;
private SectionStackSection bundleSection;
private SectionStackSection connectorsSection;
- private SectionStackSection migratorSection;
private SectionStackSection cliAlertScriptsSection;
private SectionStackSection scriptModulesSection;
@@ -84,7 +83,6 @@ public class DownloadsView extends EnhancedVLayout {
cliSection = new SectionStackSection(MSG.view_admin_downloads_cliDownload());
bundleSection = new SectionStackSection(MSG.view_admin_downloads_bundleDownload());
connectorsSection = new SectionStackSection(MSG.view_admin_downloads_connectorsDownload());
- migratorSection = new SectionStackSection(MSG.view_admin_downloads_migratorDownload());
cliAlertScriptsSection = new SectionStackSection(MSG.view_admin_downloads_cliAlertScriptsDownload());
scriptModulesSection = new SectionStackSection(MSG.view_admin_downloads_scriptModulesDownload());
@@ -99,7 +97,6 @@ public class DownloadsView extends EnhancedVLayout {
sectionStack.addSection(cliSection);
sectionStack.addSection(bundleSection);
sectionStack.addSection(connectorsSection);
- sectionStack.addSection(migratorSection);
sectionStack.addSection(cliAlertScriptsSection);
sectionStack.addSection(scriptModulesSection);
@@ -114,7 +111,6 @@ public class DownloadsView extends EnhancedVLayout {
prepareCLISection();
prepareBundleSection();
prepareConnectorsSection();
- prepareMigratorSection();
prepareCliAlertScriptsSection();
prepareScriptModulesSection();
}
@@ -313,56 +309,6 @@ public class DownloadsView extends EnhancedVLayout {
});
}
- private void prepareMigratorSection() {
- systemManager.getMigratorDownloads(new AsyncCallback<HashMap<String, String>>() {
- @Override
- public void onSuccess(HashMap<String, String> result) {
- DynamicForm form = new DynamicForm();
- form.setMargin(10);
- form.setWidth100();
-
- if (result != null && !result.isEmpty()) {
- int i = 0;
- FormItem[] items = new FormItem[result.size() + 2];
-
- for (Map.Entry<String, String> entry : result.entrySet()) {
- StaticTextItem linkItem = new StaticTextItem("link" + i);
- linkItem.setTitle(MSG.common_label_link());
- linkItem.setValue("<a href=\"" + entry.getValue() + "\">" + entry.getKey() + "</a>");
- items[i++] = linkItem;
- }
-
- SpacerItem spacerItem = new SpacerItem("spacer");
- spacerItem.setHeight(5);
- items[i++] = spacerItem;
-
- StaticTextItem helpText = new StaticTextItem("migratorHelp");
- helpText.setColSpan(2);
- helpText.setShowTitle(false);
- helpText.setValue(MSG.view_admin_downloads_migrator_help(productInfo.getShortName()));
- items[i++] = helpText;
-
- form.setItems(items);
- } else {
- StaticTextItem item = new StaticTextItem("noMigrator");
- item.setColSpan(2);
- item.setShowTitle(false);
- item.setValue(MSG.view_admin_downloads_migrator_none());
- form.setItems(item);
- }
-
- migratorSection.setItems(form);
- migratorSection.setExpanded(true);
- sectionStack.markForRedraw();
- }
-
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_admin_downloads_migrator_loadError(), caught);
- }
- });
- }
-
private void prepareCliAlertScriptsSection() {
systemManager.getCliAlertScriptDownloads(new AsyncCallback<HashMap<String, String>>() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/SystemGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/SystemGWTService.java
index 03daa5d..dc522ea 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/SystemGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/SystemGWTService.java
@@ -59,20 +59,11 @@ public interface SystemGWTService extends RemoteService {
HashMap<String, String> getConnectorDownloads() throws RuntimeException;
/**
- * Returns the name and download URL (key and value respectively) of all data-migrator downloads
- * available on the server. The URL is relative to the server's host and port (i.e. only
- * the path of the URL is returned).
- *
- * @return information about data-migrators that can be downloaded from the server
- */
- HashMap<String, String> getMigratorDownloads() throws RuntimeException;
-
- /**
* Returns the name and download URL (key and value respectively) of all CLI alert scripts
- * that are available on the server for download. These are just scripts that users can
+ * that are available on the server for download. These are just scripts that users can
* then use to create actual cli scripts for alert notifications. These scripts will usually
* require some tweaking to be usable as alert scripts.
- *
+ *
* @return info about the available CLI alert scripts
* @throws RuntimeException
*/
@@ -82,12 +73,12 @@ public interface SystemGWTService extends RemoteService {
* Returns the name and download URL (key and value respectively) of all script modules
* that are available on the server for download. These are provided by RHQ for other
* scripts to peruse using the module-loading mechanism of particular language.
- *
+ *
* @return info about the available script modules
* @throws RuntimeException
*/
HashMap<String, String> getScriptModulesDownloads() throws RuntimeException;
-
+
/**
* @return metadata properties about the CLI download available on the server.
*/
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SystemGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SystemGWTServiceImpl.java
index 5a934d7..168522d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SystemGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SystemGWTServiceImpl.java
@@ -146,26 +146,6 @@ public class SystemGWTServiceImpl extends AbstractGWTServiceImpl implements Syst
}
@Override
- public HashMap<String, String> getMigratorDownloads() throws RuntimeException {
- try {
- File downloadDir = getMigratorDownloadsDir();
- List<File> files = getFiles(downloadDir);
- if (files == null) {
- return new HashMap<String, String>(0);
- }
- HashMap<String, String> map = new HashMap<String, String>(files.size());
- for (File file : files) {
- // key is the filename, value is the relative URL to download the file from the server
- map.put(file.getName(), "/downloads/data-migrator/" + file.getName());
- }
- return map;
- } catch (Throwable t) {
- throw getExceptionToThrowToClient(t);
- }
-
- }
-
- @Override
public HashMap<String, String> getCliAlertScriptDownloads() throws RuntimeException {
try {
File downloadsDir = getCliAlertScriptDownloadsDir();
@@ -251,15 +231,6 @@ public class SystemGWTServiceImpl extends AbstractGWTServiceImpl implements Syst
return downloadDir;
}
- private File getMigratorDownloadsDir() {
- File homeDir = getDownloadHomeDir();
- File downloadDir = new File(homeDir, "data-migrator");
- if (!downloadDir.isDirectory()) {
- throw new RuntimeException("Server is missing data-migrator directory at [" + downloadDir + "]");
- }
- return downloadDir;
- }
-
private File getCliAlertScriptDownloadsDir() {
File homeDir = getDownloadHomeDir();
File downloadDir = new File(homeDir, "cli-alert-scripts");
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index febda16..62a202a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -686,10 +686,6 @@ view_admin_downloads_connectorsDownload = Connectors Download
view_admin_downloads_connectors_help = Connectors are software that is needed in order for some products to be manageable by {0}. You install connectors into some managed products so {0} agents can talk to them. See the documentation for more information.
view_admin_downloads_connectors_loadError = Cannot get connectors info
view_admin_downloads_connectors_none = No connectors are available for download
-view_admin_downloads_migratorDownload = Data Migrator Download
-view_admin_downloads_migrator_help = This is the data migrator standalone application for {0}. You can run it via java -jar rhq-data-migrator.jar. Choose option --help for help
-view_admin_downloads_migrator_none = No data migrators are available for download
-view_admin_downloads_migrator_loadError = Cannot get data migrator info
view_admin_downloads_scriptModulesDownload = Script Modules Download
view_admin_downloads_scriptModules_help = <p> Script modules are reusable components provided by RHQ to be used in your scripts (either alert scripts or CLI scripts). You can access them by using the "rhq://downloads/<module-name-without-file-extension>" URI in your scripting language of choice (i.e. in javascript, you would use the "require" function).</p>
view_admin_downloads_scriptModules_loadError = Cannot load the list of available script modules
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 11dbffd..050b459 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -664,10 +664,6 @@ view_admin_downloads_cli_version = Version des CLI
##view_admin_downloads_connectors_help = Connectors are software that is needed in order for some products to be manageable by {0}. You install connectors into some managed products so {0} agents can talk to them. See the documentation for more information.
##view_admin_downloads_connectors_loadError = Cannot get connectors info
##view_admin_downloads_connectors_none = No connectors are available for download
-view_admin_downloads_migratorDownload = Data Migrator Download
-view_admin_downloads_migrator_help = Dies ist die Appliktion zur Datenmigration für {0}. Sie können Sie mittlels ''java -jar rhq-data-migrator.jar'' starten. Nutzen Sie die Option --help für Details
-view_admin_downloads_migrator_none = Es steht kein Datenmigrator zum Download bereit
-view_admin_downloads_migrator_loadError = Kann keine Informationen zum Datenmigrator ermitteln
##view_admin_downloads_scriptModulesDownload = Script Modules Download
##view_admin_downloads_scriptModules_help = <p> Script modules are reusable components provided by RHQ to be used in your scripts (either alert scripts or CLI scripts). You can access them by using the "rhq://downloads/<module-name-without-file-extension>" URI in your scripting language of choice (i.e. in javascript, you would use the "require" function).</p>
##view_admin_downloads_scriptModules_loadError = Cannot load the list of available script modules
diff --git a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
index 839dbda..d11e27b 100644
--- a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
@@ -363,7 +363,6 @@
<mkdir dir="${rhq.ear.dir}/rhq-downloads/rhq-plugins" />
<mkdir dir="${rhq.ear.dir}/rhq-downloads/connectors" />
<mkdir dir="${rhq.ear.dir}/rhq-downloads/bundle-deployer" />
- <mkdir dir="${rhq.ear.dir}/rhq-downloads/data-migrator" />
<echo>Deploying the latest agent update binary and renaming it rhq-enterprise-agent-${rhq.version}.jar</echo>
<copy file="${settings.localRepository}/org/rhq/rhq-enterprise-agentupdate/${rhq.version}/rhq-enterprise-agentupdate-${rhq.version}.jar"
@@ -383,13 +382,6 @@
verbose="true"
failonerror="false"/>
- <echo>Deploying the latest data-migrator to the downloads location</echo>
- <!--<copy file="${settings.localRepository}/org/rhq/rhq-ant-bundle-common/${rhq.version}/rhq-ant-bundle-common-${rhq.version}.zip"-->
- <copy file="../server-metrics/target/migrator-executable/data-migrator-${rhq.version}.jar"
- tofile="${rhq.ear.dir}/rhq-downloads/data-migrator/rhq-data-migrator-${rhq.version}.jar"
- verbose="true"
- failonerror="true"/>
-
<antcall target="package-connectors" />
<!-- we don't need these in our modules directory because we deploy the rtfilter directly in the EAR
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/RHQControl.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/RHQControl.java
index e60848a..542708f 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/RHQControl.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/RHQControl.java
@@ -105,7 +105,7 @@ public class RHQControl {
System.exit(0);
} catch (RHQControlException e) {
Throwable rootCause = ThrowableUtil.getRootCause(e);
- control.log.error("There was an unexpected error: " + rootCause.getMessage(), rootCause);
+ control.log.error("There was an unxpected error: " + rootCause.getMessage(), rootCause);
System.exit(1);
}
}
commit ee8f7a33ea99dcc7a353a778dc71ab144190debd
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Jun 19 11:43:10 2013 -0500
Remove data migrator from server metrics module. The code has been relocated in a separate module.
diff --git a/.classpath b/.classpath
index 6be942c..d46b67d 100644
--- a/.classpath
+++ b/.classpath
@@ -214,6 +214,7 @@
<classpathentry kind="src" path="modules/common/cassandra-ccm/cassandra-ccm-testng/src/test/java"/>
<classpathentry kind="src" path="modules/common/cassandra-jmx/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/rhq-storage/src/main/java"/>
+ <classpathentry kind="src" path="modules/enterprise/server/data-migration/src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/apache/httpcomponents/httpclient/4.2.3/httpclient-4.2.3.jar" sourcepath="M2_REPO/org/apache/httpcomponents/httpclient/4.2.3/httpclient-4.2.3-sources.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/apache/httpcomponents/httpcore/4.2.2/httpcore-4.2.2.jar" sourcepath="M2_REPO/org/apache/httpcomponents/httpcore/4.2.2/httpcore-4.2.2-sources.jar"/>
diff --git a/modules/enterprise/server/data-migration/src/test/java/org/rhq/server/metrics/DataSourceTest.java b/modules/enterprise/server/data-migration/src/test/java/org/rhq/server/metrics/DataSourceTest.java
new file mode 100644
index 0000000..cda04ca
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/test/java/org/rhq/server/metrics/DataSourceTest.java
@@ -0,0 +1,169 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.server.metrics;
+
+import java.util.List;
+import java.util.Properties;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.commons.lang.time.StopWatch;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import org.rhq.server.metrics.migrator.ExistingDataBulkExportSource;
+import org.rhq.server.metrics.migrator.ExistingPostgresDataBulkExportSource;
+
+/**
+ * @author Thomas Segismont
+ */
+
+
+public class DataSourceTest {
+
+ //ExistingPostgresDataBulkExport
+ public static void main(String[] args) throws Exception {
+ BasicConfigurator.configure();
+ Logger.getRootLogger().setLevel(Level.INFO);
+ Logger.getLogger("org.rhq").setLevel(Level.DEBUG);
+ EntityManagerFactory entityManagerFactory = null;
+ EntityManager entityManager = null;
+ ExistingDataBulkExportSource source = null;
+ try {
+ entityManagerFactory = createEntityManager();
+ entityManager = entityManagerFactory.createEntityManager();
+ source = new ExistingPostgresDataBulkExportSource(entityManager,
+ "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1D");
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+ source.initialize();
+ int rowIndex = 0;
+ int maxResults = 30000;
+ for (;;) {
+ List<Object[]> existingData = source.getData(rowIndex, maxResults);
+ if (existingData.size() < maxResults) {
+ break;
+ } else {
+ rowIndex += maxResults;
+ }
+ }
+ stopWatch.stop();
+ System.out.println("Execution: " + stopWatch);
+ } finally {
+ if (source != null) {
+ source.close();
+ }
+ if (entityManager != null) {
+ entityManager.close();
+ }
+ if (entityManagerFactory != null) {
+ entityManagerFactory.close();
+ }
+ }
+ }
+
+ private static EntityManagerFactory createEntityManager() throws Exception {
+ Properties properties = new Properties();
+ properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
+ properties.put("hibernate.connection.username", "rhqadmin");
+ properties.put("hibernate.connection.password", "rhqadmin");
+ properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
+ String driverClassName = "org.postgresql.Driver";
+ try {
+ //Required to preload the driver manually.
+ //Without this the driver load will fail due to the packaging.
+ Class.forName(driverClassName);
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Postgres SQL Driver class could not be loaded. Missing class: " + driverClassName);
+ }
+ properties.put("hibernate.driver_class", driverClassName);
+ properties.put("hibernate.connection.url", "jdbc:postgresql://localhost:5432/rhq");
+ Ejb3Configuration configuration = new Ejb3Configuration();
+ configuration.setProperties(properties);
+ return configuration.buildEntityManagerFactory();
+ }
+
+ //ExistingDataJPABulkExportSource
+
+ public static void main2(String[] args) throws Exception {
+ BasicConfigurator.configure();
+ Logger.getRootLogger().setLevel(Level.INFO);
+ Logger.getLogger("org.rhq").setLevel(Level.DEBUG);
+ EntityManagerFactory entityManagerFactory = null;
+ EntityManager entityManager = null;
+ ExistingDataBulkExportSource source = null;
+ try {
+ entityManagerFactory = createEntityManager();
+ entityManager = entityManagerFactory.createEntityManager();
+ source = new ExistingPostgresDataBulkExportSource(entityManager,
+ "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1D");
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+ source.initialize();
+ int rowIndex = 0;
+ int maxResults = 30000;
+ for (;;) {
+ List<Object[]> existingData = source.getData(rowIndex, maxResults);
+ if (existingData.size() < maxResults) {
+ break;
+ } else {
+ rowIndex += maxResults;
+ }
+ }
+ stopWatch.stop();
+ System.out.println("Execution: " + stopWatch);
+ } finally {
+ if (source != null) {
+ source.close();
+ }
+ if (entityManager != null) {
+ entityManager.close();
+ }
+ if (entityManagerFactory != null) {
+ entityManagerFactory.close();
+ }
+ }
+ }
+
+ private static EntityManagerFactory createEntityManager2() throws Exception {
+ Properties properties = new Properties();
+ properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
+ properties.put("hibernate.connection.username", "rhqadmin");
+ properties.put("hibernate.connection.password", "rhqadmin");
+ properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
+ String driverClassName = "org.postgresql.Driver";
+ try {
+ //Required to preload the driver manually.
+ //Without this the driver load will fail due to the packaging.
+ Class.forName(driverClassName);
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Postgres SQL Driver class could not be loaded. Missing class: " + driverClassName);
+ }
+ properties.put("hibernate.driver_class", driverClassName);
+ properties.put("hibernate.connection.url", "jdbc:postgresql://localhost:5432/rhqdev");
+ Ejb3Configuration configuration = new Ejb3Configuration();
+ configuration.setProperties(properties);
+ return configuration.buildEntityManagerFactory();
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/data-migration/src/test/resources/log4j.properties b/modules/enterprise/server/data-migration/src/test/resources/log4j.properties
new file mode 100644
index 0000000..c13e2bd
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/test/resources/log4j.properties
@@ -0,0 +1,42 @@
+#
+# /*
+# * RHQ Management Platform
+# * Copyright (C) 2005-2012 Red Hat, Inc.
+# * All rights reserved.
+# *
+# * This program is free software; you can redistribute it and/or modify
+# * it under the terms of the GNU General Public License, version 2, as
+# * published by the Free Software Foundation, and/or the GNU Lesser
+# * General Public License, version 2.1, also as published by the Free
+# * Software Foundation.
+# *
+# * This program is distributed in the hope that it will be useful,
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# * GNU General Public License and the GNU Lesser General Public License
+# * for more details.
+# *
+# * You should have received a copy of the GNU General Public License
+# * and the GNU Lesser General Public License along with this program;
+# * if not, write to the Free Software Foundation, Inc.,
+# * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# */
+#
+
+log4j.rootCategory=WARN, FILE, CONSOLE
+
+log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.FILE.DatePattern='.'yyyy-MM-dd
+log4j.appender.FILE.File=./target/test.log
+log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.FILE.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c %m%n
+#log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
+log4j.appender.FILE.Append=false
+
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+#log4j.appender.CONSOLE.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c %m%n
+
+log4j.logger.org.rhq=DEBUG
+log4j.logger.com.datastax=INFO
diff --git a/modules/enterprise/server/data-migration/tools/create_test_data.py b/modules/enterprise/server/data-migration/tools/create_test_data.py
new file mode 100644
index 0000000..4e60f04
--- /dev/null
+++ b/modules/enterprise/server/data-migration/tools/create_test_data.py
@@ -0,0 +1,213 @@
+#
+# RHQ Management Platform
+# Copyright (C) 2005-2013 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+# Notes:
+#1) All times are expressed in milliseconds because the database stores timestamps in milliseconds
+#2) The data is randomly generated and does represent a live system collection patterns
+#3) The amount of data generated is based on estimates described at:
+# https://docs.jboss.org/author/display/RHQ/Metrics+Data+Migration+-+Design
+#4) The data generated is in a state consistent with the migration process
+#5) !!!! All existing data is wiped out of the existing database tables and new data only is written back!!!
+# !!!! You will lose your data if your this script without manually disabling the data deletion part !!!!
+#6) Expect the generation process to take about 60 seconds per agent
+#7) The script is configured to generate data for 10 agents, if you can increase that limit by updating the variables below
+
+import psycopg2
+import sys
+import random
+import time
+import cStringIO
+import math
+from optparse import OptionParser
+
+
+def parse_arguments():
+ parser = OptionParser()
+
+ #db settings
+ parser.add_option("--host", default="localhost", action="store", type="string", dest="db_host")
+ parser.add_option("--database", default="rhq_db", action="store", type="string", dest="db_database")
+ parser.add_option("--user", default="rhqadmin", action="store", type="string", dest="db_user")
+ parser.add_option("--password", default="rhqadmin", action="store", type="string", dest="db_password")
+
+ #program settings
+ parser.add_option("--agents", default=10, action="store", type="int", dest="number_of_agents")
+
+
+ (options, args) = parser.parse_args()
+ print options
+
+ return options
+
+class MetricType:
+ Raw,Aggregate = range(2)
+
+
+RANDOM_DATA_FACTOR = 10000;
+
+
+def generate_random_metrics(number_of_metrics = 1000, start_timestamp = 0, number_of_schedule_ids = 1, start_of_schedule_id_sequence = 1, metricType = MetricType.Raw):
+ #generate a random series of timestamps for the random metrics
+ end_timestamp = start_timestamp + number_of_metrics * 10;
+ timestamps = random.sample(range(start_timestamp,end_timestamp),number_of_metrics)
+
+ #generate a random set of schedule ids
+ end_of_schedule_id_sequence = start_of_schedule_id_sequence + number_of_schedule_ids * 100;
+ schedule_ids = random.sample(range(start_of_schedule_id_sequence,end_of_schedule_id_sequence),number_of_schedule_ids);
+
+ #the set of random metrics
+ random_metrics = []
+
+ #generate the random metrics
+ for i in range(number_of_metrics):
+ if metricType == MetricType.Raw :
+ value = generate_random_raw_value()
+ else :
+ value = generate_random_aggregate_value()
+
+ random_metric = ( random.choice(schedule_ids) , timestamps[i]) + value
+ random_metrics.append(random_metric);
+
+ return random_metrics
+
+
+def generate_random_raw_value():
+ #raw metrics have just value
+ return (random.random()*RANDOM_DATA_FACTOR,)
+
+
+def generate_random_aggregate_value():
+ #aggregate metrics have min, max, and value
+ random_values = [random.random()*RANDOM_DATA_FACTOR,random.random()*RANDOM_DATA_FACTOR, random.random()*RANDOM_DATA_FACTOR]
+ min_value = min(random_values)
+ max_value = max(random_values)
+ random_values.remove(min_value)
+ random_values.remove(max_value)
+ average_value = random_values.pop()
+
+ return (average_value, min_value, max_value)
+
+
+def insert_data(connection,data,table_name,table_columns):
+ #do the postgres insertion using copy_from functionality since it's the fastest method
+ #to bulk import data
+ start_time = time.time()
+ input_data = cStringIO.StringIO(data)
+ cursor = connection.cursor()
+ cursor.copy_from(input_data,sep="\t",table = table_name, columns = table_columns)
+ cursor.close()
+ connection.commit()
+ end_time = time.time()
+ return end_time - start_time
+
+
+def delete_table_data(connection, table):
+ delete_statement = "DELETE FROM " + table;
+ connection.cursor().execute(delete_statement)
+ connection.commit()
+
+
+def calculate_mean_standard_deviation(numbers):
+
+ average = reduce(lambda x, y: x + y, numbers) / len(numbers)
+ variance = map(lambda x: (x - average)**2, numbers)
+ average_variance = reduce(lambda x, y: x + y, variance) / len(variance)
+ standard_deviation = math.sqrt(average_variance)
+ return average, standard_deviation
+
+
+
+#Main Script
+script_start_time = time.time()
+
+
+#Parse Command Line Arguments
+options = parse_arguments()
+
+
+#General Configuration
+raw_tables = map(lambda x: "RHQ_MEAS_DATA_NUM_R"+str(x).zfill(2),range(15))
+raw_table_columns = ["schedule_id","time_stamp","value"]
+
+aggregate_tables = map(lambda x: "RHQ_MEASUREMENT_DATA_NUM_"+str(x),["1H","6H","1D"])
+aggregate_table_columns = ["schedule_id","time_stamp","value","minvalue","maxvalue"]
+
+ # see the estimation guideline at https://docs.jboss.org/author/display/RHQ/Metrics+Data+Migration+-+Design
+raw_metrics_per_agent = 900000
+aggregate_metrics_per_agent = 700000
+
+
+# some constants to be used by the algorithm
+batch_increment = 10000
+data_start_time = int(time.time() - 2*604800)*1000 # now - 2 week, convert to milliseconds
+
+#establish the db connection, update the settings for your local environment
+connection = psycopg2.connect(host=options.db_host,database=options.db_database,user=options.db_user,password=options.db_password)
+
+
+#Delete all data available
+map(lambda x : delete_table_data(connection, x), raw_tables)
+map(lambda x : delete_table_data(connection, x), aggregate_tables)
+
+
+
+metric_agent_inserting_time = []
+metric_agent_total_time = []
+
+#Generate random raw and aggregate data
+for j in range(options.number_of_agents) :
+ agent_start_time = time.time()
+ agent_inserting_time = 0
+
+ #generate and insert random metrics
+ for i in range(0,raw_metrics_per_agent,batch_increment):
+ current_batch = i / batch_increment
+ random_raw_table = random.choice(raw_tables)
+
+ raw_metrics = generate_random_metrics( number_of_metrics = batch_increment, start_timestamp = data_start_time + current_batch*batch_increment*10, \
+ start_of_schedule_id_sequence = j * batch_increment, metricType = MetricType.Raw)
+
+ data_to_insert = "\n".join(map(str,map(lambda x: "\t".join((str(s) for s in x)),raw_metrics)))
+ agent_inserting_time += insert_data(connection,data_to_insert,random_raw_table,raw_table_columns)
+
+ #generate and insert aggregate metrics
+ for i in range(0,aggregate_metrics_per_agent,batch_increment):
+ current_batch = i / batch_increment
+ random_aggregate_table = random.choice(aggregate_tables)
+
+ aggregate_metrics = generate_random_metrics( number_of_metrics = batch_increment, start_timestamp = data_start_time + current_batch*batch_increment*10, \
+ start_of_schedule_id_sequence = j * batch_increment, metricType = MetricType.Aggregate )
+
+ data_to_insert = "\n".join(map(str,map(lambda x: "\t".join((str(s) for s in x)),aggregate_metrics)))
+ agent_inserting_time += insert_data(connection,data_to_insert,random_aggregate_table,aggregate_table_columns)
+
+ metric_agent_inserting_time.append(agent_inserting_time)
+ metric_agent_total_time.append( time.time() - agent_start_time )
+
+ print "Data created for agent #",j, " - total time:", time.time() - agent_start_time, " seconds"
+
+print "Total time: ",time.time() - script_start_time, " seconds"
+
+average_inserting_time, standard_deviation_inserting_time = calculate_mean_standard_deviation(metric_agent_inserting_time)
+print "Time spent inserting data: ", metric_agent_inserting_time, " seconds"
+print "Average time inserting data for 1 agent:", average_inserting_time, " seconds with a standard deviation of ", standard_deviation_inserting_time
+
+average_time, standard_deviation_time = calculate_mean_standard_deviation(metric_agent_total_time)
+print "Time spent for each agent: ", metric_agent_total_time , " seconds"
+print "Average time for 1 agent:", average_time, " seconds with a standard deviation of ", standard_deviation_time
diff --git a/modules/enterprise/server/data-migration/tools/plugin_descriptor_metrics.py b/modules/enterprise/server/data-migration/tools/plugin_descriptor_metrics.py
new file mode 100644
index 0000000..41e5bcf
--- /dev/null
+++ b/modules/enterprise/server/data-migration/tools/plugin_descriptor_metrics.py
@@ -0,0 +1,65 @@
+#
+# RHQ Management Platform
+# Copyright (C) 2005-2013 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import os
+import operator
+from xml.dom import minidom
+
+def extract_plugin(descriptor):
+ prefix = "rhq/modules/plugins/"
+ descriptor = descriptor.replace(prefix,"")
+ return descriptor[:descriptor.index("/")]
+
+to_parse = []
+to_parse.append("rhq/modules/plugins")
+
+plugin_descriptors = []
+
+while len(to_parse) != 0:
+ current_folder = to_parse.pop(0)
+ for current_file in os.listdir(current_folder):
+ if current_file != "target":
+ if os.path.isdir(os.path.join(current_folder,current_file)):
+ to_parse.append(os.path.join(current_folder,current_file))
+ else:
+ if current_file.endswith("rhq-plugin.xml"):
+ plugin_descriptors.append(os.path.join(current_folder,current_file))
+
+final_tally = []
+
+for descriptor in plugin_descriptors:
+ xml_doc = minidom.parse(descriptor)
+ metric_list = xml_doc.getElementsByTagName("metric")
+ summary_metrics = 0
+ detail_metrics = 0
+ for metric in metric_list:
+ if (metric.attributes.has_key("dataType") and metric.attributes["dataType"].value == "measurement") or \
+ not metric.attributes.has_key("dataType"):
+ if metric.attributes.has_key("displayType") and metric.attributes["displayType"].value == "summary":
+ summary_metrics += 1
+ else:
+ detail_metrics +=1
+
+ final_tally.append((extract_plugin(descriptor), summary_metrics, detail_metrics))
+
+
+index1 = operator.itemgetter(1,2)
+final_tally.sort(key=index1, reverse=True)
+for (plugin_name, summary_metrics,detail_metrics) in final_tally :
+ print "|",plugin_name,"|",summary_metrics,"|",detail_metrics,"|", summary_metrics + detail_metrics, "|"
diff --git a/modules/enterprise/server/server-metrics/pom.xml b/modules/enterprise/server/server-metrics/pom.xml
index 6c4424e..f40f684 100644
--- a/modules/enterprise/server/server-metrics/pom.xml
+++ b/modules/enterprise/server/server-metrics/pom.xml
@@ -161,43 +161,10 @@
</systemPropertyVariables>
</configuration>
</plugin>
-
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- <archive>
- <manifest>
- <mainClass>org.rhq.server.metrics.migrator.DataMigratorRunner</mainClass>
- <addClasspath>true</addClasspath>
- </manifest>
- </archive>
- </configuration>
- <executions>
- <execution>
- <id>package-jar-with-dependencies</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- <configuration>
- <attach>false</attach>
- <finalName>migrator-executable/data-migrator-${project.version}</finalName>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
<profiles>
- <!--
- Temporarily commenting out dev profile. The data migrator self-executing JAR was
- getting deployed to the EAR and causing the EAR deployment to fail. I think the
- assembly might need to be moved outside of the dev profile.
- -->
<profile>
<id>dev</id>
<properties>
@@ -246,56 +213,5 @@
</plugins>
</build>
</profile>
-
- <profile>
- <id>oracle</id>
- <activation>
- <activeByDefault>false</activeByDefault>
- </activation>
-
- <dependencies>
- <!-- Oracle JDBC driver - required only if you want to run the tests, or dbsetup, against Oracle.
- Add a top level dependency if this profile is active to allow for db-required tests in any module.
- The driver can not be packaged for OpenSource distributions due to licensing issues, and as such,
- this profile should not be active by default. -->
- <dependency>
- <groupId>com.oracle</groupId>
- <artifactId>ojdbc6</artifactId>
- <version>${ojdbc6.version}</version>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- <archive>
- <manifest>
- <mainClass>org.rhq.server.metrics.migrator.DataMigratorRunner</mainClass>
- <addClasspath>true</addClasspath>
- </manifest>
- </archive>
- </configuration>
- <executions>
- <execution>
- <id>package-jar-with-dependencies</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- <configuration>
- <attach>false</attach>
- <finalName>migrator-executable/data-migrator-oracle-${project.version}</finalName>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
</profiles>
</project>
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java
deleted file mode 100644
index 9578e73..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2011, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator;
-
-import javax.persistence.EntityManager;
-
-import com.datastax.driver.core.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.rhq.server.metrics.domain.MetricsTable;
-import org.rhq.server.metrics.migrator.workers.AggregateDataMigrator;
-import org.rhq.server.metrics.migrator.workers.CallableMigrationWorker;
-import org.rhq.server.metrics.migrator.workers.DeleteAllData;
-import org.rhq.server.metrics.migrator.workers.RawDataMigrator;
-
-
-/**
- * @author Stefan Negrea
- *
- */
-public class DataMigrator {
-
- public enum DatabaseType {
- Postgres, Oracle
- }
-
- public enum Task {
- Migrate, Estimate
- }
-
- private interface RunnableWithException extends Runnable {
- Exception getException();
- }
-
- private final Log log = LogFactory.getLog(DataMigrator.class);
-
- public static final double UNDER_ESTIMATION_FACTOR = .15;
- public static final int SQL_TIMEOUT = 6000000;
- public static final int MAX_NUMBER_OF_FAILURES = 5;
-
- private final DataMigratorConfiguration config;
- private long estimation;
-
- public DataMigrator(EntityManager entityManager, Session session, DatabaseType databaseType) {
- this(entityManager, session, databaseType, false);
- }
-
- public DataMigrator(EntityManager entityManager, Session session, DatabaseType databaseType,
- boolean experimentalDataSource) {
-
- config = new DataMigratorConfiguration(entityManager, session, databaseType, experimentalDataSource);
- config.setDeleteDataImmediatelyAfterMigration(false);
- config.setDeleteAllDataAtEndOfMigration(false);
- config.setRunRawDataMigration(true);
- config.setRun1HAggregateDataMigration(true);
- config.setRun6HAggregateDataMigration(true);
- config.setRun1DAggregateDataMigration(true);
- }
-
- public void runRawDataMigration(boolean value) {
- config.setRunRawDataMigration(value);
- }
-
- public void run1HAggregateDataMigration(boolean value) {
- config.setRun1HAggregateDataMigration(value);
- }
-
- public void run6HAggregateDataMigration(boolean value) {
- config.setRun6HAggregateDataMigration(value);
- }
-
- public void run1DAggregateDataMigration(boolean value) {
- config.setRun1DAggregateDataMigration(value);
- }
-
- public void deleteDataImmediatelyAfterMigration() {
- config.setDeleteDataImmediatelyAfterMigration(true);
- config.setDeleteAllDataAtEndOfMigration(false);
- }
-
- public void deleteAllDataAtEndOfMigration() {
- config.setDeleteAllDataAtEndOfMigration(true);
- config.setDeleteDataImmediatelyAfterMigration(false);
- }
-
- public void preserveData() {
- config.setDeleteAllDataAtEndOfMigration(false);
- config.setDeleteDataImmediatelyAfterMigration(false);
- }
-
- public long estimate() throws Exception {
- this.estimation = 0;
- if (config.isRunRawDataMigration()) {
- retryOnFailure(new RawDataMigrator(config), Task.Estimate);
- }
-
- if (config.isRun1HAggregateDataMigration()) {
- retryOnFailure(new AggregateDataMigrator(MetricsTable.ONE_HOUR, config), Task.Estimate);
- }
-
- if (config.isRun6HAggregateDataMigration()) {
- retryOnFailure(new AggregateDataMigrator(MetricsTable.SIX_HOUR, config), Task.Estimate);
- }
-
- if (config.isRun1DAggregateDataMigration()) {
- retryOnFailure(new AggregateDataMigrator(MetricsTable.TWENTY_FOUR_HOUR, config), Task.Estimate);
- }
-
- if (config.isDeleteAllDataAtEndOfMigration()) {
- retryOnFailure(new DeleteAllData(config), Task.Estimate);
- }
-
- estimation = (long) (estimation + estimation * UNDER_ESTIMATION_FACTOR);
-
- return estimation;
- }
-
- public void migrateData() throws Exception {
- if (config.isRunRawDataMigration()) {
- retryOnFailure(new RawDataMigrator(config), Task.Migrate);
- }
-
- if (config.isRun1HAggregateDataMigration()) {
- retryOnFailure(new AggregateDataMigrator(MetricsTable.ONE_HOUR, config), Task.Migrate);
- }
-
- if (config.isRun6HAggregateDataMigration()) {
- retryOnFailure(new AggregateDataMigrator(MetricsTable.SIX_HOUR, config), Task.Migrate);
- }
-
- if (config.isRun1DAggregateDataMigration()) {
- retryOnFailure(new AggregateDataMigrator(MetricsTable.TWENTY_FOUR_HOUR, config), Task.Migrate);
- }
-
- if (config.isDeleteAllDataAtEndOfMigration()) {
- retryOnFailure(new DeleteAllData(config), Task.Migrate);
- }
- }
-
- public void deleteOldData() throws Exception {
- if (config.isDeleteAllDataAtEndOfMigration()) {
- retryOnFailure(new DeleteAllData(config), Task.Migrate);
- }
- }
-
- /**
- * Retries the migration {@link #MAX_NUMBER_OF_FAILURES} times before
- * failing the migration operation.
- *
- * @param migrator
- * @throws Exception
- */
- private Thread retryOnFailure(final CallableMigrationWorker migrator, final Task task)
- throws Exception {
-
- RunnableWithException runnable = new RunnableWithException() {
- private Exception exception;
-
- @Override
- public void run() {
- int numberOfFailures = 0;
- Exception caughtException = null;
-
- log.info(migrator.getClass());
-
- while (numberOfFailures < MAX_NUMBER_OF_FAILURES) {
- try {
- if (task == Task.Estimate) {
- estimation += migrator.estimate();
- } else {
- migrator.migrate();
- }
- return;
- } catch (Exception e) {
- log.error("Migrator " + migrator.getClass() + " failed. Retrying!", e);
-
- caughtException = e;
- numberOfFailures++;
- }
- }
-
- this.exception = caughtException;
- }
-
- @Override
- public Exception getException() {
- return this.exception;
- }
- };
-
- Thread localThread = new Thread(runnable);
- localThread.start();
- localThread.join();
-
- if (runnable.getException() != null) {
- throw runnable.getException();
- }
-
- return localThread;
- }
-
- public class DataMigratorConfiguration {
-
- private final EntityManager entityManager;
- private final Session session;
- private final DatabaseType databaseType;
- private final boolean experimentalDataSource;
-
- private boolean deleteDataImmediatelyAfterMigration;
- private boolean deleteAllDataAtEndOfMigration;
-
- private boolean runRawDataMigration;
- private boolean run1HAggregateDataMigration;
- private boolean run6HAggregateDataMigration;
- private boolean run1DAggregateDataMigration;
-
- public DataMigratorConfiguration(EntityManager entityManager, Session session, DatabaseType databaseType,
- boolean experimentalDataSource) {
- this.entityManager = entityManager;
- this.session = session;
- this.databaseType = databaseType;
- this.experimentalDataSource = experimentalDataSource;
- }
-
- public boolean isDeleteDataImmediatelyAfterMigration() {
- return deleteDataImmediatelyAfterMigration;
- }
-
- private void setDeleteDataImmediatelyAfterMigration(boolean deleteDataImmediatelyAfterMigration) {
- this.deleteDataImmediatelyAfterMigration = deleteDataImmediatelyAfterMigration;
- }
-
- public boolean isDeleteAllDataAtEndOfMigration() {
- return deleteAllDataAtEndOfMigration;
- }
-
- private void setDeleteAllDataAtEndOfMigration(boolean deleteAllDataAtEndOfMigration) {
- this.deleteAllDataAtEndOfMigration = deleteAllDataAtEndOfMigration;
- }
-
- public boolean isRunRawDataMigration() {
- return runRawDataMigration;
- }
-
- private void setRunRawDataMigration(boolean runRawDataMigration) {
- this.runRawDataMigration = runRawDataMigration;
- }
-
- public boolean isRun1HAggregateDataMigration() {
- return run1HAggregateDataMigration;
- }
-
- private void setRun1HAggregateDataMigration(boolean run1hAggregateDataMigration) {
- run1HAggregateDataMigration = run1hAggregateDataMigration;
- }
-
- public boolean isRun6HAggregateDataMigration() {
- return run6HAggregateDataMigration;
- }
-
- private void setRun6HAggregateDataMigration(boolean run6hAggregateDataMigration) {
- run6HAggregateDataMigration = run6hAggregateDataMigration;
- }
-
- public boolean isRun1DAggregateDataMigration() {
- return run1DAggregateDataMigration;
- }
-
- private void setRun1DAggregateDataMigration(boolean run1dAggregateDataMigration) {
- run1DAggregateDataMigration = run1dAggregateDataMigration;
- }
-
- public EntityManager getEntityManager() {
- return entityManager;
- }
-
- public Session getSession() {
- return session;
- }
-
- public DatabaseType getDatabaseType() {
- return databaseType;
- }
-
- public boolean isExperimentalDataSource() {
- return experimentalDataSource;
- }
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java
deleted file mode 100644
index 31d2a10..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2011, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
-
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-
-import com.datastax.driver.core.Cluster;
-import com.datastax.driver.core.ProtocolOptions.Compression;
-import com.datastax.driver.core.Session;
-import com.datastax.driver.core.exceptions.NoHostAvailableException;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.PosixParser;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.log4j.ConsoleAppender;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.apache.log4j.PatternLayout;
-import org.hibernate.ejb.Ejb3Configuration;
-
-import org.rhq.server.metrics.migrator.DataMigrator.DatabaseType;
-
-
-/**
- * @author Stefan Negrea
- *
- * Only postgres is supported by the runner, however the data migrator itself can run
- * with any database.
- *
- * Maven command to run this from the command line:
- *
- * mvn install -DskipTests exec:java -Dexec.mainClass="org.rhq.server.metrics.DataMigratorRunner"
- *
- *
- */
-@SuppressWarnings({ "static-access", "deprecation" })
-public class DataMigratorRunner {
-
- private static final int DEFAULT_CASSANDRA_PORT = 9142;
- private final Log log = LogFactory.getLog(DataMigratorRunner.class);
-
- //Cassandra
- private Option cassandraUserOption = OptionBuilder.withLongOpt("cassandra-user").hasArg().withType(String.class)
- .withDescription("Cassandra user (default: rhqadmin)").create();
- private Option cassandraPasswordOption = OptionBuilder.withLongOpt("cassandra-password").hasArg()
- .withDescription("Cassandra password (default: rhqadmin)").withType(String.class).create();
- private Option cassandraHostsOption = OptionBuilder.withLongOpt("cassandra-hosts").hasArg().withType(String.class)
- .withDescription("Cassandra hosts, format host_ip_1,host_ip_2,... (default: 127.0.0.1")
- .create();
- private Option cassandraPortOption = OptionBuilder.withLongOpt("cassandra-port").hasArg().withType(Integer.class)
- .withDescription("Cassandra native binary protocol port (default: 9142)").create();
- private Option cassandraCompressionOption = OptionBuilder.withLongOpt("cassandra-compression").hasOptionalArg()
- .withType(Boolean.class).withDescription("Enable compression for communication with Cassandra (default: true)")
- .create();
-
- //SQL
- private Option sqlUserOption = OptionBuilder.withLongOpt("sql-user").hasArg().withType(String.class)
- .withDescription("SQL server user (default: rhqadmin)").create();
- private Option sqlPasswordOption = OptionBuilder.withLongOpt("sql-password").hasArg().withType(String.class)
- .withDescription("SQL server password (default: rhqadmin)").create();
- private Option sqlHostOption = OptionBuilder.withLongOpt("sql-host").hasArg().withType(String.class)
- .withDescription("SQL server host address (default: localhost)").create();
- private Option sqlPortOption = OptionBuilder.withLongOpt("sql-port").hasArg().withType(String.class)
- .withDescription("SQL server port (default: 5432)").create();
- private Option sqlDBOption = OptionBuilder.withLongOpt("sql-db").hasArg().withType(String.class)
- .withDescription("SQL database (default: rhq)").create();
-
- private Option sqlServerType = OptionBuilder.withLongOpt("sql-server-type").hasArg().withType(String.class)
- .withDescription("SQL server type, only postgres and oracle are supported (default: postgres)").create();
- private Option sqlPostgresServer = OptionBuilder.withLongOpt("sql-server-postgres").hasOptionalArg()
- .withType(Boolean.class).withDescription("Postgres SQL server.").create();
- private Option sqlOracleServer = OptionBuilder.withLongOpt("sql-server-oracle").hasOptionalArg()
- .withType(Boolean.class)
- .withDescription("Oracle SQL server.").create();
-
- //Migration
- private Option disableRawOption = OptionBuilder.withLongOpt("disable-raw-migration").hasOptionalArg().withType(Boolean.class)
- .withDescription("Disable raw table migration (default: false)").create();
- private Option disable1HOption = OptionBuilder.withLongOpt("disable-1h-migration").hasOptionalArg().withType(Boolean.class)
- .withDescription("Disable 1 hour aggregates table migration (default: false)").create();
- private Option disable6HOption = OptionBuilder.withLongOpt("disable-6h-migration").hasOptionalArg().withType(Boolean.class)
- .withDescription("Disable 6 hours aggregates table migration (default: false)").create();
- private Option disable1DOption = OptionBuilder.withLongOpt("disable-1d-migration").hasOptionalArg().withType(Boolean.class)
- .withDescription("Disable 24 hours aggregates table migration (default: false)").create();
- private Option preserveDataOption = OptionBuilder.withLongOpt("preserve-data").hasOptionalArg().withType(Boolean.class)
- .withDescription("Preserve SQL data post migration (default: true)").create();
- private Option deleteDataOption = OptionBuilder.withLongOpt("delete-data").hasOptionalArg().withType(Boolean.class)
- .withDescription("Delete SQL data at the end of migration (default: false)").create();
- private Option estimateOnlyOption = OptionBuilder.withLongOpt("estimate-only").hasOptionalArg().withType(Boolean.class)
- .withDescription("Only estimate how long the migration will take (default: false)").create();
- private Option deleteOnlyOption = OptionBuilder.withLongOpt("delete-only").hasOptionalArg().withType(Boolean.class)
- .withDescription("Only delete data from the old SQL server, no migration will be performed (default: false)")
- .create();
- private Option experimentalExportOption = OptionBuilder.withLongOpt("experimental-export").hasOptionalArg().withType(Boolean.class)
- .withDescription("Enable experimental bulk export for Postgres, option ignored for Oracle migration (default: false)")
- .create();
-
- //Runner
- private Option helpOption = OptionBuilder.withLongOpt("help").create("h");
- private Option debugLogOption = OptionBuilder.withLongOpt("debugLog")
- .withDescription("Enable debug level logs for the communication with Cassandra and SQL Server (default: false)")
- .create("X");
- private Option configFileOption = OptionBuilder.withLongOpt("config-file").hasArg()
- .withDescription("Configuration file. All the command line options can be set in a typical properties file. " +
- "Command line arguments take precedence over default and configuration file options.")
- .create();
-
- private Map<Object, Object> configuration = new HashMap<Object, Object>();
- private Options options;
-
- /**
- * @param args
- * @throws ParseException
- */
- public static void main(String[] args) throws Exception {
- initLogging();
- try{
- DataMigratorRunner runner = new DataMigratorRunner();
- runner.configure(args);
- runner.run();
- } catch (HelpRequestedException h) {
- //do nothing
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(1);
- }
-
- System.exit(0);
- }
-
- private static void initLogging() {
- Logger root = Logger.getRootLogger();
- if (!root.getAllAppenders().hasMoreElements()) {
- root.addAppender(new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)));
- setLogLevel(Level.ERROR);
- }
- }
-
- private static void setLogLevel(Level level) {
- Logger root = Logger.getRootLogger();
- root.setLevel(level);
-
- Logger cassandraLogging = root.getLoggerRepository().getLogger("log4j.logger.org.apache.cassandra.cql.jdbc");
- cassandraLogging.setLevel(level);
-
- Logger cassandraDriverLogging = root.getLoggerRepository().getLogger("com.datastax.driver");
- cassandraDriverLogging.setLevel(level);
-
- Logger hibernateLogging = root.getLoggerRepository().getLogger("org.hibernate");
- hibernateLogging.setLevel(Level.ERROR);
-
- Logger migratorLogging = root.getLoggerRepository().getLogger("org.rhq");
- if (Level.DEBUG.equals(level)) {
- migratorLogging.setLevel(Level.ALL);
- } else {
- migratorLogging.setLevel(level);
- }
- }
-
- private void configure(String args[]) throws Exception {
- options = new Options();
-
- options.addOption(cassandraUserOption);
- options.addOption(cassandraPasswordOption);
- options.addOption(cassandraHostsOption);
- options.addOption(cassandraPortOption);
- options.addOption(cassandraCompressionOption);
-
- options.addOption(sqlUserOption);
- options.addOption(sqlPasswordOption);
- options.addOption(sqlHostOption);
- options.addOption(sqlPortOption);
- options.addOption(sqlDBOption);
- options.addOption(sqlServerType);
- options.addOption(sqlPostgresServer);
- options.addOption(sqlOracleServer);
-
- options.addOption(disableRawOption);
- options.addOption(disable1HOption);
- options.addOption(disable6HOption);
- options.addOption(disable1DOption);
- options.addOption(preserveDataOption);
- options.addOption(deleteDataOption);
- options.addOption(estimateOnlyOption);
- options.addOption(deleteOnlyOption);
- options.addOption(experimentalExportOption);
-
- options.addOption(helpOption);
- options.addOption(debugLogOption);
- options.addOption(configFileOption);
-
- CommandLine commandLine;
- try {
- CommandLineParser parser = new PosixParser();
- commandLine = parser.parse(options, args);
- } catch (Exception e) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.setWidth(120);
- formatter.printHelp("DataMigrationRunner", options);
- throw new Exception("Error parsing command line arguments");
- }
-
- if (commandLine.hasOption(helpOption.getLongOpt()) || commandLine.hasOption(helpOption.getOpt())) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("DataMigrationRunner", options);
- throw new HelpRequestedException();
- }
-
- if (commandLine.hasOption(debugLogOption.getLongOpt()) || commandLine.hasOption(debugLogOption.getOpt())) {
- DataMigratorRunner.setLogLevel(Level.DEBUG);
- }
-
- loadDefaultConfiguration();
- if (commandLine.hasOption(configFileOption.getLongOpt())) {
- loadConfigFile(commandLine.getOptionValue(configFileOption.getLongOpt()));
- }
-
- parseCassandraOptions(commandLine);
- parseSQLOptions(commandLine);
- parseMigrationOptions(commandLine);
- }
-
- /**
- * Add default configuration options to the configuration store.
- */
- private void loadDefaultConfiguration() {
- //default Cassandra configuration
- configuration.put(cassandraUserOption, "rhqadmin");
- configuration.put(cassandraPasswordOption, "rhqadmin");
- configuration.put(cassandraHostsOption, new String[] { "127.0.0.1" });
- configuration.put(cassandraPortOption, DEFAULT_CASSANDRA_PORT);
- configuration.put(cassandraCompressionOption, true);
-
- //default SQL configuration
- configuration.put(sqlUserOption, "rhqadmin");
- configuration.put(sqlPasswordOption, "rhqadmin");
- configuration.put(sqlHostOption, "localhost");
- configuration.put(sqlPortOption, "5432");
- configuration.put(sqlDBOption, "rhq");
- configuration.put(sqlServerType, "postgres");
-
- //default runner options
- configuration.put(disableRawOption, false);
- configuration.put(disable1HOption, false);
- configuration.put(disable6HOption, false);
- configuration.put(disable1DOption, false);
- configuration.put(preserveDataOption, true);
- configuration.put(estimateOnlyOption, false);
- configuration.put(deleteOnlyOption, false);
- configuration.put(experimentalExportOption, false);
- }
-
- /**
- * Load the configuration options from file and overlay them on top of the default
- * options.
- *
- * @param file config file
- */
- private void loadConfigFile(String file) {
- try {
- File configFile = new File(file);
- if (!configFile.exists()) {
- throw new FileNotFoundException("Configuration file not found!");
- }
-
- Properties configProperties = new Properties();
- FileInputStream stream = new FileInputStream(configFile);
- configProperties.load(stream);
- stream.close();
-
- for (Object optionObject : options.getOptions()) {
- Option option = (Option) optionObject;
- Object optionValue;
-
- if ((optionValue = configProperties.get(option.getLongOpt())) != null) {
- log.debug("Configuration option loaded: " + option.getLongOpt() + " (" + option.getType() + ") -> "
- + optionValue);
-
- if (option.equals(cassandraHostsOption)) {
- String[] cassandraHosts = parseCassandraHosts(optionValue.toString());
- configuration.put(option, cassandraHosts);
- } else if (option.equals(sqlServerType)) {
- if ("oracle".equals(optionValue)) {
- configuration.put(option, "oracle");
- } else {
- configuration.put(option, "postgres");
- }
- } else if (option.equals(sqlPostgresServer)) {
- boolean value = tryParseBoolean(optionValue.toString(), true);
- if (value == true) {
- configuration.put(sqlServerType, "postgres");
- }
- } else if (option.equals(sqlOracleServer)) {
- boolean value = tryParseBoolean(optionValue.toString(), true);
- if (value == true) {
- configuration.put(sqlServerType, "oracle");
- }
- } else if (option.getType().equals(Boolean.class)) {
- configuration.put(option, tryParseBoolean(optionValue.toString(), true));
- } else if (option.getType().equals(Integer.class)) {
- configuration.put(option, tryParseInteger(optionValue.toString(), 0));
- } else {
- configuration.put(option, optionValue.toString());
- }
- }
- }
- } catch (Exception e) {
- log.error("Unable to load or process the configuration file.", e);
- System.exit(1);
- }
-
- log.debug(configuration.toString());
- }
-
- /**
- * Parse command line options for Cassandra.
- *
- * @param commandLine command line
- * @throws NoHostAvailableException
- */
- private void parseCassandraOptions(CommandLine commandLine) throws Exception {
- if (commandLine.hasOption(cassandraUserOption.getLongOpt())) {
- configuration.put(cassandraUserOption, commandLine.getOptionValue(cassandraUserOption.getLongOpt()));
- }
-
- if (commandLine.hasOption(cassandraPasswordOption.getLongOpt())) {
- configuration
- .put(cassandraPasswordOption, commandLine.getOptionValue(cassandraPasswordOption.getLongOpt()));
- }
-
- if (commandLine.hasOption(cassandraHostsOption.getLongOpt())) {
- String[] cassandraHosts = parseCassandraHosts(commandLine.getOptionValue(cassandraHostsOption.getLongOpt()));
- configuration.put(cassandraHostsOption, cassandraHosts);
- }
-
- if (commandLine.hasOption(cassandraPortOption.getLongOpt())) {
- Integer cassandraPort = tryParseInteger(commandLine.getOptionValue(cassandraPortOption.getLongOpt()),
- DEFAULT_CASSANDRA_PORT);
- configuration.put(cassandraPortOption, cassandraPort);
- }
-
- if (commandLine.hasOption(cassandraCompressionOption.getLongOpt())) {
- boolean value = tryParseBoolean(commandLine.getOptionValue(cassandraCompressionOption.getLongOpt()), true);
- configuration.put(cassandraCompressionOption, value);
- }
- }
-
- /**
- * Parse command line options for SQL.
- *
- * @param commandLine command line
- * @throws NoHostAvailableException
- */
- private void parseSQLOptions(CommandLine commandLine) throws NoHostAvailableException {
- if (commandLine.hasOption(sqlUserOption.getLongOpt())) {
- configuration.put(sqlUserOption, commandLine.getOptionValue(sqlUserOption.getLongOpt()));
- }
-
- if (commandLine.hasOption(sqlPasswordOption.getLongOpt())) {
- configuration.put(sqlPasswordOption, commandLine.getOptionValue(sqlPasswordOption.getLongOpt()));
- }
-
- if (commandLine.hasOption(sqlHostOption.getLongOpt())) {
- configuration.put(sqlHostOption, commandLine.getOptionValue(sqlHostOption.getLongOpt()));
- }
-
- if (commandLine.hasOption(sqlPortOption.getLongOpt())) {
- configuration.put(sqlPortOption, commandLine.getOptionValue(sqlPortOption.getLongOpt()));
- }
-
- if (commandLine.hasOption(sqlDBOption.getLongOpt())) {
- configuration.put(sqlDBOption, commandLine.getOptionValue(sqlDBOption.getLongOpt()));
- }
-
- if (commandLine.hasOption(sqlServerType.getLongOpt())) {
- if ("oracle".equals(commandLine.getOptionValue(sqlServerType.getLongOpt()))) {
- configuration.put(sqlServerType, "oracle");
- } else {
- configuration.put(sqlServerType, "postgres");
- }
- } else if (commandLine.hasOption(sqlPostgresServer.getLongOpt())) {
- configuration.put(sqlServerType, "postgres");
- } else if (commandLine.hasOption(sqlOracleServer.getLongOpt())) {
- configuration.put(sqlServerType, "oracle");
- }
- }
-
- /**
- * Parse command line options for the actual migration progress.
- *
- * @param commandLine
- */
- private void parseMigrationOptions(CommandLine commandLine) {
- boolean value;
-
- if (commandLine.hasOption(disableRawOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(disableRawOption.getLongOpt()), true);
- configuration.put(disableRawOption, value);
- }
-
- if (commandLine.hasOption(disable1HOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(disable1HOption.getLongOpt()), true);
- configuration.put(disable1HOption, value);
- }
-
- if (commandLine.hasOption(disable6HOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(disable6HOption.getLongOpt()), true);
- configuration.put(disable6HOption, value);
- }
-
- if (commandLine.hasOption(disable1DOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(disable1DOption.getLongOpt()), true);
- configuration.put(disable1DOption, value);
- }
-
- if (commandLine.hasOption(preserveDataOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(preserveDataOption.getLongOpt()), true);
- configuration.put(preserveDataOption, value);
- } else if (commandLine.hasOption(deleteDataOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(deleteDataOption.getLongOpt()), true);
- configuration.put(preserveDataOption, value);
- }
-
- if (commandLine.hasOption(estimateOnlyOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(estimateOnlyOption.getLongOpt()), true);
- configuration.put(estimateOnlyOption, value);
- }
-
- if (commandLine.hasOption(experimentalExportOption.getLongOpt())) {
- value = tryParseBoolean(commandLine.getOptionValue(experimentalExportOption.getLongOpt()), true);
- configuration.put(experimentalExportOption, value);
- }
- }
-
- private void run() throws Exception {
- log.debug("Creating Entity Manager");
- EntityManager entityManager = this.createEntityManager();
- log.debug("Done creating Entity Manager");
-
- log.debug("Creating Cassandra session");
- Session session = this.createCassandraSession();
- log.debug("Done creating Cassandra session");
-
- DatabaseType databaseType = DatabaseType.Postgres;
- if ("oracle".equals(configuration.get(sqlServerType))) {
- databaseType = databaseType.Oracle;
- }
- DataMigrator migrator = new DataMigrator(entityManager, session, databaseType, tryParseBoolean(
- configuration.get(experimentalExportOption), false));
-
- if (!(Boolean) configuration.get(deleteOnlyOption)) {
- if ((Boolean) configuration.get(preserveDataOption)) {
- migrator.preserveData();
- } else {
- migrator.deleteAllDataAtEndOfMigration();
- }
-
- migrator.runRawDataMigration(!(Boolean) configuration.get(disableRawOption));
- migrator.run1HAggregateDataMigration(!(Boolean) configuration.get(disable1HOption));
- migrator.run6HAggregateDataMigration(!(Boolean) configuration.get(disable6HOption));
- migrator.run1DAggregateDataMigration(!(Boolean) configuration.get(disable1DOption));
-
- System.out.println("Estimation process - starting\n");
- long estimate = migrator.estimate();
- System.out.println("The migration process will take approximately: "
- + TimeUnit.MILLISECONDS.toMinutes(estimate) + " minutes (or " + estimate + " milliseconds)\n");
- System.out.println("Estimation process - ended\n\n");
-
- if (!(Boolean) configuration.get(estimateOnlyOption)) {
- System.out.println("Migration process - starting\n");
- long startTime = System.currentTimeMillis();
- migrator.migrateData();
- long duration = System.currentTimeMillis() - startTime;
- System.out.println("The migration process took: " + TimeUnit.MILLISECONDS.toMinutes(duration)
- + " minutes (or " + duration + " milliseconds)\n");
- System.out.println("Migration process - ended\n");
- }
- } else {
- migrator.deleteAllDataAtEndOfMigration();
- migrator.runRawDataMigration(true);
- migrator.run1HAggregateDataMigration(true);
- migrator.run6HAggregateDataMigration(true);
- migrator.run1DAggregateDataMigration(true);
-
- System.out.println("Estimation process - starting\n");
- long estimate = migrator.estimate();
- System.out.println("The deletion of old data will take approximately: "
- + TimeUnit.MILLISECONDS.toMinutes(estimate) + " minutes (or " + estimate + " milliseconds)\n");
- System.out.println("Estimation process - ended\n\n");
-
- if (!(Boolean) configuration.get(estimateOnlyOption)) {
- System.out.println("Old data deletion process - starting\n");
- long startTime = System.currentTimeMillis();
- migrator.deleteOldData();
- long duration = System.currentTimeMillis() - startTime;
- System.out.println("The deletion process took: " + TimeUnit.MILLISECONDS.toMinutes(duration)
- + " minutes (or " + duration + " milliseconds)\n");
- System.out.println("Old data deletion process - ended\n");
- }
- }
-
- /*if (entityManager != null) {
- entityManager.close();
- }
- if (entityManagerFactory != null) {
- entityManagerFactory.close();
- }*/
- }
-
- /**
- * Create a Cassandra session based on configuration options.
- *
- * @return Cassandra session
- * @throws Exception
- */
- private Session createCassandraSession() throws Exception {
- Compression selectedCompression = Compression.NONE;
- if ((Boolean) configuration.get(cassandraCompressionOption)) {
- selectedCompression = Compression.SNAPPY;
- }
-
- Cluster cluster = Cluster
- .builder()
- .addContactPoints((String[]) configuration.get(cassandraHostsOption))
- .withPort((Integer) configuration.get(cassandraPortOption))
- .withCompression(selectedCompression)
- .withoutMetrics()
- .withCredentials((String) configuration.get(cassandraUserOption),
- (String) configuration.get(cassandraPasswordOption))
- .build();
-
- return cluster.connect("rhq");
- }
-
- /**
- * Create a hibernate session to the SQL server.
- *
- * @return
- * @throws Exception
- */
- private EntityManager createEntityManager() throws Exception {
- Properties properties = new Properties();
- properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
- properties.put("hibernate.connection.username", (String) configuration.get(sqlUserOption));
- properties.put("hibernate.connection.password", (String) configuration.get(sqlPasswordOption));
- properties.put("javax.persistence.query.timeout", DataMigrator.SQL_TIMEOUT);
- properties.put("hibernate.c3p0.timeout", DataMigrator.SQL_TIMEOUT);
-
- if ("oracle".equals(configuration.get(sqlServerType))) {
- String driverClassName = "oracle.jdbc.driver.OracleDriver";
-
- try {
- //Required to preload the driver manually.
- //Without this the driver load will fail due to the packaging.
- Class.forName(driverClassName);
- } catch (ClassNotFoundException e) {
- log.debug(e);
- throw new Exception("Oracle SQL Driver class could not be loaded. Missing class: " + driverClassName);
- }
-
- properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
- properties.put("hibernate.driver_class", driverClassName);
- properties.put("hibernate.connection.url", "jdbc:oracle:thin:@" + (String) configuration.get(sqlHostOption)
- + ":" + (String) configuration.get(sqlPortOption) + ":" + (String) configuration.get(sqlDBOption));
- properties.put("hibernate.default_schema", (String) configuration.get(sqlDBOption));
- properties.put("hibernate.connection.oracle.jdbc.ReadTimeout", DataMigrator.SQL_TIMEOUT);
- } else {
- String driverClassName = "org.postgresql.Driver";
-
- try {
- //Required to preload the driver manually.
- //Without this the driver load will fail due to the packaging.
- Class.forName(driverClassName);
- } catch (ClassNotFoundException e) {
- log.debug(e);
- throw new Exception("Postgres SQL Driver class could not be loaded. Missing class: " + driverClassName);
- }
-
- properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
- properties.put("hibernate.driver_class", driverClassName);
- properties.put("hibernate.connection.url", "jdbc:postgresql://" + (String) configuration.get(sqlHostOption)
- + ":" + (String) configuration.get(sqlPortOption) + "/" + (String) configuration.get(sqlDBOption));
- }
-
- log.debug("Creating entity manager with the following configuration:");
- log.debug(properties);
-
- Ejb3Configuration configuration = new Ejb3Configuration();
- configuration.setProperties(properties);
- EntityManagerFactory factory = configuration.buildEntityManagerFactory();
- return factory.createEntityManager();
- }
-
- /**
- * Parse Cassandra host information submitted in the form:
- * host_addres,jmx_port,native_port|host_address_2,jmx_port,native_port
- *
- * @param stringValue
- * @return
- */
- private String[] parseCassandraHosts(String stringValue) {
- String[] seeds = stringValue.split(",");
- return seeds;
- }
-
- /**
- * @param value object value to parse
- * @param defaultValue default value
- * @return
- */
- private boolean tryParseBoolean(Object value, boolean defaultValue) {
- try {
- return Boolean.parseBoolean(value.toString());
- } catch (Exception e) {
- return defaultValue;
- }
- }
-
- /**
- * @param value object value to parse
- * @param defaultValue default value
- * @return
- */
- private Integer tryParseInteger(Object value, int defaultValue) {
- try {
- return Integer.parseInt(value.toString());
- } catch (Exception e) {
- return defaultValue;
- }
- }
-
- @SuppressWarnings("serial")
- private class HelpRequestedException extends Exception {
- public HelpRequestedException() {
- super("Help Requested");
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java
deleted file mode 100644
index 756d1b1..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.rhq.server.metrics.migrator;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.util.StringTokenizer;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.rhq.core.util.stream.StreamUtil;
-
-/**
- * @author Thomas Segismont
- */
-public abstract class ExistingDataBulkExportSource implements ExistingDataSource {
-
- private static final Log log = LogFactory.getLog(ExistingDataBulkExportSource.class);
-
- protected static final int IO_BUFFER_SIZE = 1024 * 64;
-
- protected static final String DELIMITER = "|";
-
- private File existingDataFile;
-
- private BufferedReader existingDataFileReader;
-
- private int currentIndex;
-
- public ExistingDataBulkExportSource() {
- Random random = new Random();
- String exportFileName = System.currentTimeMillis() + "." + random.nextInt() + ".export";
- this.existingDataFile = new File(System.getProperty("java.io.tmpdir"), exportFileName);
- }
-
- @Override
- public void initialize() throws Exception {
- this.exportExistingData();
- this.startReading();
- }
-
- @Override
- public void close() throws Exception {
- this.stopReading();
- this.removeTempFile();
- }
-
- protected abstract void exportExistingData() throws Exception;
-
- protected File getExistingDataFile() {
- return existingDataFile;
- }
-
- protected void startReading() throws Exception {
- if (!existingDataFile.exists() && !existingDataFile.isFile() && !existingDataFile.canRead()) {
- throw new IllegalStateException();
- }
- existingDataFileReader = new BufferedReader(new FileReader(existingDataFile));
- currentIndex = 0;
- }
-
- protected void stopReading() {
- StreamUtil.safeClose(existingDataFileReader);
- }
-
- protected void removeTempFile(){
- if(this.existingDataFile.exists()){
- try{
- this.existingDataFile.delete();
- }catch(Exception e){
- log.debug("Unable to clean temporary file " + this.existingDataFile, e);
- }
- }
- }
-
- @Override
- public List<Object[]> getData(int fromIndex, int maxResults) throws Exception {
- if (log.isDebugEnabled()) {
- log.debug("Reading lines " + fromIndex + " to " + (fromIndex + maxResults));
- }
-
- if (fromIndex != currentIndex) {
- throw new IllegalStateException();
- }
-
- List<Object[]> results = new LinkedList<Object[]>();
- for (int i = 0; i < maxResults; i++) {
- String nextLine = existingDataFileReader.readLine();
- if (nextLine == null) {
- break;
- }
- currentIndex++;
- StringTokenizer stringTokenizer = new StringTokenizer(nextLine, DELIMITER);
- Object[] row = new Object[stringTokenizer.countTokens()];
- for (int j = 0; j < row.length; j++) {
- row[j] = stringTokenizer.nextToken();
- }
- results.add(row);
- }
- return results;
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java
deleted file mode 100644
index fde9096..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.rhq.server.metrics.migrator;
-
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-
-import javax.persistence.EntityManager;
-
-import org.hibernate.Session;
-import org.hibernate.engine.spi.SessionFactoryImplementor;
-import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
-
-import org.rhq.core.util.jdbc.JDBCUtil;
-import org.rhq.core.util.stream.StreamUtil;
-
-/**
- * @author Thomas Segismont
- */
-public class ExistingDataJPABulkExportSource extends ExistingDataBulkExportSource {
-
- private EntityManager entityManager;
- private String selectNativeQuery;
-
- public ExistingDataJPABulkExportSource(EntityManager entityManager, String selectNativeQuery) {
- super();
- }
-
- protected void exportExistingData() throws Exception {
- BufferedWriter fileWriter = null;
- Connection connection = null;
- PreparedStatement statement = null;
- ResultSet resultSet = null;
- try {
- fileWriter = new BufferedWriter(new FileWriter(getExistingDataFile()), IO_BUFFER_SIZE);
- Session session = (Session) this.entityManager.getDelegate();
- SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
- ConnectionProvider cp = sfi.getConnectionProvider();
- connection = cp.getConnection();
- statement = connection.prepareStatement(this.selectNativeQuery);
- resultSet = statement.executeQuery();
- int columnCount = resultSet.getMetaData().getColumnCount();
- while (resultSet.next()) {
- for (int i = 1; i < columnCount + 1; i++) {
- if (i > 1) {
- fileWriter.write(DELIMITER);
- }
- fileWriter.write(resultSet.getString(i));
- }
- fileWriter.write("\n");
- }
- } finally {
- StreamUtil.safeClose(fileWriter);
- JDBCUtil.safeClose(connection, statement, resultSet);
- }
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java
deleted file mode 100644
index 9aca36a..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.rhq.server.metrics.migrator;
-
-import java.util.List;
-
-import javax.persistence.EntityManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * @author Thomas Segismont
- */
-public class ExistingDataJPASource implements ExistingDataSource {
-
- private static final Log log = LogFactory.getLog(ExistingDataJPASource.class);
-
- private EntityManager entityManager;
- private String selectNativeQuery;
-
- public ExistingDataJPASource(EntityManager entityManager, String selectNativeQuery) {
- this.entityManager = entityManager;
- this.selectNativeQuery = selectNativeQuery;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public List<Object[]> getData(int fromIndex, int maxResults) throws Exception {
- if (log.isDebugEnabled()) {
- log.debug("Reading lines " + fromIndex + " to " + (fromIndex + maxResults));
- }
-
- return (List<Object[]>) entityManager.createNativeQuery(selectNativeQuery).setFirstResult(fromIndex)
- .setMaxResults(maxResults).getResultList();
- }
-
- @Override
- public void initialize() {
- //nothing to do since it just implements a simple query with limits
- }
-
- @Override
- public void close() {
- //nothing to do since it just implements a simple query with limits
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java
deleted file mode 100644
index 033c5d9..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.rhq.server.metrics.migrator;
-
-import java.util.List;
-
-/**
- * @author Thomas Segismont
- */
-public interface ExistingDataSource {
-
- static final int TIMEOUT = 6000000;
-
- List<Object[]> getData(int fromIndex, int maxResults) throws Exception;
-
- void initialize() throws Exception;
-
- void close() throws Exception;
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java
deleted file mode 100644
index 2ba7e4a..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.rhq.server.metrics.migrator;
-
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.sql.Connection;
-
-import javax.persistence.EntityManager;
-
-import org.hibernate.Session;
-import org.hibernate.engine.spi.SessionFactoryImplementor;
-import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
-import org.postgresql.copy.CopyManager;
-import org.postgresql.core.BaseConnection;
-
-import org.rhq.core.util.jdbc.JDBCUtil;
-import org.rhq.core.util.stream.StreamUtil;
-
-/**
- * @author Thomas Segismont
- */
-public class ExistingPostgresDataBulkExportSource extends ExistingDataBulkExportSource {
-
- private final EntityManager entityManager;
- private final String selectNativeQuery;
- private final int maxResults;
-
- public ExistingPostgresDataBulkExportSource(EntityManager entityManager, String selectNativeQuery) {
- this(entityManager, selectNativeQuery, -1);
- }
-
- public ExistingPostgresDataBulkExportSource(EntityManager entityManager, String selectNativeQuery, int maxResults) {
- super();
- this.entityManager = entityManager;
- this.selectNativeQuery = selectNativeQuery;
- this.maxResults = maxResults;
- }
-
- protected void exportExistingData() throws Exception {
- BufferedWriter fileWriter = null;
- Connection connection = null;
- try {
- fileWriter = new BufferedWriter(new FileWriter(getExistingDataFile()), IO_BUFFER_SIZE);
- Session session = (Session) entityManager.getDelegate();
- SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
- ConnectionProvider cp = sfi.getConnectionProvider();
- connection = cp.getConnection();
- CopyManager copyManager = new CopyManager((BaseConnection) connection);
-
- if (maxResults > 0) {
- copyManager.copyOut("COPY (" + selectNativeQuery + " LIMIT " + maxResults
- + ") TO STDOUT WITH DELIMITER '" + DELIMITER + "'", fileWriter);
- } else {
- copyManager.copyOut("COPY (" + selectNativeQuery + ") TO STDOUT WITH DELIMITER '" + DELIMITER + "'",
- fileWriter);
- }
- } finally {
- StreamUtil.safeClose(fileWriter);
- JDBCUtil.safeClose(connection);
- }
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java
deleted file mode 100644
index 42161a4..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.rhq.server.metrics.migrator;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.persistence.EntityManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.Query;
-import org.hibernate.ScrollMode;
-import org.hibernate.ScrollableResults;
-import org.hibernate.Session;
-import org.hibernate.StatelessSession;
-
-import org.rhq.server.metrics.migrator.DataMigrator.DatabaseType;
-
-/**
- * @author Stefan Negrea
- */
-public class ScrollableDataSource implements ExistingDataSource {
-
- private static final Log log = LogFactory.getLog(ScrollableDataSource.class);
-
- private final EntityManager entityManager;
- private final DatabaseType databaseType;
- private final String selectNativeQuery;
- private final int maxResults;
-
- private ScrollableResults results;
- private StatelessSession session;
- private int lastMigratedItemIndex;
-
-
- public ScrollableDataSource(EntityManager entityManager, DatabaseType databaseType,
- String selectNativeQuery) {
- this(entityManager, databaseType, selectNativeQuery, -1);
- }
-
- public ScrollableDataSource(EntityManager entityManager, DatabaseType databaseType, String selectNativeQuery,
- int maxResults) {
- this.entityManager = entityManager;
- this.databaseType = databaseType;
- this.selectNativeQuery = selectNativeQuery;
- this.maxResults = maxResults;
- }
-
- @Override
- public List<Object[]> getData(int fromIndex, int maxResults) throws Exception {
- if (fromIndex != lastMigratedItemIndex + 1) {
- throw new Exception("Cursor error. " + fromIndex + " " + lastMigratedItemIndex);
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Reading lines " + fromIndex + " to " + (fromIndex + maxResults));
- }
-
- List<Object[]> resultList = new ArrayList<Object[]>();
-
- int maxLimit = lastMigratedItemIndex + maxResults;
-
- while (results.next()) {
- resultList.add(results.get());
-
- if (++lastMigratedItemIndex == maxLimit) {
- break;
- }
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Read lines " + fromIndex + " to " + (fromIndex + maxResults));
- }
-
- return resultList;
- }
-
- @Override
- public void initialize() {
- if (session != null || results != null) {
- close();
- }
-
- session = ((Session) entityManager.getDelegate()).getSessionFactory().openStatelessSession();
-
- this.prepareSQLSession();
-
- if (log.isDebugEnabled()) {
- if (maxResults >= 0) {
- log.debug("Preparing the query with " + maxResults + " results.");
- } else {
- log.debug("Preparing the query with all the results.");
- }
- }
-
- Query query = session.createSQLQuery(selectNativeQuery);
- if (maxResults >= 0) {
- query.setMaxResults(maxResults);
- }
- query.setFetchSize(30000);
- query.setReadOnly(true);
- query.setTimeout(TIMEOUT);
- results = query.scroll(ScrollMode.FORWARD_ONLY);
-
- lastMigratedItemIndex = -1;
-
- if (log.isDebugEnabled()) {
- if (maxResults >= 0) {
- log.debug("Query prepared with " + maxResults + " results.");
- } else {
- log.debug("Query prepared with all the results.");
- }
- }
- }
-
- @Override
- public void close() {
- if (results != null) {
- results.close();
- results = null;
- }
-
- if (session != null) {
- session.close();
- session = null;
- }
- }
-
- private void prepareSQLSession() {
- if (DatabaseType.Postgres.equals(this.databaseType)) {
- log.debug("Preparing SQL connection with timeout: " + DataMigrator.SQL_TIMEOUT);
-
- Query query = session.createSQLQuery("SET LOCAL statement_timeout = " + DataMigrator.SQL_TIMEOUT);
- query.setReadOnly(true);
- query.executeUpdate();
- }
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java
deleted file mode 100644
index 92bf37a..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator;
-
-import org.apache.commons.lang.time.StopWatch;
-
-/**
- * @author Stefan Negrea
- *
- */
-public class Telemetry {
- private StopWatch generalTimer;
- private StopWatch migrationTimer;
-
- public Telemetry() {
- this.generalTimer = new StopWatch();
- this.migrationTimer = new StopWatch();
- }
-
- public StopWatch getGeneralTimer() {
- return generalTimer;
- }
-
- public StopWatch getMigrationTimer() {
- return migrationTimer;
- }
-
- public long getMigrationTime() {
- return migrationTimer.getTime();
- }
-
- public long getGeneralTime() {
- return generalTimer.getTime();
- }
-
- public long getNonMigrationTime() {
- return this.getGeneralTime() - this.getMigrationTime();
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java
deleted file mode 100644
index 3c006be..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator.workers;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.StatelessSession;
-
-import org.rhq.server.metrics.migrator.DataMigrator;
-import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
-import org.rhq.server.metrics.migrator.DataMigrator.DatabaseType;
-import org.rhq.server.metrics.migrator.DataMigrator.Task;
-import org.rhq.server.metrics.migrator.ExistingDataSource;
-import org.rhq.server.metrics.migrator.ExistingPostgresDataBulkExportSource;
-import org.rhq.server.metrics.migrator.ScrollableDataSource;
-
-/**
- * @author Stefan Negrea
- *
- */
-public abstract class AbstractMigrationWorker {
- private final Log log = LogFactory.getLog(AbstractMigrationWorker.class);
-
- /**
- * Returns a list of all the raw SQL metric tables.
- * There is no equivalent in Cassandra, all raw data is stored in a single column family.
- *
- * @return SQL raw metric tables
- */
- protected static String[] getRawDataTables() {
- int tableCount = 15;
- String tablePrefix = "RHQ_MEAS_DATA_NUM_R";
-
- String[] tables = new String[tableCount];
- for (int i = 0; i < tableCount; i++) {
- if (i < 10) {
- tables[i] = tablePrefix + "0" + i;
- } else {
- tables[i] = tablePrefix + i;
- }
- }
-
- return tables;
- }
-
- protected ExistingDataSource getExistingDataSource(String query, Task task, DataMigratorConfiguration config) {
- if (Task.Migrate.equals(task)) {
- if (DatabaseType.Oracle.equals(config.getDatabaseType())) {
- return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query);
- } else {
- if (!config.isExperimentalDataSource()) {
- return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query);
- } else {
- return new ExistingPostgresDataBulkExportSource(config.getEntityManager(), query);
- }
- }
- } else if (Task.Estimate.equals(task)) {
- int limit = CallableMigrationWorker.MAX_RECORDS_TO_LOAD_FROM_SQL
- * (CallableMigrationWorker.NUMBER_OF_BATCHES_FOR_ESTIMATION + 1);
-
- if (DatabaseType.Oracle.equals(config.getDatabaseType())) {
- return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query, limit);
- } else {
- if (!config.isExperimentalDataSource()) {
- return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query, limit);
- } else {
- return new ExistingPostgresDataBulkExportSource(config.getEntityManager(), query, limit);
- }
- }
- }
-
- return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query);
- }
-
- protected void prepareSQLSession(StatelessSession session, DataMigratorConfiguration config) {
- if (DatabaseType.Postgres.equals(config.getDatabaseType())) {
- log.debug("Preparing SQL connection with timeout: " + DataMigrator.SQL_TIMEOUT);
-
- org.hibernate.Query query = session.createSQLQuery("SET LOCAL statement_timeout = "
- + DataMigrator.SQL_TIMEOUT);
- query.setReadOnly(true);
- query.executeUpdate();
- }
- }
-
- protected StatelessSession getSQLSession(DataMigratorConfiguration config) {
- StatelessSession session = ((org.hibernate.Session) config.getEntityManager().getDelegate())
- .getSessionFactory().openStatelessSession();
-
- prepareSQLSession(session, config);
-
- return session;
- }
-
- protected void closeSQLSession(StatelessSession session) {
- try {
- if (session != null) {
- session.close();
- }
- } catch (Exception e) {
- //log.debug("Unable to close SQL stateless session. " + e);
- }
- }
-
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java
deleted file mode 100644
index 5511321..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator.workers;
-
-import static com.datastax.driver.core.querybuilder.QueryBuilder.ttl;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import com.datastax.driver.core.ResultSetFuture;
-import com.datastax.driver.core.querybuilder.Batch;
-import com.datastax.driver.core.querybuilder.QueryBuilder;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.StatelessSession;
-
-import org.rhq.server.metrics.domain.AggregateType;
-import org.rhq.server.metrics.domain.MetricsTable;
-import org.rhq.server.metrics.migrator.DataMigrator;
-import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
-import org.rhq.server.metrics.migrator.DataMigrator.Task;
-import org.rhq.server.metrics.migrator.ExistingDataSource;
-import org.rhq.server.metrics.migrator.Telemetry;
-
-/**
- * @author Stefan Negrea
- *
- */
-public class AggregateDataMigrator extends AbstractMigrationWorker implements CallableMigrationWorker {
-
- private final Log log = LogFactory.getLog(AggregateDataMigrator.class);
-
- private final DataMigratorConfiguration config;
- private final String selectQuery;
- private final String deleteQuery;
- private final String countQuery;
- private final MetricsTable metricsTable;
- private final MetricsIndexUpdateAccumulator metricsIndexAccumulator;
-
- /**
- * @param query
- * @param metricsTable
- */
- public AggregateDataMigrator(MetricsTable metricsTable, DataMigratorConfiguration config)
- throws Exception {
-
- this.metricsTable = metricsTable;
- this.config = config;
-
- if (MetricsTable.ONE_HOUR.equals(this.metricsTable)) {
- this.selectQuery = MigrationQuery.SELECT_1H_DATA.toString();
- this.deleteQuery = MigrationQuery.DELETE_1H_DATA.toString();
- this.countQuery = MigrationQuery.COUNT_1H_DATA.toString();
- } else if (MetricsTable.SIX_HOUR.equals(this.metricsTable)) {
- this.selectQuery = MigrationQuery.SELECT_6H_DATA.toString();
- this.deleteQuery = MigrationQuery.DELETE_6H_DATA.toString();
- this.countQuery = MigrationQuery.COUNT_6H_DATA.toString();
- } else if (MetricsTable.TWENTY_FOUR_HOUR.equals(this.metricsTable)) {
- this.selectQuery = MigrationQuery.SELECT_1D_DATA.toString();
- this.deleteQuery = MigrationQuery.DELETE_1D_DATA.toString();
- this.countQuery = MigrationQuery.COUNT_1D_DATA.toString();
- } else {
- throw new Exception("MetricsTable " + metricsTable.toString() + " not supported by this migrator.");
- }
-
- metricsIndexAccumulator = new MetricsIndexUpdateAccumulator(metricsTable, config);
- }
-
- @Override
- public long estimate() throws Exception {
- long recordCount = this.getRowCount(this.countQuery);
- log.debug("Retrieved record count for table " + metricsTable.toString() + " -- " + recordCount);
-
- Telemetry telemetry = this.performMigration(Task.Estimate);
- long estimatedTimeToMigrate = telemetry.getMigrationTime();
-
- long estimation = (recordCount / (long) MAX_RECORDS_TO_LOAD_FROM_SQL / (long) NUMBER_OF_BATCHES_FOR_ESTIMATION)
- * estimatedTimeToMigrate;
-
- estimation += telemetry.getNonMigrationTime();
-
- return estimation;
- }
-
- public void migrate() throws Exception {
- performMigration(Task.Migrate);
- if (config.isDeleteDataImmediatelyAfterMigration()) {
- deleteTableData();
- }
- }
-
- private long getRowCount(String countQuery) {
- StatelessSession session = getSQLSession(config);
-
- org.hibernate.Query query = session.createSQLQuery(countQuery);
- query.setReadOnly(true);
- query.setTimeout(DataMigrator.SQL_TIMEOUT);
- long count = Long.parseLong(query.uniqueResult().toString());
-
- closeSQLSession(session);
-
- return count;
- }
-
- private void deleteTableData() throws Exception {
- int failureCount = 0;
- while (failureCount < MAX_NUMBER_OF_FAILURES) {
- try {
- StatelessSession session = getSQLSession(config);
- session.getTransaction().begin();
- org.hibernate.Query nativeQuery = session.createSQLQuery(this.deleteQuery);
- nativeQuery.executeUpdate();
- session.getTransaction().commit();
- closeSQLSession(session);
- log.info("- " + metricsTable.toString() + " - Cleaned -");
- } catch (Exception e) {
- log.error("Failed to delete " + metricsTable.toString()
- + " data. Attempting to delete data one more time...");
-
- failureCount++;
- if (failureCount == MAX_NUMBER_OF_FAILURES) {
- throw e;
- }
- }
- }
- }
-
- private Telemetry performMigration(Task task) throws Exception {
- Telemetry telemetry = new Telemetry();
- telemetry.getGeneralTimer().start();
-
- long numberOfBatchesMigrated = 0;
-
- List<Object[]> existingData;
- int failureCount;
-
- int lastMigratedRecord = 0;
- ExistingDataSource dataSource = getExistingDataSource(selectQuery, task, config);
- dataSource.initialize();
-
- telemetry.getMigrationTimer().start();
- while (true) {
- existingData = dataSource.getData(lastMigratedRecord, MAX_RECORDS_TO_LOAD_FROM_SQL);
-
- if (existingData.size() == 0) {
- break;
- }
-
- lastMigratedRecord += existingData.size();
-
- failureCount = 0;
- while (failureCount < MAX_NUMBER_OF_FAILURES) {
- try {
- insertDataToCassandra(existingData);
- break;
- } catch (Exception e) {
- log.error("Failed to insert " + metricsTable.toString()
- + " data. Attempting to insert the current batch of data one more time");
- log.error(e);
-
- failureCount++;
- if (failureCount == MAX_NUMBER_OF_FAILURES) {
- throw e;
- }
- }
- }
-
- log.info("- " + metricsTable + " - " + lastMigratedRecord + " -");
-
- numberOfBatchesMigrated++;
- if (Task.Estimate.equals(task) && numberOfBatchesMigrated >= NUMBER_OF_BATCHES_FOR_ESTIMATION) {
- break;
- }
- }
-
- metricsIndexAccumulator.drain();
-
- telemetry.getMigrationTimer().stop();
-
- dataSource.close();
- telemetry.getGeneralTimer().stop();
-
- return telemetry;
- }
-
- private void insertDataToCassandra(List<Object[]> existingData) throws Exception {
- List<ResultSetFuture> resultSetFutures = new ArrayList<ResultSetFuture>();
- Batch batch = QueryBuilder.batch();
- int batchSize = 0;
-
- //only need approximate TTL to speed up processing
- //given that each batch is processed within seconds, getting the
- //system time once per batch has minimal impact on the record retention
- long creationTimeMillis;
- long itemTTLSeconds;
- long currentTimeMillis = System.currentTimeMillis();
- long expectedTTLMillis = metricsTable.getTTLinMilliseconds();
-
- for (Object[] rawMeasurement : existingData) {
- creationTimeMillis = Long.parseLong(rawMeasurement[MigrationQuery.TIMESTAMP_INDEX].toString());
- itemTTLSeconds = (expectedTTLMillis - currentTimeMillis + creationTimeMillis) / 1000l;
-
- if (itemTTLSeconds > 0) {
- int scheduleId = Integer.parseInt(rawMeasurement[MigrationQuery.SCHEDULE_INDEX].toString());
- Date time = new Date(creationTimeMillis);
-
- batch.add(QueryBuilder.insertInto(metricsTable.toString()).value("schedule_id", scheduleId)
- .value("time", time).value("type", AggregateType.AVG.ordinal())
- .value("value", Double.parseDouble(rawMeasurement[MigrationQuery.VALUE_INDEX].toString()))
- .using(ttl((int) itemTTLSeconds)));
-
- batch.add(QueryBuilder.insertInto(metricsTable.toString()).value("schedule_id", scheduleId)
- .value("time", time).value("type", AggregateType.MIN.ordinal())
- .value("value", Double.parseDouble(rawMeasurement[MigrationQuery.MIN_VALUE_INDEX].toString()))
- .using(ttl((int) itemTTLSeconds)));
-
- batch.add(QueryBuilder.insertInto(metricsTable.toString()).value("schedule_id", scheduleId)
- .value("time", time).value("type", AggregateType.MAX.ordinal())
- .value("value", Double.parseDouble(rawMeasurement[MigrationQuery.MAX_VALUE_INDEX].toString()))
- .using(ttl((int) itemTTLSeconds)));
-
- batchSize += 3;
-
- metricsIndexAccumulator.add(scheduleId, creationTimeMillis);
- }
-
- if (batchSize >= MAX_AGGREGATE_BATCH_TO_CASSANDRA) {
- resultSetFutures.add(config.getSession().executeAsync(batch));
- batch = QueryBuilder.batch();
- batchSize = 0;
- }
- }
-
- if (batchSize != 0) {
- resultSetFutures.add(config.getSession().executeAsync(batch));
- }
-
- for (ResultSetFuture future : resultSetFutures) {
- future.get();
- }
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java
deleted file mode 100644
index 05a7ac6..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator.workers;
-
-/**
- * @author Stefan Negrea
- *
- */
-public interface CallableMigrationWorker {
-
- public static final int MAX_RECORDS_TO_LOAD_FROM_SQL = 30000;
- public static final int MAX_RAW_BATCH_TO_CASSANDRA = 100;
- public static final int MAX_AGGREGATE_BATCH_TO_CASSANDRA = 50;
- public static final int NUMBER_OF_BATCHES_FOR_ESTIMATION = 4;
- public static final int MAX_NUMBER_OF_FAILURES = 5;
-
- long estimate() throws Exception;
-
- void migrate() throws Exception;
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java
deleted file mode 100644
index c1cb62c..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator.workers;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.StatelessSession;
-
-import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
-
-/**
- * @author Stefan Negrea
- *
- */
-public class DeleteAllData extends AbstractMigrationWorker implements CallableMigrationWorker {
-
- private final Log log = LogFactory.getLog(DeleteAllData.class);
-
- private final DataMigratorConfiguration config;
-
- public DeleteAllData(DataMigratorConfiguration config) {
- this.config = config;
- }
-
- public void migrate() {
- org.hibernate.Query nativeQuery;
- StatelessSession session = getSQLSession(config);
-
- if (config.isRun1HAggregateDataMigration()) {
- session.getTransaction().begin();
- nativeQuery = session.createSQLQuery(MigrationQuery.DELETE_1H_DATA.toString());
- nativeQuery.executeUpdate();
- session.getTransaction().commit();
- log.info("- RHQ_MEASUREMENT_DATA_NUM_1H - Cleaned -");
- }
-
- if (config.isRun6HAggregateDataMigration()) {
- session.getTransaction().begin();
- nativeQuery = session.createSQLQuery(MigrationQuery.DELETE_6H_DATA.toString());
- nativeQuery.executeUpdate();
- session.getTransaction().commit();
- log.info("- RHQ_MEASUREMENT_DATA_NUM_6H - Cleaned -");
- }
-
- if (config.isRun1DAggregateDataMigration()) {
- session.getTransaction().begin();
- nativeQuery = session.createSQLQuery(MigrationQuery.DELETE_1D_DATA.toString());
- nativeQuery.executeUpdate();
- session.getTransaction().commit();
- log.info("- RHQ_MEASUREMENT_DATA_NUM_1D - Cleaned -");
- }
-
- if (config.isRunRawDataMigration()) {
- for (String table : getRawDataTables()) {
- session.getTransaction().begin();
- String deleteAllData = String.format(MigrationQuery.DELETE_RAW_ALL_DATA.toString(), table);
- nativeQuery = session.createSQLQuery(deleteAllData);
- nativeQuery.executeUpdate();
- session.getTransaction().commit();
- log.info("- " + table + " - Cleaned -");
- }
- }
-
- closeSQLSession(session);
- }
-
- @Override
- public long estimate() throws Exception {
- return 300000; // return return 5 minutes for now without any database side checks.
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java
deleted file mode 100644
index a126d7e..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator.workers;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.datastax.driver.core.BoundStatement;
-import com.datastax.driver.core.PreparedStatement;
-import com.datastax.driver.core.ResultSetFuture;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.Query;
-import org.hibernate.StatelessSession;
-import org.joda.time.DateTime;
-import org.joda.time.Duration;
-
-import org.rhq.server.metrics.DateTimeService;
-import org.rhq.server.metrics.MetricsConfiguration;
-import org.rhq.server.metrics.domain.MetricsTable;
-import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
-
-/**
- * @author Stefan Negrea
- *
- */
-public class MetricsIndexUpdateAccumulator extends AbstractMigrationWorker {
- private static final int MAX_SIZE = 3000;
-
- private final Log log = LogFactory.getLog(MetricsIndexUpdateAccumulator.class);
-
- private final DateTimeService dateTimeService = new DateTimeService();
- private final MetricsConfiguration configuration = new MetricsConfiguration();
- private final Map<Integer, Set<Long>> accumulator = new HashMap<Integer, Set<Long>>();
-
- private final MetricsTable table;
- private final DataMigratorConfiguration config;
-
- private final long timeLimit;
- private final PreparedStatement updateMetricsIndex;
- private final Duration sliceDuration;
- private final boolean validAccumulatorTable;
-
- private int currentCount = 0;
-
- public MetricsIndexUpdateAccumulator(MetricsTable table, DataMigratorConfiguration config) {
- this.table = table;
- this.config = config;
-
- if (MetricsTable.RAW.equals(table) || MetricsTable.ONE_HOUR.equals(table)
- || MetricsTable.SIX_HOUR.equals(table)) {
- this.sliceDuration = configuration.getTimeSliceDuration(table);
- this.timeLimit = this.getLastAggregationTime(table) - this.sliceDuration.getMillis();
- this.updateMetricsIndex = config.getSession().prepare(
- "INSERT INTO " + MetricsTable.INDEX.getTableName()
- + " (bucket, time, schedule_id) VALUES (?, ?, ?)");
- this.validAccumulatorTable = true;
- } else {
- this.timeLimit = Integer.MAX_VALUE;
- this.updateMetricsIndex = null;
- this.sliceDuration = null;
- this.validAccumulatorTable = false;
- }
- }
-
- public void add(int scheduleId, long timestamp) throws Exception {
- if (validAccumulatorTable && timeLimit <= timestamp) {
- long alignedTimeSlice = dateTimeService.getTimeSlice(timestamp, sliceDuration).getMillis();
-
- if (accumulator.containsKey(scheduleId)) {
- Set<Long> timestamps = accumulator.get(scheduleId);
- if (!timestamps.contains(alignedTimeSlice)) {
- timestamps.add(alignedTimeSlice);
-
- currentCount++;
- }
- } else {
- Set<Long> timestamps = new HashSet<Long>();
- timestamps.add(timestamp);
- accumulator.put(scheduleId, timestamps);
-
- currentCount++;
- }
- }
-
- if (currentCount > MAX_SIZE) {
- drain();
- }
- }
-
- public void drain() throws Exception {
- if (log.isDebugEnabled()) {
- log.debug("Draining metrics index accumulator with " + currentCount + " entries");
- }
-
- List<ResultSetFuture> resultSetFutures = new ArrayList<ResultSetFuture>();
-
- for (Map.Entry<Integer, Set<Long>> entry : accumulator.entrySet()) {
- for (Long timestamp : entry.getValue()) {
- BoundStatement statement = updateMetricsIndex.bind(this.table.getTableName(), new Date(timestamp),
- entry.getKey());
- resultSetFutures.add(config.getSession().executeAsync(statement));
- }
- }
-
- for (ResultSetFuture future : resultSetFutures) {
- future.get();
- }
-
- accumulator.clear();
- currentCount = 0;
- }
-
- private long getLastAggregationTime(MetricsTable migratedTable) {
- StatelessSession session = getSQLSession(config);
-
- long aggregationSlice = -1;
- Duration duration = null;
- String queryString = null;
-
- if (MetricsTable.RAW.equals(migratedTable)) {
- duration = configuration.getRawTimeSliceDuration();
- queryString = MigrationQuery.MAX_TIMESTAMP_1H_DATA.toString();
- } else if (MetricsTable.ONE_HOUR.equals(migratedTable)) {
- duration = configuration.getOneHourTimeSliceDuration();
- queryString = MigrationQuery.MAX_TIMESTAMP_6H_DATA.toString();
- } else if (MetricsTable.SIX_HOUR.equals(migratedTable)) {
- duration = configuration.getSixHourTimeSliceDuration();
- queryString = MigrationQuery.MAX_TIMESTAMP_1D_DATA.toString();
- }
-
- if (duration != null && queryString != null) {
- Query query = session.createSQLQuery(queryString);
- String queryResult = query.uniqueResult().toString();
- Long timestamp = Long.parseLong(queryResult);
- aggregationSlice = dateTimeService.getTimeSlice(new DateTime(timestamp), duration).getMillis();
- }
-
- closeSQLSession(session);
-
- return aggregationSlice;
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java
deleted file mode 100644
index 7f13349..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator.workers;
-
-/**
- * @author Stefan Negrea
- *
- */
-public enum MigrationQuery {
- SELECT_1H_DATA(
- "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1H ORDER BY schedule_id, time_stamp"), SELECT_6H_DATA(
- "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_6H ORDER BY schedule_id, time_stamp"), SELECT_1D_DATA(
- "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1D ORDER BY schedule_id, time_stamp"),
-
- DELETE_1H_DATA("DELETE FROM RHQ_MEASUREMENT_DATA_NUM_1H"), DELETE_6H_DATA("DELETE FROM RHQ_MEASUREMENT_DATA_NUM_6H"), DELETE_1D_DATA(
- "DELETE FROM RHQ_MEASUREMENT_DATA_NUM_1D"),
-
- COUNT_1H_DATA("SELECT COUNT(*) FROM RHQ_MEASUREMENT_DATA_NUM_1H"), COUNT_6H_DATA(
- "SELECT COUNT(*) FROM RHQ_MEASUREMENT_DATA_NUM_6H"), COUNT_1D_DATA(
- "SELECT COUNT(*) FROM RHQ_MEASUREMENT_DATA_NUM_1D"),
-
- MAX_TIMESTAMP_1H_DATA("SELECT MAX(time_stamp) FROM RHQ_MEASUREMENT_DATA_NUM_1H"), MAX_TIMESTAMP_6H_DATA(
- "SELECT MAX(time_stamp) FROM RHQ_MEASUREMENT_DATA_NUM_6H"), MAX_TIMESTAMP_1D_DATA(
- "SELECT MAX(time_stamp) FROM RHQ_MEASUREMENT_DATA_NUM_1D"),
-
- COUNT_RAW("SELECT COUNT(*) FROM %s"), SELECT_RAW_DATA(
- "SELECT schedule_id, time_stamp, value FROM %s ORDER BY schedule_id, time_stamp"), DELETE_RAW_ALL_DATA(
- "DELETE FROM %s"), DELETE_RAW_ENTRY("DELETE FROM %s WHERE schedule_id = ?");
-
- public static final int SCHEDULE_INDEX = 0;
- public static final int TIMESTAMP_INDEX = 1;
- public static final int VALUE_INDEX = 2;
- public static final int MIN_VALUE_INDEX = 3;
- public static final int MAX_VALUE_INDEX = 4;
-
- private String query;
-
- private MigrationQuery(String query) {
- this.query = query;
- }
-
- /**
- * @return the query
- */
- public String getQuery() {
- return query;
- }
-
- @Override
- public String toString() {
- return query;
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java
deleted file mode 100644
index 6680fd2..0000000
--- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright 2013, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.server.metrics.migrator.workers;
-
-import static com.datastax.driver.core.querybuilder.QueryBuilder.ttl;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-
-import com.datastax.driver.core.ResultSetFuture;
-import com.datastax.driver.core.querybuilder.Batch;
-import com.datastax.driver.core.querybuilder.QueryBuilder;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.StatelessSession;
-
-import org.rhq.server.metrics.domain.MetricsTable;
-import org.rhq.server.metrics.migrator.DataMigrator;
-import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
-import org.rhq.server.metrics.migrator.DataMigrator.Task;
-import org.rhq.server.metrics.migrator.ExistingDataSource;
-import org.rhq.server.metrics.migrator.Telemetry;
-
-/**
- * @author Stefan Negrea
- *
- */
-public class RawDataMigrator extends AbstractMigrationWorker implements CallableMigrationWorker {
- private final Log log = LogFactory.getLog(RawDataMigrator.class);
-
- private final Queue<String> tablesNotProcessed = new LinkedList<String>(Arrays.asList(getRawDataTables()));
- private final MetricsIndexUpdateAccumulator metricsIndexAccumulator;
- private final DataMigratorConfiguration config;
-
- public RawDataMigrator(DataMigratorConfiguration config) {
- this.config = config;
- this.metricsIndexAccumulator = new MetricsIndexUpdateAccumulator(MetricsTable.RAW, config);
- }
-
- public long estimate() throws Exception {
- long recordCount = 0;
- for (String table : getRawDataTables()) {
- String countQuery = String.format(MigrationQuery.COUNT_RAW.toString(), table);
- long tableRecordCount = this.getRowCount(countQuery);
-
- log.debug("Retrieved record count for table " + table + " -- " + tableRecordCount);
-
- recordCount += tableRecordCount;
- }
-
- Telemetry telemetry = this.performMigration(Task.Estimate);
- long estimatedTimeToMigrate = telemetry.getMigrationTime();
- long estimation = (recordCount / (long) MAX_RECORDS_TO_LOAD_FROM_SQL / (long) NUMBER_OF_BATCHES_FOR_ESTIMATION)
- * estimatedTimeToMigrate;
- estimation += telemetry.getNonMigrationTime();
-
- return estimation;
- }
-
- public void migrate() throws Exception {
- performMigration(Task.Migrate);
- }
-
- private long getRowCount(String countQuery) {
- StatelessSession session = getSQLSession(config);
-
- org.hibernate.Query query = session.createSQLQuery(countQuery);
- query.setReadOnly(true);
- query.setTimeout(DataMigrator.SQL_TIMEOUT);
-
- long count = Long.parseLong(query.uniqueResult().toString());
-
- closeSQLSession(session);
-
- return count;
- }
-
- private Telemetry performMigration(Task task) throws Exception {
- Telemetry telemetry = new Telemetry();
- telemetry.getGeneralTimer().start();
-
- long numberOfBatchesMigrated = 0;
-
- List<Object[]> existingData;
- int failureCount;
-
- telemetry.getMigrationTimer().start();
- telemetry.getMigrationTimer().suspend();
-
- while (!tablesNotProcessed.isEmpty()) {
- String table = tablesNotProcessed.peek();
-
- String selectQuery = String.format(MigrationQuery.SELECT_RAW_DATA.toString(), table);
-
- ExistingDataSource dataSource = getExistingDataSource(selectQuery, task, config);
- dataSource.initialize();
-
- log.info("Start migrating raw table: " + table);
-
- telemetry.getMigrationTimer().resume();
- int lastMigratedRecord = 0;
- while (true) {
- existingData = dataSource.getData(lastMigratedRecord, MAX_RECORDS_TO_LOAD_FROM_SQL);
-
- if (existingData.size() == 0) {
- break;
- }
-
- lastMigratedRecord += existingData.size();
-
- failureCount = 0;
- while (failureCount < MAX_NUMBER_OF_FAILURES) {
- try {
- insertDataToCassandra(existingData);
- break;
- } catch (Exception e) {
- log.error("Failed to insert " + MetricsTable.RAW.toString()
- + " data. Attempting to insert the current batch of data one more time");
- log.error(e);
-
- failureCount++;
- if (failureCount == MAX_AGGREGATE_BATCH_TO_CASSANDRA) {
- throw e;
- }
- }
- }
-
- log.info("- " + table + " - " + lastMigratedRecord + " -");
-
- numberOfBatchesMigrated++;
- if (Task.Estimate.equals(task) && numberOfBatchesMigrated >= NUMBER_OF_BATCHES_FOR_ESTIMATION) {
- break;
- }
- }
- telemetry.getMigrationTimer().suspend();
-
- if (Task.Migrate.equals(task)) {
- log.info("Done migrating raw table" + table + "---------------------");
-
- if (config.isDeleteDataImmediatelyAfterMigration()) {
- deleteTableData(table);
- }
- } else if (numberOfBatchesMigrated >= NUMBER_OF_BATCHES_FOR_ESTIMATION) {
- break;
- }
-
- dataSource.close();
- tablesNotProcessed.poll();
- }
-
- telemetry.getMigrationTimer().resume();
- metricsIndexAccumulator.drain();
- telemetry.getMigrationTimer().suspend();
-
- telemetry.getGeneralTimer().stop();
- return telemetry;
- }
-
- private void deleteTableData(String table) throws Exception {
- String deleteQuery = String.format(MigrationQuery.DELETE_RAW_ENTRY.toString(), table);
- int failureCount = 0;
- while (failureCount < MAX_NUMBER_OF_FAILURES) {
- try {
- StatelessSession session = getSQLSession(config);
- session.getTransaction().begin();
- org.hibernate.Query nativeQuery = session.createSQLQuery(deleteQuery);
- nativeQuery.executeUpdate();
- session.getTransaction().commit();
- closeSQLSession(session);
- log.info("- " + table + " - Cleaned -");
- } catch (Exception e) {
- log.error("Failed to delete " + table + " data. Attempting to delete data one more time...");
-
- failureCount++;
- if (failureCount == MAX_NUMBER_OF_FAILURES) {
- throw e;
- }
- }
- }
- }
-
- private void insertDataToCassandra(List<Object[]> existingData) throws Exception {
- List<ResultSetFuture> resultSetFutures = new ArrayList<ResultSetFuture>();
- Batch batch = QueryBuilder.batch();
- int batchSize = 0;
-
- //only need approximate TTL to speed up processing
- //given that each batch is processed within seconds, getting the
- //system time once per batch has minimal impact on the record retention
- long creationTimeMillis;
- long itemTTLSeconds;
- long currentTimeMillis = System.currentTimeMillis();
- long expectedTTLMillis = MetricsTable.RAW.getTTLinMilliseconds();
-
- for (Object[] rawDataPoint : existingData) {
- creationTimeMillis = Long.parseLong(rawDataPoint[MigrationQuery.TIMESTAMP_INDEX].toString());
- itemTTLSeconds = (expectedTTLMillis - currentTimeMillis + creationTimeMillis) / 1000l;
-
- if (itemTTLSeconds > 0) {
- int scheduleId = Integer.parseInt(rawDataPoint[MigrationQuery.SCHEDULE_INDEX].toString());
- Date creationTime = new Date(creationTimeMillis);
-
- batch.add(QueryBuilder.insertInto(MetricsTable.RAW.toString()).value("schedule_id", scheduleId)
- .value("time", creationTime)
- .value("value", Double.parseDouble(rawDataPoint[MigrationQuery.VALUE_INDEX].toString()))
- .using(ttl((int) itemTTLSeconds)));
- batchSize++;
-
- metricsIndexAccumulator.add(scheduleId, creationTimeMillis);
- }
-
- if (batchSize >= MAX_RAW_BATCH_TO_CASSANDRA) {
- resultSetFutures.add(config.getSession().executeAsync(batch));
- batch = QueryBuilder.batch();
- batchSize = 0;
- }
- }
-
- if (batchSize != 0) {
- resultSetFutures.add(config.getSession().executeAsync(batch));
- }
-
- for (ResultSetFuture future : resultSetFutures) {
- future.get();
- }
- }
-}
diff --git a/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/DataSourceTest.java b/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/DataSourceTest.java
deleted file mode 100644
index cda04ca..0000000
--- a/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/DataSourceTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2013 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.rhq.server.metrics;
-
-import java.util.List;
-import java.util.Properties;
-
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-
-import org.apache.commons.lang.time.StopWatch;
-import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.hibernate.ejb.Ejb3Configuration;
-
-import org.rhq.server.metrics.migrator.ExistingDataBulkExportSource;
-import org.rhq.server.metrics.migrator.ExistingPostgresDataBulkExportSource;
-
-/**
- * @author Thomas Segismont
- */
-
-
-public class DataSourceTest {
-
- //ExistingPostgresDataBulkExport
- public static void main(String[] args) throws Exception {
- BasicConfigurator.configure();
- Logger.getRootLogger().setLevel(Level.INFO);
- Logger.getLogger("org.rhq").setLevel(Level.DEBUG);
- EntityManagerFactory entityManagerFactory = null;
- EntityManager entityManager = null;
- ExistingDataBulkExportSource source = null;
- try {
- entityManagerFactory = createEntityManager();
- entityManager = entityManagerFactory.createEntityManager();
- source = new ExistingPostgresDataBulkExportSource(entityManager,
- "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1D");
- StopWatch stopWatch = new StopWatch();
- stopWatch.start();
- source.initialize();
- int rowIndex = 0;
- int maxResults = 30000;
- for (;;) {
- List<Object[]> existingData = source.getData(rowIndex, maxResults);
- if (existingData.size() < maxResults) {
- break;
- } else {
- rowIndex += maxResults;
- }
- }
- stopWatch.stop();
- System.out.println("Execution: " + stopWatch);
- } finally {
- if (source != null) {
- source.close();
- }
- if (entityManager != null) {
- entityManager.close();
- }
- if (entityManagerFactory != null) {
- entityManagerFactory.close();
- }
- }
- }
-
- private static EntityManagerFactory createEntityManager() throws Exception {
- Properties properties = new Properties();
- properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
- properties.put("hibernate.connection.username", "rhqadmin");
- properties.put("hibernate.connection.password", "rhqadmin");
- properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
- String driverClassName = "org.postgresql.Driver";
- try {
- //Required to preload the driver manually.
- //Without this the driver load will fail due to the packaging.
- Class.forName(driverClassName);
- } catch (ClassNotFoundException e) {
- throw new Exception("Postgres SQL Driver class could not be loaded. Missing class: " + driverClassName);
- }
- properties.put("hibernate.driver_class", driverClassName);
- properties.put("hibernate.connection.url", "jdbc:postgresql://localhost:5432/rhq");
- Ejb3Configuration configuration = new Ejb3Configuration();
- configuration.setProperties(properties);
- return configuration.buildEntityManagerFactory();
- }
-
- //ExistingDataJPABulkExportSource
-
- public static void main2(String[] args) throws Exception {
- BasicConfigurator.configure();
- Logger.getRootLogger().setLevel(Level.INFO);
- Logger.getLogger("org.rhq").setLevel(Level.DEBUG);
- EntityManagerFactory entityManagerFactory = null;
- EntityManager entityManager = null;
- ExistingDataBulkExportSource source = null;
- try {
- entityManagerFactory = createEntityManager();
- entityManager = entityManagerFactory.createEntityManager();
- source = new ExistingPostgresDataBulkExportSource(entityManager,
- "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1D");
- StopWatch stopWatch = new StopWatch();
- stopWatch.start();
- source.initialize();
- int rowIndex = 0;
- int maxResults = 30000;
- for (;;) {
- List<Object[]> existingData = source.getData(rowIndex, maxResults);
- if (existingData.size() < maxResults) {
- break;
- } else {
- rowIndex += maxResults;
- }
- }
- stopWatch.stop();
- System.out.println("Execution: " + stopWatch);
- } finally {
- if (source != null) {
- source.close();
- }
- if (entityManager != null) {
- entityManager.close();
- }
- if (entityManagerFactory != null) {
- entityManagerFactory.close();
- }
- }
- }
-
- private static EntityManagerFactory createEntityManager2() throws Exception {
- Properties properties = new Properties();
- properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
- properties.put("hibernate.connection.username", "rhqadmin");
- properties.put("hibernate.connection.password", "rhqadmin");
- properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
- String driverClassName = "org.postgresql.Driver";
- try {
- //Required to preload the driver manually.
- //Without this the driver load will fail due to the packaging.
- Class.forName(driverClassName);
- } catch (ClassNotFoundException e) {
- throw new Exception("Postgres SQL Driver class could not be loaded. Missing class: " + driverClassName);
- }
- properties.put("hibernate.driver_class", driverClassName);
- properties.put("hibernate.connection.url", "jdbc:postgresql://localhost:5432/rhqdev");
- Ejb3Configuration configuration = new Ejb3Configuration();
- configuration.setProperties(properties);
- return configuration.buildEntityManagerFactory();
- }
-
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/server-metrics/tools/create_test_data.py b/modules/enterprise/server/server-metrics/tools/create_test_data.py
deleted file mode 100644
index 4e60f04..0000000
--- a/modules/enterprise/server/server-metrics/tools/create_test_data.py
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# RHQ Management Platform
-# Copyright (C) 2005-2013 Red Hat, Inc.
-# All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-# Notes:
-#1) All times are expressed in milliseconds because the database stores timestamps in milliseconds
-#2) The data is randomly generated and does represent a live system collection patterns
-#3) The amount of data generated is based on estimates described at:
-# https://docs.jboss.org/author/display/RHQ/Metrics+Data+Migration+-+Design
-#4) The data generated is in a state consistent with the migration process
-#5) !!!! All existing data is wiped out of the existing database tables and new data only is written back!!!
-# !!!! You will lose your data if your this script without manually disabling the data deletion part !!!!
-#6) Expect the generation process to take about 60 seconds per agent
-#7) The script is configured to generate data for 10 agents, if you can increase that limit by updating the variables below
-
-import psycopg2
-import sys
-import random
-import time
-import cStringIO
-import math
-from optparse import OptionParser
-
-
-def parse_arguments():
- parser = OptionParser()
-
- #db settings
- parser.add_option("--host", default="localhost", action="store", type="string", dest="db_host")
- parser.add_option("--database", default="rhq_db", action="store", type="string", dest="db_database")
- parser.add_option("--user", default="rhqadmin", action="store", type="string", dest="db_user")
- parser.add_option("--password", default="rhqadmin", action="store", type="string", dest="db_password")
-
- #program settings
- parser.add_option("--agents", default=10, action="store", type="int", dest="number_of_agents")
-
-
- (options, args) = parser.parse_args()
- print options
-
- return options
-
-class MetricType:
- Raw,Aggregate = range(2)
-
-
-RANDOM_DATA_FACTOR = 10000;
-
-
-def generate_random_metrics(number_of_metrics = 1000, start_timestamp = 0, number_of_schedule_ids = 1, start_of_schedule_id_sequence = 1, metricType = MetricType.Raw):
- #generate a random series of timestamps for the random metrics
- end_timestamp = start_timestamp + number_of_metrics * 10;
- timestamps = random.sample(range(start_timestamp,end_timestamp),number_of_metrics)
-
- #generate a random set of schedule ids
- end_of_schedule_id_sequence = start_of_schedule_id_sequence + number_of_schedule_ids * 100;
- schedule_ids = random.sample(range(start_of_schedule_id_sequence,end_of_schedule_id_sequence),number_of_schedule_ids);
-
- #the set of random metrics
- random_metrics = []
-
- #generate the random metrics
- for i in range(number_of_metrics):
- if metricType == MetricType.Raw :
- value = generate_random_raw_value()
- else :
- value = generate_random_aggregate_value()
-
- random_metric = ( random.choice(schedule_ids) , timestamps[i]) + value
- random_metrics.append(random_metric);
-
- return random_metrics
-
-
-def generate_random_raw_value():
- #raw metrics have just value
- return (random.random()*RANDOM_DATA_FACTOR,)
-
-
-def generate_random_aggregate_value():
- #aggregate metrics have min, max, and value
- random_values = [random.random()*RANDOM_DATA_FACTOR,random.random()*RANDOM_DATA_FACTOR, random.random()*RANDOM_DATA_FACTOR]
- min_value = min(random_values)
- max_value = max(random_values)
- random_values.remove(min_value)
- random_values.remove(max_value)
- average_value = random_values.pop()
-
- return (average_value, min_value, max_value)
-
-
-def insert_data(connection,data,table_name,table_columns):
- #do the postgres insertion using copy_from functionality since it's the fastest method
- #to bulk import data
- start_time = time.time()
- input_data = cStringIO.StringIO(data)
- cursor = connection.cursor()
- cursor.copy_from(input_data,sep="\t",table = table_name, columns = table_columns)
- cursor.close()
- connection.commit()
- end_time = time.time()
- return end_time - start_time
-
-
-def delete_table_data(connection, table):
- delete_statement = "DELETE FROM " + table;
- connection.cursor().execute(delete_statement)
- connection.commit()
-
-
-def calculate_mean_standard_deviation(numbers):
-
- average = reduce(lambda x, y: x + y, numbers) / len(numbers)
- variance = map(lambda x: (x - average)**2, numbers)
- average_variance = reduce(lambda x, y: x + y, variance) / len(variance)
- standard_deviation = math.sqrt(average_variance)
- return average, standard_deviation
-
-
-
-#Main Script
-script_start_time = time.time()
-
-
-#Parse Command Line Arguments
-options = parse_arguments()
-
-
-#General Configuration
-raw_tables = map(lambda x: "RHQ_MEAS_DATA_NUM_R"+str(x).zfill(2),range(15))
-raw_table_columns = ["schedule_id","time_stamp","value"]
-
-aggregate_tables = map(lambda x: "RHQ_MEASUREMENT_DATA_NUM_"+str(x),["1H","6H","1D"])
-aggregate_table_columns = ["schedule_id","time_stamp","value","minvalue","maxvalue"]
-
- # see the estimation guideline at https://docs.jboss.org/author/display/RHQ/Metrics+Data+Migration+-+Design
-raw_metrics_per_agent = 900000
-aggregate_metrics_per_agent = 700000
-
-
-# some constants to be used by the algorithm
-batch_increment = 10000
-data_start_time = int(time.time() - 2*604800)*1000 # now - 2 week, convert to milliseconds
-
-#establish the db connection, update the settings for your local environment
-connection = psycopg2.connect(host=options.db_host,database=options.db_database,user=options.db_user,password=options.db_password)
-
-
-#Delete all data available
-map(lambda x : delete_table_data(connection, x), raw_tables)
-map(lambda x : delete_table_data(connection, x), aggregate_tables)
-
-
-
-metric_agent_inserting_time = []
-metric_agent_total_time = []
-
-#Generate random raw and aggregate data
-for j in range(options.number_of_agents) :
- agent_start_time = time.time()
- agent_inserting_time = 0
-
- #generate and insert random metrics
- for i in range(0,raw_metrics_per_agent,batch_increment):
- current_batch = i / batch_increment
- random_raw_table = random.choice(raw_tables)
-
- raw_metrics = generate_random_metrics( number_of_metrics = batch_increment, start_timestamp = data_start_time + current_batch*batch_increment*10, \
- start_of_schedule_id_sequence = j * batch_increment, metricType = MetricType.Raw)
-
- data_to_insert = "\n".join(map(str,map(lambda x: "\t".join((str(s) for s in x)),raw_metrics)))
- agent_inserting_time += insert_data(connection,data_to_insert,random_raw_table,raw_table_columns)
-
- #generate and insert aggregate metrics
- for i in range(0,aggregate_metrics_per_agent,batch_increment):
- current_batch = i / batch_increment
- random_aggregate_table = random.choice(aggregate_tables)
-
- aggregate_metrics = generate_random_metrics( number_of_metrics = batch_increment, start_timestamp = data_start_time + current_batch*batch_increment*10, \
- start_of_schedule_id_sequence = j * batch_increment, metricType = MetricType.Aggregate )
-
- data_to_insert = "\n".join(map(str,map(lambda x: "\t".join((str(s) for s in x)),aggregate_metrics)))
- agent_inserting_time += insert_data(connection,data_to_insert,random_aggregate_table,aggregate_table_columns)
-
- metric_agent_inserting_time.append(agent_inserting_time)
- metric_agent_total_time.append( time.time() - agent_start_time )
-
- print "Data created for agent #",j, " - total time:", time.time() - agent_start_time, " seconds"
-
-print "Total time: ",time.time() - script_start_time, " seconds"
-
-average_inserting_time, standard_deviation_inserting_time = calculate_mean_standard_deviation(metric_agent_inserting_time)
-print "Time spent inserting data: ", metric_agent_inserting_time, " seconds"
-print "Average time inserting data for 1 agent:", average_inserting_time, " seconds with a standard deviation of ", standard_deviation_inserting_time
-
-average_time, standard_deviation_time = calculate_mean_standard_deviation(metric_agent_total_time)
-print "Time spent for each agent: ", metric_agent_total_time , " seconds"
-print "Average time for 1 agent:", average_time, " seconds with a standard deviation of ", standard_deviation_time
diff --git a/modules/enterprise/server/server-metrics/tools/plugin_descriptor_metrics.py b/modules/enterprise/server/server-metrics/tools/plugin_descriptor_metrics.py
deleted file mode 100644
index 41e5bcf..0000000
--- a/modules/enterprise/server/server-metrics/tools/plugin_descriptor_metrics.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# RHQ Management Platform
-# Copyright (C) 2005-2013 Red Hat, Inc.
-# All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-import os
-import operator
-from xml.dom import minidom
-
-def extract_plugin(descriptor):
- prefix = "rhq/modules/plugins/"
- descriptor = descriptor.replace(prefix,"")
- return descriptor[:descriptor.index("/")]
-
-to_parse = []
-to_parse.append("rhq/modules/plugins")
-
-plugin_descriptors = []
-
-while len(to_parse) != 0:
- current_folder = to_parse.pop(0)
- for current_file in os.listdir(current_folder):
- if current_file != "target":
- if os.path.isdir(os.path.join(current_folder,current_file)):
- to_parse.append(os.path.join(current_folder,current_file))
- else:
- if current_file.endswith("rhq-plugin.xml"):
- plugin_descriptors.append(os.path.join(current_folder,current_file))
-
-final_tally = []
-
-for descriptor in plugin_descriptors:
- xml_doc = minidom.parse(descriptor)
- metric_list = xml_doc.getElementsByTagName("metric")
- summary_metrics = 0
- detail_metrics = 0
- for metric in metric_list:
- if (metric.attributes.has_key("dataType") and metric.attributes["dataType"].value == "measurement") or \
- not metric.attributes.has_key("dataType"):
- if metric.attributes.has_key("displayType") and metric.attributes["displayType"].value == "summary":
- summary_metrics += 1
- else:
- detail_metrics +=1
-
- final_tally.append((extract_plugin(descriptor), summary_metrics, detail_metrics))
-
-
-index1 = operator.itemgetter(1,2)
-final_tally.sort(key=index1, reverse=True)
-for (plugin_name, summary_metrics,detail_metrics) in final_tally :
- print "|",plugin_name,"|",summary_metrics,"|",detail_metrics,"|", summary_metrics + detail_metrics, "|"
10 years, 11 months
[rhq] modules/enterprise
by mazz
modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Install.java | 2 +-
modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
New commits:
commit b3ddd9c30e6462bed54b3b8a96d7c53b050330bb
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Jun 19 15:30:28 2013 -0400
there is no example.storage.properties, remove its reference from help text
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Install.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Install.java
index f81d006..df07b5a 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Install.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Install.java
@@ -89,7 +89,7 @@ public class Install extends AbstractInstall {
true,
"A properties file with keys that correspond to option names "
+ "of the storage installer. Each property will be translated into an option that is passed to the "
- + " storage installer. See example.storage.properties for examples.")
+ + "storage installer.")
.addOption(
null,
AGENT_PREFERENCE,
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
index 7611419..5d4fd54 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
@@ -100,8 +100,7 @@ public class Upgrade extends AbstractInstall {
true,
"This option is valid only when upgrading from older systems that did not have storage nodes. Use this option to specify non-default storage "
+ "installer options. It is the path to a properties file with keys that correspond to option names of the "
- + "storage installer. Each property will be translated into an option that is passed to the storage "
- + "installer. See example.storage.properties for examples.")
+ + "storage installer. Each property will be translated into an option that is passed to the storage installer.")
.addOption(
null,
RUN_DATA_MIGRATION,
10 years, 11 months
[rhq] Branch 'mtho11/dual-slider-chart-control' - 34 commits - modules/common modules/core modules/enterprise modules/integration-tests
by mike thompson
modules/common/cassandra-ccm/cassandra-ccm-core/src/main/bundle/cassandra/conf/rhq.cassandra.yaml | 8
modules/common/cassandra-ccm/cassandra-ccm-core/src/test/resources/expected.cassandra.yaml | 8
modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java | 132 -
modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java | 26
modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java | 6
modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java | 21
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java | 11
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java | 7
modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java | 30
modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDetailsView.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/lookup/ResourceLookupComboBoxItem.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java | 1
modules/enterprise/pom.xml | 2
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.bat | 199 ++
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh | 243 +++
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.bat | 15
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat | 5
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage.bat | 10
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl | 30
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat | 28
modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf | 10
modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-storage-wrapper.conf | 10
modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml | 4
modules/enterprise/server/data-migration/pom.xml | 213 +++
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java | 309 ++++
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java | 674 ++++++++++
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java | 124 +
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java | 58
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java | 64
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java | 36
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java | 80 +
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java | 156 ++
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java | 57
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java | 123 +
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java | 262 +++
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java | 38
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java | 89 +
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java | 172 ++
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java | 71 +
modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java | 250 +++
modules/enterprise/server/data-migration/src/main/resources/logging.properties | 31
modules/enterprise/server/data-migration/src/main/resources/module/main/module.xml | 32
modules/enterprise/server/data-migration/src/main/scripts/module-assembly.xml | 37
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java | 2
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementOOBManagerBeanTest.java | 2
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java | 2
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java | 2
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBeanPreparation.java | 2
modules/enterprise/server/jar/pom.xml | 30
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java | 1
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java | 21
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java | 22
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/CassandraClusterHeartBeatJob.java | 138 --
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/StorageClientManagerBean.java | 194 --
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java | 34
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MetricsManagerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceTypeHandlerBean.java | 71 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java | 93 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java | 194 ++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterHeartBeatJob.java | 126 +
modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl | 9
modules/enterprise/server/jar/src/main/xsl/apiout2html_overview.xsl | 101 +
modules/enterprise/server/plugins/alert-scriptlang/pom.xml | 15
modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java | 21
modules/enterprise/server/plugins/alert-scriptlang/src/main/resources/META-INF/rhq-serverplugin.xml | 1
modules/enterprise/server/pom.xml | 1
modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java | 55
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java | 34
75 files changed, 4290 insertions(+), 613 deletions(-)
New commits:
commit f90b8e8ef2aa5baf4870cea32a08d9cb86e2dc23
Merge: 09aa4cd c2ca9cd
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jun 19 12:26:17 2013 -0700
Merge branch 'master' into mtho11/dual-slider-chart-control
commit c2ca9cd6da3fa6290e875593009486efda0631a3
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Jun 19 14:56:21 2013 -0400
Beef up RUN_AS/RUN_AS_ME option for the server and storage windows services.
Make sure the RUN_AS options can be used without hanging rhqctl on a
password prompt. These are now like the agent, although by default
RHQ_STORAGE_PASSWORD_PROMPT is set false for storage and server, since they
are primarily installed via rhqctl. It still defaults to true for the
agent-wrapper, since agents are primarily not installed by rhqctl.
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.bat b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.bat
index 0991caa..cfdc8ea 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.bat
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.bat
@@ -42,13 +42,16 @@ rem the wrapper log file will go.
rem
rem RHQ_SERVER_RUN_AS - if defined, then when the Windows Service is
rem installed, the value is the domain\username of the
-rem user that the Windows Service will run as
+rem user that the Windows Service will run as. It is
+rem important to also set RHQ_SERVER_PASSWORD for the
+rem current user account.
rem
rem RHQ_SERVER_RUN_AS_ME - if defined, then when the Windows Service is
-rem installed, the domain\username of the
-rem user that the Windows Service will run as will
-rem be the current user (.\%USERNAME%). This takes
-rem precedence over RHQ_SERVER_RUN_AS.
+rem installed, the domain\username of the user that the Windows
+rem Service will run as will be the current user (.\%USERNAME%).
+rem This takes precedence over RHQ_SERVER_RUN_AS. It is
+rem important to also set RHQ_SERVER_PASSWORD for the
+rem current user account.
rem
rem Note that you cannot define custom Java VM parameters or command line
rem arguments to pass to the RHQ Server standalone.sh. If you wish to pass in
@@ -168,6 +171,8 @@ if defined RHQ_SERVER_DEBUG set _DEBUG_OPTS=wrapper.debug=true
rem Determine what user the Windows Service will run as.
if defined RHQ_SERVER_RUN_AS set _WRAPPER_NTSERVICE_ACCOUNT="wrapper.ntservice.account=%RHQ_SERVER_RUN_AS%"
if defined RHQ_SERVER_RUN_AS_ME set _WRAPPER_NTSERVICE_ACCOUNT="wrapper.ntservice.account=.\%USERNAME%"
+rem This service is typically installed by rhqctl, so assume we don't want to prompt
+if not defined RHQ_SERVER_PASSWORD_PROMPT set RHQ_SERVER_PASSWORD_PROMPT=false
if /i "%1"=="console" (
rem START SERVER
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat
index 5b96ff0..43ccd3b 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat
@@ -4,7 +4,7 @@ rem ============================================================================
rem RHQ Storage Installer Script
rem
rem This file is used to complete the installation of the RHQ storage Server on a
-rem UNIX platform.
+rem Windows platform.
rem
rem This script is customizable by setting the following environment variables:
rem
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage.bat b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage.bat
index 3ab4442..3201ae5 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage.bat
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage.bat
@@ -42,12 +42,16 @@ rem the wrapper log file will go.
rem
rem RHQ_STORAGE_RUN_AS - if defined, then when the Windows Service is
rem installed, the value is the domain\username of the
-rem user that the Windows Service will run as
+rem user that the Windows Service will run as. It is
+rem important to also set RHQ_STORAGE_PASSWORD for the
+rem current user account.
rem
rem RHQ_STORAGE_RUN_AS_ME - if defined, then when the Windows Service is
rem installed, the domain\username of the user that the Windows
rem Service will run as will be the current user (.\%USERNAME%).
-rem This takes precedence over RHQ_STORAGE_RUN_AS.
+rem This takes precedence over RHQ_STORAGE_RUN_AS. It is
+rem important to also set RHQ_STORAGE_PASSWORD for the
+rem current user account.
rem
rem Note that you cannot define custom Java VM parameters or command line
rem arguments to pass to Cassandra. If you wish to pass in specific arguments,
@@ -187,6 +191,8 @@ if defined RHQ_STORAGE_DEBUG set _DEBUG_OPTS=wrapper.debug=true
rem Determine what user the Windows Service will run as.
if defined RHQ_STORAGE_RUN_AS set _WRAPPER_NTSERVICE_ACCOUNT="wrapper.ntservice.account=%RHQ_STORAGE_RUN_AS%"
if defined RHQ_STORAGE_RUN_AS_ME set _WRAPPER_NTSERVICE_ACCOUNT="wrapper.ntservice.account=.\%USERNAME%"
+rem This service is typically installed by rhqctl, so assume we don't want to prompt
+if not defined RHQ_STORAGE_PASSWORD_PROMPT set RHQ_STORAGE_PASSWORD_PROMPT=false
if /i "%1"=="console" (
rem START STORAGE NODE
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
index c5afd1b..dc41ed9 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
@@ -26,6 +26,12 @@
# set.RHQ_SERVER_JAVA_EXE_FILE_PATH - Java executable
# set.RHQ_SERVER_OS_PLATFORM - The operating system platform name
# set.RHQ_SERVER_WRAPPER_LOG_DIR_PATH - The Java Service Wrapper's log file (helpful if installing, uninstalling or starting fails)
+# set.RHQ_SERVER_PASSWORD_PROMPT - TRUE if password needs to be typed on
+# the console when installing. FALSE
+# requires RHQ_SERVER_PASSWORD to be set.
+# set.RHQ_SERVER_PASSWORD - the password of the user that is to
+# run the service. Only used if
+# RHQ_SERVER_PASSWORD_PROMPT is FALSE.
#*****************************************************************************
# Load in the specific environment for the RHQ Server instance to start
@@ -171,8 +177,8 @@ wrapper.ntservice.console=FALSE
# If prompt is true, the user will be prompted for the password. If false,
# the password configuration property will be used.
#wrapper.ntservice.account=.\username
-wrapper.ntservice.password.prompt=TRUE
-#wrapper.ntservice.password=xyz
+wrapper.ntservice.password.prompt=%RHQ_SERVER_PASSWORD_PROMPT%
+wrapper.ntservice.password=%RHQ_SERVER_PASSWORD%
#*****************************************************************************
# Wrapper UNIX Service Properties
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-storage-wrapper.conf b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-storage-wrapper.conf
index 306df82..14f2ff1 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-storage-wrapper.conf
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-storage-wrapper.conf
@@ -27,6 +27,12 @@
# set.RHQ_SERVER_JAVA_EXE_FILE_PATH - Java executable
# set.RHQ_STORAGE_OS_PLATFORM - The operating system platform name
# set.RHQ_STORAGE_WRAPPER_LOG_DIR_PATH - The Java Service Wrapper's log file (helpful if installing, uninstalling or starting fails)
+# set.RHQ_STORAGE_PASSWORD_PROMPT - TRUE if password needs to be typed on
+# the console when installing. FALSE
+# requires RHQ_STORAGE_PASSWORD to be set.
+# set.RHQ_STORAGE_PASSWORD - the password of the user that is to
+# run the service. Only used if
+# RHQ_STORAGE_PASSWORD_PROMPT is FALSE.
#*****************************************************************************
# Load in the specific environment for the RHQ Storage Node instance to start
@@ -156,8 +162,8 @@ wrapper.ntservice.console=FALSE
# If prompt is true, the user will be prompted for the password. If false,
# the password configuration property will be used.
#wrapper.ntservice.account=.\username
-wrapper.ntservice.password.prompt=TRUE
-#wrapper.ntservice.password=xyz
+wrapper.ntservice.password.prompt=%RHQ_STORAGE_PASSWORD_PROMPT%
+wrapper.ntservice.password=%RHQ_STORAGE_PASSWORD%
#*****************************************************************************
# Wrapper UNIX Service Properties
commit 59ec01dd518b9b3ebe929d61186bbee8f74c69c6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Jun 19 14:27:32 2013 -0400
fix comments in rhqctl
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl
index 1c537c6..73dda06 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl
@@ -1,16 +1,16 @@
#!/bin/sh
# =============================================================================
-# RHQ Storage Installer Script
+# RHQ Control Script
#
-# This file is used to complete the installation of the RHQ storage Server on a
-# UNIX platform.
+# This file is used to perform install/upgrade/start/stop commands for
+# RHQ Servers (and their associated storage nodes/agents) on a UNIX platform.
#
# This script is customizable by setting the following environment variables:
#
# RHQ_CONTROL_DEBUG - If this is defined, the script will emit debug
-# messages. If this is not defined or set to "false"
-# debug messages are not emitted.
+# messages. If this is not defined or set to "false"
+# debug messages are not emitted.
#
# RHQ_SERVER_HOME - Defines where the server's home install directory is.
# If not defined, it will be assumed to be the parent
@@ -39,18 +39,18 @@
# Server's embedded JRE will be used.
#
# RHQ_CONTROL_JAVA_OPTS - Java VM command line options to be
-# passed into the Java VM. If this is not defined
-# this script will pass in a default set of options.
-# If you only want to add options to the defaults,
-# then you will want to use
-# RHQ_CONTROL_ADDITIONAL_JAVA_OPTS instead.
+# passed into the Java VM. If this is not defined
+# this script will pass in a default set of options.
+# If you only want to add options to the defaults,
+# then you will want to use
+# RHQ_CONTROL_ADDITIONAL_JAVA_OPTS instead.
#
# RHQ_CONTROL_ADDITIONAL_JAVA_OPTS - additional Java VM command
-# line options to be passed into the VM.
-# This is added to RHQ_CONTROL_JAVA_OPTS; it
-# is mainly used to augment the
-# default set of options. This can be
-# left unset if it is not needed.
+# line options to be passed into the VM.
+# This is added to RHQ_CONTROL_JAVA_OPTS;
+# it is mainly used to augment the
+# default set of options. This can be
+# left unset if it is not needed.
#
# If the embedded JRE is to be used but is not available, the fallback
# JRE to be used will be determined by the JAVA_HOME environment variable.
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat
index d86c4f7..43910c1 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat
@@ -1,15 +1,15 @@
@echo off
rem =============================================================================
-rem RHQ Storage Installer Script
+rem RHQ Control Script
rem This file is used to control the RHQ components on a Windows machine.
rem This script is customizable by setting the following environment variables:
rem RHQ_CONTROL_DEBUG - If this is defined, the script will emit debug
-rem messages. If this is not defined or set to "false"
-rem debug messages are not emitted.
+rem messages. If this is not defined or set to "false"
+rem debug messages are not emitted.
rem RHQ_SERVER_HOME - Defines where the server's home install directory is.
rem If not defined, it will be assumed to be the parent
@@ -36,18 +36,18 @@ rem $RHQ_SERVER_JAVA_HOME\bin\java
rem is used.
rem RHQ_CONTROL_JAVA_OPTS - Java VM command line options to be
-rem passed into the Java VM. If this is not defined
-rem this script will pass in a default set of options.
-rem If you only want to add options to the defaults,
-rem then you will want to use
-rem RHQ_CONTROL_ADDITIONAL_JAVA_OPTS instead.
+rem passed into the Java VM. If this is not defined
+rem this script will pass in a default set of options.
+rem If you only want to add options to the defaults,
+rem then you will want to use
+rem RHQ_CONTROL_ADDITIONAL_JAVA_OPTS instead.
rem RHQ_CONTROL_ADDITIONAL_JAVA_OPTS - additional Java VM command
-rem line options to be passed into the VM.
-rem This is added to RHQ_CONTROL_JAVA_OPTS; it
-rem is mainly used to augment the
-rem default set of options. This can be
-rem left unset if it is not needed.
+rem line options to be passed into the VM.
+rem This is added to RHQ_CONTROL_JAVA_OPTS;
+rem it is mainly used to augment the
+rem default set of options. This can be
+rem left unset if it is not needed.
rem =============================================================================
commit 7e512faae456aed3334b83363a7b2425009ea069
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Jun 19 11:39:57 2013 -0500
Add Cassandra schema manager dependency to the list for server jar.
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 70f90ae..6732dad 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -62,6 +62,12 @@
<dependency>
<groupId>org.rhq</groupId>
+ <artifactId>rhq-cassandra-schema</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
<artifactId>rhq-core-client-api</artifactId>
<version>${project.version}</version>
</dependency>
commit b41bd6adf3567c5baa9bc1d8dcc4658a3858590a
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Jun 19 10:32:04 2013 -0500
Update storage node maintanance job to:
1) Run the topology change via the schema manager if necessary
2) Update the seed list
3) Retrieve live configuration from the storage service
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
index 4f74a78..6cecbb2 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
@@ -69,6 +69,8 @@ public class AbstractManager {
private static final String SCHEMA_EXISTS_QUERY = "SELECT * FROM system.schema_keyspaces WHERE keyspace_name = 'rhq';";
private static final String VERSION_COLUMNFAMILY_EXISTS_QUERY = "SELECT * from system.schema_columnfamilies WHERE keyspace_name='rhq' AND columnfamily_name='schema_version';";
private static final String VERSION_QUERY = "SELECT version FROM rhq.schema_version";
+ private static final String REPLICATION_FACTOR_QUERY = "SELECT strategy_options FROM system.schema_keyspaces where keyspace_name='rhq';";
+
private final Log log = LogFactory.getLog(AbstractManager.class);
@@ -248,4 +250,26 @@ public class AbstractManager {
log.info("Shutting down connections");
session.getCluster().shutdown();
}
+
+ protected int getReplicationFactor() {
+ int replicationFactor = 1;
+ try {
+ String replicationFactorString = "replication_factor\"";
+
+ ResultSet resultSet = session.execute(REPLICATION_FACTOR_QUERY);
+ Row row = resultSet.one();
+
+ String resultString = row.getString(0);
+ resultString = resultString.substring(resultString.indexOf(replicationFactorString)
+ + replicationFactorString.length());
+ resultString = resultString.substring(resultString.indexOf('"') + 1);
+ resultString = resultString.substring(0, resultString.indexOf('"'));
+
+ replicationFactor = Integer.parseInt(resultString);
+ } catch (Exception e) {
+ log.error(e);
+ }
+
+ return replicationFactor;
+ }
}
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
index 923065c..fcb8d94 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
@@ -69,9 +69,9 @@ public class SchemaManager {
version.drop();
}
- public void updateTopology() throws Exception {
+ public boolean updateTopology() throws Exception {
TopologyManager topology = new TopologyManager(username, password, nodes);
- topology.updateTopology();
+ return topology.updateTopology();
}
private static List<StorageNode> parseNodeInformation(String... nodes) {
@@ -97,7 +97,7 @@ public class SchemaManager {
if (args.length < 4) {
System.out.println("Usage : command username password nodes...");
System.out.println("\n");
- System.out.println("Commands : install | drop ");
+ System.out.println("Commands : install | drop | topology");
System.out.println("Node format: hostname|thriftPort|nativeTransportPort");
return;
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java
index 87e2a18..850c383 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java
@@ -64,28 +64,39 @@ public class TopologyManager extends AbstractManager {
super(username, password, nodes);
}
- public void updateTopology() throws Exception {
+ public boolean updateTopology() throws Exception {
+ boolean result = false;
+
initCluster();
if (schemaExists()) {
log.info("Applying topology updates...");
- this.updateReplicationFactor(nodes.size());
+ result = this.updateReplicationFactor(nodes.size());
this.updateGCGrace(nodes.size());
} else {
log.info("Topology updates cannot be applied because the schema is not installed.");
}
shutdown();
+
+ return result;
}
private boolean updateReplicationFactor(int numberOfNodes) throws Exception {
log.info("Starting to execute " + Task.UpdateReplicationFactor + " task.");
int replicationFactor = 1;
- if (numberOfNodes < 4) {
- replicationFactor = numberOfNodes;
- } else {
+
+ if (numberOfNodes == 2) {
+ replicationFactor = 2;
+ } else if (numberOfNodes == 3) {
+ replicationFactor = 2;
+ } else if (numberOfNodes > 3) {
replicationFactor = 3;
}
+ if (getReplicationFactor() == replicationFactor) {
+ return false;
+ }
+
log.info("Applying file " + Task.UpdateReplicationFactor.getFile() + " for " + Task.UpdateReplicationFactor
+ " task.");
for (String query : this.getSteps(Task.UpdateReplicationFactor.getFile())) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java
index c6a64fb..f492fa0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java
@@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
+import org.rhq.cassandra.schema.SchemaManager;
import org.rhq.core.domain.cloud.StorageNode;
import org.rhq.core.domain.common.JobTrigger;
import org.rhq.core.domain.configuration.Configuration;
@@ -41,6 +42,7 @@ import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.util.StringUtil;
import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal;
import org.rhq.enterprise.server.operation.OperationManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -67,6 +69,8 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
private final static String UPDATE_SEEDS_LIST = "updateSeedsList";
private final static String SEEDS_LIST = "seedsList";
private final static String SUCCEED_PROPERTY = "succeed";
+ private static final String USERNAME_PROP = "rhq.cassandra.username";
+ private static final String PASSWORD_PROP = "rhq.cassandra.password";
@Override
public void executeJobCode(JobExecutionContext arg0) throws JobExecutionException {
@@ -80,14 +84,36 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
//3. Wait for the all storage nodes to be part of the same cluster
storageNodes = waitForClustering(storageNodes);
- //4. Run repair operation on all the storage nodes
- for (StorageNode storageNode : storageNodes) {
- Resource resource = storageNode.getResource();
- runNodeMaintenanceOperation(resource);
+ //4. Update topology
+ boolean topologyUpdated = updateTopology(storageNodes);
+
+ //5. Run repair operation on all the storage nodes if topology(replication factor was updated)
+ if (topologyUpdated) {
+ List<String> seedList = new ArrayList<String>();
+ for (StorageNode storageNode : storageNodes) {
+ seedList.add(storageNode.getAddress());
+ }
+
+ for (StorageNode storageNode : storageNodes) {
+ Resource resource = storageNode.getResource();
+ runNodeMaintenance(resource, seedList);
+ }
+ }
+ }
+
+ private boolean updateTopology(List<StorageNode> storageNodes) throws JobExecutionException {
+ String username = getRequiredStorageProperty(USERNAME_PROP);
+ String password = getRequiredStorageProperty(PASSWORD_PROP);
+ SchemaManager schemaManager = new SchemaManager(username, password, storageNodes);
+ try{
+ return schemaManager.updateTopology();
+ } catch (Exception e) {
+ log.error(e);
}
+
+ return false;
}
- @SuppressWarnings("unchecked")
private List<StorageNode> waitForClustering(List<StorageNode> storageNodes) {
List<String> existingEndpoints = new ArrayList<String>();
for (StorageNode storageNode : storageNodes) {
@@ -108,14 +134,23 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
List<Resource> childResources = LookupUtil.getResourceManager().findResourcesByCriteria(
LookupUtil.getSubjectManager().getOverlord(), c);
+
+
for (Resource childResource : childResources) {
if (STORAGE_SERVICE.equals(childResource.getName())) {
- PropertyList propertyList = childResource.getResourceConfiguration().getList(
- LOAD_MAP_PROPERTY);
- List<Property> actualList = propertyList.getList();
- for (Property property : actualList) {
- PropertyMap map = (PropertyMap) property;
- endpoints.add(map.get(ENDPOINT_PROPERTY).toString());
+ try {
+ PropertyList propertyList = LookupUtil
+ .getConfigurationManager()
+ .getLiveResourceConfiguration(LookupUtil.getSubjectManager().getOverlord(),
+ childResource.getId(), true).getList(LOAD_MAP_PROPERTY);
+
+ List<Property> actualList = propertyList.getList();
+ for (Property property : actualList) {
+ PropertyMap map = (PropertyMap) property;
+ endpoints.add(map.get(ENDPOINT_PROPERTY).toString());
+ }
+ } catch (Exception e) {
+ log.error("Error fetching live configuration for resource " + resource.getId());
}
break;
@@ -149,7 +184,7 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
return storageNodes;
}
- private void runNodeMaintenanceOperation(Resource resource) {
+ private void runNodeMaintenance(Resource resource, List<String> seedList) {
OperationManagerLocal operationManager = LookupUtil.getOperationManager();
try {
@@ -161,8 +196,14 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
List<Property> properties = new ArrayList<Property>();
properties.add(new PropertySimple(RUN_REPAIR_PROPERTY, Boolean.TRUE));
- properties.add(new PropertySimple(UPDATE_SEEDS_LIST, Boolean.FALSE));
- properties.add(new PropertyList(SEEDS_LIST));
+ properties.add(new PropertySimple(UPDATE_SEEDS_LIST, Boolean.TRUE));
+
+ PropertyList seedListProperty = new PropertyList(SEEDS_LIST);
+ for (String seed : seedList) {
+ seedListProperty.add(new PropertySimple("seed", seed));
+ }
+ properties.add(seedListProperty);
+
Configuration config = new Configuration();
config.setProperties(properties);
newSchedule.setParameters(config);
@@ -244,4 +285,14 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
iteration++;
}
}
+
+ private String getRequiredStorageProperty(String property) throws JobExecutionException {
+ String value = System.getProperty(property);
+ if (StringUtil.isEmpty(property)) {
+ throw new JobExecutionException("The system property [" + property + "] is not set. The RHQ "
+ + "server will not be able connect to the RHQ storage node(s). This property should be defined "
+ + "in rhq-server.properties.");
+ }
+ return value;
+ }
}
commit 2d2a2ac358b7da452397c856bbf58434aa9bdc41
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 19 11:22:42 2013 -0400
adding DataPurgeJobTest back for inclusion in jenkins build
The last build that excluded it did not get hund up but I am not certain if
this test class is in fact the culprit.
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index af2ea60..319ab23 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -558,7 +558,6 @@
<configuration>
<skipTests>${skipTests}</skipTests>
<excludes>
- <exclude>**/DataPurgeJobTest.java</exclude>
<!-- NOTE: PERF GROUP EXCLUDED (SEE BZ 874696) -->
<exclude>org/rhq/**/performance/**/*.java</exclude>
commit 3aa76ccf7db7a0a721cf5c0fb12f2a6b3a49b5be
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Jun 18 16:38:31 2013 -0500
The properties were not linked properly back to the configuration entity when using setProperties method.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
index 591d2e9..b1e6e22 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
@@ -25,7 +25,6 @@ package org.rhq.core.domain.configuration;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -493,6 +492,12 @@ public class Configuration implements Serializable, Cloneable, AbstractPropertyM
return propertiesProxy;
}
+ /**
+ * This method removes the existing set of properties and adds the properties
+ * that got passed as argument to the list of properties.
+ *
+ * @param properties new set of properties
+ */
public void setProperties(Collection<Property> properties) {
//propertiesProxy is a mere view of the properties map.
//thus, if one obtained an instance of propertiesProxy from the #getProperties() method and then tried to
@@ -505,9 +510,9 @@ public class Configuration implements Serializable, Cloneable, AbstractPropertyM
return;
}
- this.properties = new HashMap<String, Property>();
+ this.properties.clear();
for (Property p : properties) {
- this.properties.put(p.getName(), p);
+ this.put(p);
}
}
commit 6543f9887c518eedb657992df72a6f2e0675974c
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jun 19 15:49:48 2013 +0200
BZ 965350 Prevent NPE if the server plugin manager is not yet started.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java
index d7edc6c..0e4283a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java
@@ -611,7 +611,10 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote {
AlertNotificationLog notificationLog = null;
String senderName = alertNotification.getSenderName();
- if (senderName == null) {
+ if (alertSenderPluginManager == null) {
+ notificationLog = new AlertNotificationLog(alert,senderName, ResultState.FAILURE,
+ "Notification was not sent as alert sender plugins are not yet initialized ");
+ } else if (senderName == null) {
notificationLog = new AlertNotificationLog(alert, senderName, ResultState.FAILURE, "Sender '"
+ senderName + "' is not defined");
} else {
@@ -1031,20 +1034,20 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote {
if (isShort) {
if (configNameRegex == null || configNameRegex.length() == 0) {
if (pathNameRegex == null || pathNameRegex.length() == 0) {
- // neither a config name regex nor path regex was specified
+ // neither a config name regex nor path regex was specified
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT_SHORT));
} else {
- // a path name regex was specified, but not a config name regex
+ // a path name regex was specified, but not a config name regex
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT_ONLYPATHS_SHORT,
pathNameRegex));
}
} else {
if (pathNameRegex == null || pathNameRegex.length() == 0) {
- // a config name regex was specified, but not a path name regex
+ // a config name regex was specified, but not a path name regex
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT_ONLYCONFIG_SHORT,
configNameRegex));
} else {
- // both a config name regex and a path regex was specified
+ // both a config name regex and a path regex was specified
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT_CONFIGPATHS_SHORT,
pathNameRegex, configNameRegex));
}
@@ -1052,20 +1055,20 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote {
} else {
if (configNameRegex == null || configNameRegex.length() == 0) {
if (pathNameRegex == null || pathNameRegex.length() == 0) {
- // neither a config name regex nor path regex was specified
+ // neither a config name regex nor path regex was specified
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT));
} else {
- // a path name regex was specified, but not a config name regex
+ // a path name regex was specified, but not a config name regex
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT_ONLYPATHS,
pathNameRegex));
}
} else {
if (pathNameRegex == null || pathNameRegex.length() == 0) {
- // a config name regex was specified, but not a path name regex
+ // a config name regex was specified, but not a path name regex
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT_ONLYCONFIG,
configNameRegex));
} else {
- // both a config name regex and a path regex was specified
+ // both a config name regex and a path regex was specified
str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_DRIFT_CONFIGPATHS,
pathNameRegex, configNameRegex));
}
commit eecad4da551794d406830337748398240d77a01e
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 19 09:09:53 2013 -0400
temporarily disable test class while debugging jenkins issues
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 319ab23..af2ea60 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -558,6 +558,7 @@
<configuration>
<skipTests>${skipTests}</skipTests>
<excludes>
+ <exclude>**/DataPurgeJobTest.java</exclude>
<!-- NOTE: PERF GROUP EXCLUDED (SEE BZ 874696) -->
<exclude>org/rhq/**/performance/**/*.java</exclude>
commit 5dbd4d288614df3e0cd4d661ad7ed3b25cd74be2
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jun 19 15:03:47 2013 +0200
BZ 949065 Prevent a NPE if Events show up before the EventManager is fully initialized.
Reviewed by mazz.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
index 3705505..4f6a9a1 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
@@ -164,7 +164,7 @@ public class PluginContainer {
}
private PluginContainer() {
- // for why we need to do this, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6727821
+ // for why we need to do this, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6727821
try {
Configuration.getConfiguration();
} catch (Throwable t) {
@@ -260,10 +260,10 @@ public class PluginContainer {
/**
* If the plugin container has been initialized, the plugins have started work, and the container is
- * not actively shutting down, this returns <code>true</code>.
- *
+ * not actively shutting down, this returns <code>true</code>.
+ *
* <p>Note! that there is no locking on this method. Therefore it returns quickly and is likely correct, but if
- * called outside of locking the return value is not guaranteed. As such, use this only as a lightweight check.</p>
+ * called outside of locking the return value is not guaranteed. As such, use this only as a lightweight check.</p>
*
* @return <code>true</code> if the plugin container was initialized, started and is not shutting down; <code>false</code> otherwise
*/
@@ -281,14 +281,14 @@ public class PluginContainer {
* <p>If the plugin container has already been initialized, this method does nothing and returns.</p>
*/
public void initialize() {
- // this quick guard is OK but doesn't prevent several calls to initialize() from stacking up while waiting for the lock
+ // this quick guard is OK but doesn't prevent several calls to initialize() from stacking up while waiting for the lock
if (started) {
log.info("Plugin container is already initialized.");
}
Lock lock = obtainWriteLock();
try {
- // this guard prevents us from executing initialize logic multiple times in a row
+ // this guard prevents us from executing initialize logic multiple times in a row
if (started) {
return;
}
@@ -317,7 +317,7 @@ public class PluginContainer {
operationManager = new OperationManager();
resourceFactoryManager = new ResourceFactoryManager();
contentManager = new ContentManager();
- eventManager = new EventManager();
+ eventManager = new EventManager(configuration);
supportManager = new SupportManager();
bundleManager = new BundleManager();
driftManager = new DriftManager();
@@ -358,7 +358,7 @@ public class PluginContainer {
* this method does nothing and returns.
*/
public boolean shutdown() {
- // this quick guard is OK but doesn't prevent several calls to shutdown() from stacking up while waiting for the lock
+ // this quick guard is OK but doesn't prevent several calls to shutdown() from stacking up while waiting for the lock
if (!isRunning()) {
log.info("Plugin container is already shut down.");
}
@@ -367,7 +367,7 @@ public class PluginContainer {
// end up deadlocked.
Lock lock = (configuration.isWaitForShutdownServiceTermination()) ? obtainReadLock() : obtainWriteLock();
try {
- // this guard prevents us from executing shutdown logic multiple times in a row
+ // this guard prevents us from executing shutdown logic multiple times in a row
if (!isRunning()) {
return true;
}
@@ -471,7 +471,7 @@ public class PluginContainer {
Introspector.flushCaches();
LogFactory.releaseAll();
- // for why we need to do this, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6727821
+ // for why we need to do this, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6727821
try {
Configuration.setConfiguration(null);
} catch (Throwable t) {
@@ -740,10 +740,10 @@ public class PluginContainer {
/**
* Add the callback listener to notify when the plugin container is initialized. If this method is invoked and
* the PC is already initialized, then <code>listener</code> will be invoked immediately.
- *
+ *
* @param name associated with the listener
* @param listener The callback object to notify. If a listener with the supplied name is registered, it
- * will be replaced with the newly supplied listner.
+ * will be replaced with the newly supplied listner.
*/
public void addInitializationListener(String name, InitializationListener listener) {
synchronized (initListenersLock) {
@@ -756,10 +756,10 @@ public class PluginContainer {
}
/**
- * Add the callback listener to notify when the plugin container is shutdown. Unlike
- * {@link #addInitializationListener(String, InitializationListener)} the <code>listener</code> will
+ * Add the callback listener to notify when the plugin container is shutdown. Unlike
+ * {@link #addInitializationListener(String, InitializationListener)} the <code>listener</code> will
* not be invoked immediately if the PC is already shutdown. It will only be invoked on future shutdowns.
- *
+ *
* @param name associated with the listener
* @param listener The callback object to notify. If a listener with the supplied name is registered, it
* will be replaced with the newly supplied listener.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
index db8e65d..64bca8b 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
@@ -70,9 +70,13 @@ public class EventManager implements ContainerService {
private Map<PollerKey, Runnable> pollerThreads;
private SigarProxy sigar;
- public void initialize() {
+ public EventManager(PluginContainerConfiguration configuration) {
+ this.pcConfig = configuration;
this.activeReport = new EventReport(this.pcConfig.getEventReportMaxPerSource(), this.pcConfig
.getEventReportMaxTotal());
+ }
+
+ public void initialize() {
// Schedule sender thread(s) to send Event reports to the Server periodically.
EventSenderRunner senderRunner = new EventSenderRunner(this);
@@ -101,7 +105,7 @@ public class EventManager implements ContainerService {
}
public void setConfiguration(PluginContainerConfiguration config) {
- this.pcConfig = config;
+ // Was already passed in the constructor
}
void publishEvents(@NotNull Set<Event> events, @NotNull Resource resource) {
commit 0a87fb1d7e7e1944f574e87990aa5f645e5cddf6
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jun 19 09:40:25 2013 +0200
Add a link to the resource from the alert details view.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDetailsView.java
index d1eb779..68a0953 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDetailsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDetailsView.java
@@ -1,8 +1,7 @@
/*
* RHQ Management Platform
- * Copyright 2010, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.alert;
@@ -47,6 +46,7 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.BookmarkableView;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
+import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.ViewPath;
import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTab;
import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTabSet;
@@ -181,7 +181,8 @@ public class AlertDetailsView extends EnhancedVLayout implements BookmarkableVie
StaticTextItem resourceItem = new StaticTextItem("resourceName",
MSG.view_alert_details_field_watched_resource());
- resourceItem.setValue(record.getAttribute("resourceName"));
+ String resourceUrl = LinkManager.getResourceLink(Integer.parseInt(record.getAttribute("resourceId")));
+ resourceItem.setValue(LinkManager.getHref(resourceUrl, record.getAttribute("resourceName")));
items.add(resourceItem);
StaticTextItem resourceAncestryItem = new StaticTextItem("resourceAncestry",
commit e59e69d4f3f100f9c346dc6e46587e5dc74cb21b
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 19 04:49:09 2013 -0400
fix integration test
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-core/src/test/resources/expected.cassandra.yaml b/modules/common/cassandra-ccm/cassandra-ccm-core/src/test/resources/expected.cassandra.yaml
index 244f6d9..82778c9 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-core/src/test/resources/expected.cassandra.yaml
+++ b/modules/common/cassandra-ccm/cassandra-ccm-core/src/test/resources/expected.cassandra.yaml
@@ -484,18 +484,18 @@ compaction_preheat_key_cache: true
# stream_throughput_outbound_megabits_per_sec: 200
# How long the coordinator should wait for read operations to complete
-read_request_timeout_in_ms: 10000
+read_request_timeout_in_ms: 20000
# How long the coordinator should wait for seq or index scans to complete
-range_request_timeout_in_ms: 10000
+range_request_timeout_in_ms: 20000
# How long the coordinator should wait for writes to complete
-write_request_timeout_in_ms: 10000
+write_request_timeout_in_ms: 20000
# How long the coordinator should wait for truncates to complete
# (This can be much longer, because we need to flush all CFs
# to make sure we can clear out anythink in the commitlog that could
# cause truncated data to reappear.)
truncate_request_timeout_in_ms: 60000
# The default timeout for other, miscellaneous operations
-request_timeout_in_ms: 10000
+request_timeout_in_ms: 20000
# Enable operation timeout information exchange between nodes to accurately
# measure request timeouts, If disabled cassandra will assuming the request
commit fe019d24ded56cb8a10ee03ee8d215f3f8bb073a
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jun 19 05:56:30 2013 +0200
BZ 918051 - Don't allow to pass arbitrary names for the resource.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/lookup/ResourceLookupComboBoxItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/lookup/ResourceLookupComboBoxItem.java
index a96f42a..b321118 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/lookup/ResourceLookupComboBoxItem.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/lookup/ResourceLookupComboBoxItem.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -79,6 +79,7 @@ public class ResourceLookupComboBoxItem extends ComboBoxItem {
setPickListWidth(800);
setTextMatchStyle(TextMatchStyle.SUBSTRING);
setCompleteOnTab(true);
+ setAddUnknownValues(false);
}
}
commit 1e7366008ab319f9770f01e294b111ae10c39b8e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jun 18 21:33:12 2013 +0200
Allow to search for resource types by name
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceTypeHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceTypeHandlerBean.java
index ad1fc3e..e73efbd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceTypeHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceTypeHandlerBean.java
@@ -19,14 +19,20 @@
package org.rhq.enterprise.server.rest;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -35,13 +41,18 @@ import javax.ws.rs.core.UriInfo;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiError;
import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+import org.jboss.resteasy.annotations.GZIP;
import org.jboss.resteasy.annotations.cache.Cache;
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
import org.rhq.enterprise.server.rest.domain.ResourceTypeRest;
+import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
* Deal with resource types
@@ -78,12 +89,7 @@ public class ResourceTypeHandlerBean extends AbstractRestBean {
throw new StuffNotFoundException("Resource type with id " + resourceTypeId);
}
- ResourceTypeRest rtr = new ResourceTypeRest();
- rtr.setId(resourceTypeId);
- rtr.setName(type.getName());
- rtr.setPluginName(type.getPlugin());
- rtr.setCreatePolicy(type.getCreateDeletePolicy());
- rtr.setDataType(type.getCreationDataType());
+ ResourceTypeRest rtr = resourceTypeToResourceTypeRest(type);
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
@@ -94,4 +100,57 @@ public class ResourceTypeHandlerBean extends AbstractRestBean {
}
+
+ @GET @GZIP
+ @Path("/")
+ @ApiOperation(value = "Search for resource types", responseClass = "ResourceTypeRest", multiValueResponse = true)
+ public Response getTypes(@ApiParam("Limit results to param in the resource type name") @QueryParam("q") String name,
+ @ApiParam("Limit results to the plugin with the passed name") @QueryParam("plugin") String pluginName,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @Context UriInfo uriInfo,
+ @Context HttpHeaders headers) {
+
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ if (name!=null) {
+ criteria.addFilterName(name);
+ }
+ if (pluginName!=null) {
+ criteria.addFilterPluginName(pluginName);
+ }
+ PageList<ResourceType> pageList = typeManager.findResourceTypesByCriteria(caller,criteria);
+ List<ResourceTypeRest> rtrList = new ArrayList<ResourceTypeRest>(pageList.size());
+ for (ResourceType type : pageList) {
+ ResourceTypeRest rtr = resourceTypeToResourceTypeRest(type);
+ rtrList.add(rtr);
+ }
+
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder = Response.ok();
+ builder.type(mediaType);
+
+ if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder, uriInfo, pageList, rtrList);
+ } else {
+ GenericEntity<List<ResourceTypeRest>> list = new GenericEntity<List<ResourceTypeRest>>(rtrList) {
+ };
+ builder.entity(list);
+ createPagingHeader(builder,uriInfo,pageList);
+ }
+
+ return builder.build();
+
+ }
+
+ private ResourceTypeRest resourceTypeToResourceTypeRest(ResourceType type) {
+ ResourceTypeRest rtr = new ResourceTypeRest();
+ rtr.setId(type.getId());
+ rtr.setName(type.getName());
+ rtr.setPluginName(type.getPlugin());
+ rtr.setCreatePolicy(type.getCreateDeletePolicy());
+ rtr.setDataType(type.getCreationDataType());
+ return rtr;
+ }
+
+
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index f7b7e48..32c8bce 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -49,6 +49,7 @@ import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.iterableWithSize;
import static org.hamcrest.Matchers.not;
/**
@@ -1008,6 +1009,39 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testTypeByNameAndPlugin() throws Exception {
+
+ given()
+ .header(acceptJson)
+ .queryParam("q","CPU")
+ .queryParam("plugin","Platforms")
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .body("",iterableWithSize(1))
+ .body("[0].name",is("CPU"))
+ .header("X-collection-size",is("1"))
+ .when()
+ .get("/resource/type");
+ }
+
+ @Test
+ public void testTypeByNameAndPlugin2() throws Exception {
+
+ given()
+ .header(acceptJson)
+ .queryParam("q","C P U")
+ .queryParam("plugin","Frobnitz")
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .body("",iterableWithSize(0))
+ .header("X-collection-size",is("0"))
+ .when()
+ .get("/resource/type");
+ }
+
+ @Test
public void testUnknownCreateResourceStatusId() throws Exception {
given()
commit fd82864454a360ced7b7e65a97a35acd39b6eabe
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jun 18 20:56:34 2013 +0200
Add the creation of an overview report.
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 314e228..70f90ae 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -968,6 +968,30 @@
</fileMappers>
</transformationSet>
<transformationSet>
+ <!-- Generate a html renderingof a short form -->
+ <!-- org.rhq.helpers.rest_docs_generator.test plugin wrote to target/docs/xml (see -AtargetDirectory above) -->
+ <dir>target/docs/xml</dir>
+ <includes>
+ <include>rest-api-out.xml</include>
+ </includes>
+ <stylesheet>src/main/xsl/apiout2html_overview.xsl</stylesheet>
+ <parameters>
+ <parameter>
+ <name>basePath</name>
+ <value>http://localhost:7080/rest</value>
+ </parameter>
+ </parameters>
+ <outputDir>${project.build.directory}/docs/html</outputDir>
+ <fileMappers>
+ <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.MergeFileMapper">
+ <targetName>rest-api-overview</targetName>
+ </fileMapper>
+ <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
+ <targetExtension>.html</targetExtension>
+ </fileMapper>
+ </fileMappers>
+ </transformationSet>
+ <transformationSet>
<!-- Generate a docbook file as input to fop -->
<!-- org.rhq.helpers.rest_docs_generator.test plugin wrote to target/docs/xml (see -AtargetDirectory above) -->
<dir>target/docs/xml</dir>
diff --git a/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl b/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
index 0206139..8bfb0a0 100644
--- a/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
+++ b/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
@@ -9,12 +9,13 @@
<xsl:template match="/api">
<html>
<head>
- <title>Api documentation</title>
+ <title>RHQ REST-Api documentation</title>
<style type="text/css">
h2 {background-color:#ADD8E6 }
h3 {background-color:#C0C0C0 }
th {font-weight:bold; font-size:120% }
em {font-style:italic}
+ .exp {background-color:#CC6666 }
</style>
</head>
<body>
@@ -29,8 +30,9 @@
<xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="@path"/></xsl:attribute>
<xsl:call-template name="class-level-path"/>
-
</xsl:element>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@shortDesc"/>
</li>
</xsl:for-each>
</ul>
@@ -59,6 +61,9 @@
<xsl:template match="class">
<xsl:element name="h2">
<xsl:attribute name="id"><xsl:value-of select="@path"/></xsl:attribute>
+ <xsl:if test="contains(@shortDesc,'EXPERIMENT')">
+ <xsl:attribute name="class">exp</xsl:attribute>
+ </xsl:if>
<!--/<xsl:value-of select="@path"/>-->
<xsl:call-template name="class-level-path"/>
<xsl:if test="@shortDesc">
diff --git a/modules/enterprise/server/jar/src/main/xsl/apiout2html_overview.xsl b/modules/enterprise/server/jar/src/main/xsl/apiout2html_overview.xsl
new file mode 100644
index 0000000..77e38b8
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/xsl/apiout2html_overview.xsl
@@ -0,0 +1,101 @@
+<!--
+ Taken from https://github.com/pilhuhn/swagger-core/blob/org.rhq.helpers.rest_docs_ge...
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <xsl:param name="basePath"/>
+ <xsl:strip-space elements="a"/>
+
+ <xsl:template match="/api">
+ <html>
+ <head>
+ <title>RHQ REST-Api overview</title>
+ <style type="text/css">
+ h2 {background-color:#ADD8E6 }
+ h3 {background-color:#C0C0C0 }
+ th {font-weight:bold; font-size:120% }
+ em {font-style:italic}
+ .exp {background-color:#CC6666 }
+ </style>
+ </head>
+ <body>
+ <h1>REST-api documentation</h1>
+ <em>Base path (if not otherwise specified) : <xsl:value-of select="$basePath"/></em>
+ <h2>Table of contents</h2>
+ <ul>
+ <xsl:for-each select="class">
+ <xsl:sort select="@basePath"/>
+ <xsl:sort select="@path"/>
+ <li>
+ <xsl:element name="a">
+ <xsl:attribute name="href">#<xsl:value-of select="@path"/></xsl:attribute>
+ <xsl:call-template name="class-level-path"/>
+ </xsl:element>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@shortDesc"/>
+ </li>
+ </xsl:for-each>
+ </ul>
+ <xsl:apply-templates>
+ <xsl:sort select="@basePath"/>
+ <xsl:sort select="@path"/>
+ </xsl:apply-templates>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template name="class-level-path">
+ <xsl:choose>
+ <xsl:when test="@basePath">
+ <xsl:value-of select="@basePath"/>
+ <xsl:if test="not(substring(@basePath,string-length(@basePath)-1)='/')">/</xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$basePath"/>
+ <xsl:if test="not(substring($basePath,string-length($basePath)-1)='/')">/</xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:value-of select="@path"/>
+ </xsl:template>
+
+ <xsl:template match="class">
+ <xsl:element name="h2">
+ <xsl:attribute name="id"><xsl:value-of select="@path"/></xsl:attribute>
+ <xsl:if test="contains(@shortDesc,'EXPERIMENT')">
+ <xsl:attribute name="class">exp</xsl:attribute>
+ </xsl:if>
+ <!--/<xsl:value-of select="@path"/>-->
+ <xsl:call-template name="class-level-path"/>
+ <xsl:if test="@shortDesc">
+ : <xsl:value-of select="@shortDesc"/>
+ </xsl:if>
+ </xsl:element>
+ <em><xsl:value-of select="@description"/></em>
+ <br/>
+ <xsl:if test="method">
+ <xsl:apply-templates>
+ <xsl:sort select="@path"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <p/>
+ </xsl:template>
+
+ <xsl:template match="method">
+ <h3><xsl:value-of select="@method"/><xsl:text xml:space="preserve"> /</xsl:text><xsl:value-of select="../@path"/>
+ <xsl:if test="not(@path = '')">/</xsl:if><xsl:value-of select="@path"/>
+ </h3>
+ <em><xsl:value-of select="@description"/></em>
+ <br/>
+
+ </xsl:template>
+
+ <xsl:template match="param">
+ </xsl:template>
+
+ <xsl:template match="error">
+ </xsl:template>
+
+ <xsl:template match="produces">
+ </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
commit a6d5f0b776fb98eb38c2a9201b224417899dbcc2
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Jun 18 16:09:44 2013 -0400
increase default timeouts for read, write, and range requests
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/bundle/cassandra/conf/rhq.cassandra.yaml b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/bundle/cassandra/conf/rhq.cassandra.yaml
index 977a108..bae3ecc 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/bundle/cassandra/conf/rhq.cassandra.yaml
+++ b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/bundle/cassandra/conf/rhq.cassandra.yaml
@@ -484,18 +484,18 @@ compaction_preheat_key_cache: true
# stream_throughput_outbound_megabits_per_sec: 200
# How long the coordinator should wait for read operations to complete
-read_request_timeout_in_ms: 10000
+read_request_timeout_in_ms: 20000
# How long the coordinator should wait for seq or index scans to complete
-range_request_timeout_in_ms: 10000
+range_request_timeout_in_ms: 20000
# How long the coordinator should wait for writes to complete
-write_request_timeout_in_ms: 10000
+write_request_timeout_in_ms: 20000
# How long the coordinator should wait for truncates to complete
# (This can be much longer, because we need to flush all CFs
# to make sure we can clear out anythink in the commitlog that could
# cause truncated data to reappear.)
truncate_request_timeout_in_ms: 60000
# The default timeout for other, miscellaneous operations
-request_timeout_in_ms: 10000
+request_timeout_in_ms: 20000
# Enable operation timeout information exchange between nodes to accurately
# measure request timeouts, If disabled cassandra will assuming the request
commit 32fcb18435a54df98e7c3807bbb8165b9747112c
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Jun 18 16:01:32 2013 -0400
replacing CassandraClusterHeartBeatJob with StorageClusterHeartBeatJob
CassandraClusterHeartBeatJob was a Quartz job and would only run on a single
server in an HA deployment. We want the checks it performs to run on each
server. StorageClusterHeartBeatJob provides the same functionality but is
implemented as an EJB timer.
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java
index 606fcbf..4cc67c0 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java
@@ -60,7 +60,7 @@ import org.rhq.core.domain.resource.Agent;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.drift.DriftServerPluginService;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementOOBManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementOOBManagerBeanTest.java
index 3ed0f3f..fe922bb 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementOOBManagerBeanTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementOOBManagerBeanTest.java
@@ -55,7 +55,7 @@ import org.rhq.core.domain.resource.Agent;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.util.jdbc.JDBCUtil;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.drift.DriftServerPluginService;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java
index d1c897a..49048ee 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java
@@ -45,7 +45,7 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementOOBManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
index 846bc74..2e654ab 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
@@ -32,7 +32,7 @@ import javax.persistence.PersistenceContext;
import org.rhq.core.domain.cloud.Server;
import org.rhq.core.domain.cloud.StorageNode;
import org.rhq.enterprise.server.RHQConstants;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.core.StartupBean;
import org.rhq.enterprise.server.naming.NamingHack;
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBeanPreparation.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBeanPreparation.java
index a2e6b74..c272afe 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBeanPreparation.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBeanPreparation.java
@@ -69,7 +69,7 @@ public class StrippedDownStartupBeanPreparation {
}
/**
- * The storage client initialization performed by {@link org.rhq.enterprise.server.cassandra.StorageClientManagerBean#init()}
+ * The storage client initialization performed by {@link org.rhq.enterprise.server.storage.StorageClientManagerBean#init()}
* requires having a server entity in the database which will be the case with a regular deployment. This method
* persists a server before any tests execute. If the server entity does not exist or cannot be loaded, then the
* storage client will not initialize properly and any tests that depend on the storage client will fail.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/CassandraClusterHeartBeatJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/CassandraClusterHeartBeatJob.java
deleted file mode 100644
index 86d8ec9..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/CassandraClusterHeartBeatJob.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *
- * * RHQ Management Platform
- * * Copyright (C) 2005-2012 Red Hat, Inc.
- * * All rights reserved.
- * *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License, version 2, as
- * * published by the Free Software Foundation, and/or the GNU Lesser
- * * General Public License, version 2.1, also as published by the Free
- * * Software Foundation.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License and the GNU Lesser General Public License
- * * for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * and the GNU Lesser General Public License along with this program;
- * * if not, write to the Free Software Foundation, Inc.,
- * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-package org.rhq.enterprise.server.cassandra;
-
-import static org.rhq.core.domain.cloud.Server.OperationMode.MAINTENANCE;
-import static org.rhq.core.domain.cloud.Server.OperationMode.NORMAL;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.quartz.Job;
-import org.quartz.JobDataMap;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-
-import org.rhq.cassandra.ClusterInitService;
-import org.rhq.core.domain.cloud.Server;
-import org.rhq.core.domain.cloud.Server.OperationMode;
-import org.rhq.core.domain.cloud.StorageNode;
-import org.rhq.enterprise.server.auth.SubjectManagerLocal;
-import org.rhq.enterprise.server.cloud.TopologyManagerLocal;
-import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
-import org.rhq.enterprise.server.util.LookupUtil;
-
-/**
- * @author John Sanda
- */
-public class CassandraClusterHeartBeatJob implements Job {
-
- public static final String JOB_NAME = CassandraClusterHeartBeatJob.class.getSimpleName();
- public static final String KEY_CONNECTION_TIMEOUT = "rhq.cassandra.connection.timeout";
- public static final String KEY_CASSANDRA_HOSTS = "rhq.cassandra.hosts";
-
- private final Log log = LogFactory.getLog(CassandraClusterHeartBeatJob.class);
-
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- ClusterInitService clusterInitService = new ClusterInitService();
- Server rhqServer = getRhqServer();
- JobDataMap dataMap = context.getMergedJobDataMap();
- String hosts = (String) dataMap.get(KEY_CASSANDRA_HOSTS);
- int timeout = Integer.parseInt((String) dataMap.get(KEY_CONNECTION_TIMEOUT));
- List<StorageNode> cassandraHosts = new ArrayList<StorageNode>();
-
- for (String s : hosts.split(",")) {
- StorageNode storageNode = new StorageNode();
- storageNode.parseNodeInformation(s);
- cassandraHosts.add(storageNode);
-
- }
- boolean pingable = clusterInitService.ping(cassandraHosts, 1);
- if (pingable) {
- if (rhqServer.getOperationMode() != NORMAL) {
- changeServerMode(rhqServer, NORMAL);
- log.info("Restarting storage client subsystem...");
- StorageClientManagerBean storageClientManager = getStorageClientManager();
- storageClientManager.init();
- }
- return;
- }
-
- if (log.isWarnEnabled()) {
- log.warn(rhqServer + " is unable to connect to any Cassandra node. Server will go into maintenance mode.");
- }
- changeServerMode(rhqServer, MAINTENANCE);
- log.info("Preparing to shut down storage client subsystem");
- StorageClientManagerBean storageClientManager = getStorageClientManager();
- storageClientManager.shutdown();
- }
-
- private Server getRhqServer() {
- ServerManagerLocal serverManager = LookupUtil.getServerManager();
- return serverManager.getServer();
- }
-
- private void changeServerMode(Server rhqServer, OperationMode mode) {
- if (rhqServer.getOperationMode() == mode) {
- return;
- }
-
- if (log.isInfoEnabled()) {
- log.info("Moving " + rhqServer + " from " + rhqServer.getOperationMode() + " to " + mode);
- }
- TopologyManagerLocal rhqClusterManager = LookupUtil.getTopologyManager();
- SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
- rhqClusterManager.updateServerMode(subjectManager.getOverlord(), new Integer[] {rhqServer.getId()}, mode);
- }
-
- private StorageClientManagerBean getStorageClientManager() {
- try {
- return (StorageClientManagerBean) new InitialContext().lookup(
- "java:global/rhq/rhq-enterprise-server-ejb3/" + StorageClientManagerBean.class.getSimpleName());
- } catch (NamingException e) {
- String msg = "Unable to access " + StorageClientManagerBean.class + " due to JNDI error. You may " +
- "need to restart the server so that the storage client subsystem can be reinitialized.";
- log.error(msg, e);
- throw new RuntimeException(msg, e);
- }
- }
-
- private void logException(String msg, Exception e) {
- if (log.isDebugEnabled()) {
- log.debug(msg, e);
- } else if (log.isInfoEnabled()) {
- log.info(msg + ": " + e.getMessage());
- } else {
- log.warn(msg);
- }
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/StorageClientManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/StorageClientManagerBean.java
deleted file mode 100644
index c84f6dc..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cassandra/StorageClientManagerBean.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- *
- * * RHQ Management Platform
- * * Copyright (C) 2005-2012 Red Hat, Inc.
- * * All rights reserved.
- * *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License, version 2, as
- * * published by the Free Software Foundation, and/or the GNU Lesser
- * * General Public License, version 2.1, also as published by the Free
- * * Software Foundation.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License and the GNU Lesser General Public License
- * * for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * and the GNU Lesser General Public License along with this program;
- * * if not, write to the Free Software Foundation, Inc.,
- * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-package org.rhq.enterprise.server.cassandra;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.ejb.ConcurrencyManagement;
-import javax.ejb.ConcurrencyManagementType;
-import javax.ejb.EJB;
-import javax.ejb.Singleton;
-
-import com.datastax.driver.core.Cluster;
-import com.datastax.driver.core.ProtocolOptions;
-import com.datastax.driver.core.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.rhq.cassandra.util.ClusterBuilder;
-import org.rhq.core.domain.cloud.Server;
-import org.rhq.core.domain.cloud.StorageNode;
-import org.rhq.core.util.StringUtil;
-import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal;
-import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
-import org.rhq.server.metrics.DateTimeService;
-import org.rhq.server.metrics.MetricsConfiguration;
-import org.rhq.server.metrics.MetricsDAO;
-import org.rhq.server.metrics.MetricsServer;
-
-/**
- * @author John Sanda
- */
-@Singleton
-(a)ConcurrencyManagement(ConcurrencyManagementType.BEAN)
-public class StorageClientManagerBean {
-
- private final Log log = LogFactory.getLog(StorageClientManagerBean.class);
-
- private static final String USERNAME_PROP = "rhq.cassandra.username";
- private static final String PASSWORD_PROP = "rhq.cassandra.password";
- private static final String RHQ_KEYSPACE = "rhq";
-
- @EJB
- private ServerManagerLocal serverManager;
-
- @EJB
- private StorageNodeManagerLocal storageNodeManager;
-
- private Session session;
- private MetricsConfiguration metricsConfiguration;
- private MetricsDAO metricsDAO;
- private MetricsServer metricsServer;
- private boolean initialized;
-
- public synchronized void init() {
- if (initialized) {
- if (log.isDebugEnabled()) {
- log.debug("Storage client subsystem is already initialized. Skipping initialization.");
- }
- return;
- }
-
- log.info("Initializing storage client subsystem");
-
- //decide if there are no storage nodes persisted before doing anything
- boolean isNewServerInstall = storageNodeManager.getStorageNodes().isEmpty();
-
- storageNodeManager.scanForStorageNodes();
-
- String username = getRequiredStorageProperty(USERNAME_PROP);
- String password = getRequiredStorageProperty(PASSWORD_PROP);
-
- metricsConfiguration = new MetricsConfiguration();
- session = createSession(username, password, storageNodeManager.getStorageNodes());
- metricsDAO = new MetricsDAO(session, metricsConfiguration);
-
- Server server = serverManager.getServer();
- initMetricsServer(isNewServerInstall, server.getCtime());
-
- initialized = true;
- log.info("Storage client subsystem is now initialized");
- }
-
- public synchronized void shutdown() {
- if (!initialized) {
- log.info("Storage client subsystem is already shut down. Skipping shutdown steps.");
- return;
- }
-
- log.info("Shutting down storage client subsystem");
- metricsServer.shutdown();
- metricsDAO = null;
- metricsServer = null;
- session.getCluster().shutdown();
- session = null;
- initialized = false;
- }
-
- public MetricsDAO getMetricsDAO() {
- return this.metricsDAO;
- }
-
- public MetricsServer getMetricsServer() {
- return this.metricsServer;
- }
-
- public Session getSession() {
- return this.session;
- }
-
- public MetricsConfiguration getMetricsConfiguration() {
- return this.metricsConfiguration;
- }
-
- private Session createSession(String username, String password, List<StorageNode> storageNodes) {
- if (log.isDebugEnabled()) {
- log.debug("Initializing session to connect to storage node cluster");
- }
- List<String> hostNames = new ArrayList<String>();
- for (StorageNode storageNode : storageNodes) {
- hostNames.add(storageNode.getAddress());
- }
- int port = storageNodes.get(0).getCqlPort();
-
- boolean compressionEnabled = Boolean.valueOf(System.getProperty("rhq.cassandra.client.compression-enabled",
- "false"));
- ProtocolOptions.Compression compression;
- if (compressionEnabled) {
- compression = ProtocolOptions.Compression.SNAPPY;
- log.info("Compression has been enabled for the storage client. Be aware that if your storage nodes do " +
- "not support compression then the client will not be able to connect to the storage cluster.");
- } else {
- compression = ProtocolOptions.Compression.NONE;
- log.debug("Storage client compression is disabled");
- }
-
- Cluster cluster = new ClusterBuilder()
- .addContactPoints(hostNames.toArray(new String[hostNames.size()]))
- .withCredentials(username, password)
- .withPort(port)
- .withCompression(compression)
- .build();
-
- return cluster.connect(RHQ_KEYSPACE);
- }
-
- private void initMetricsServer(boolean isNewInstall, long serverInstallTime) {
- if (log.isDebugEnabled()) {
- log.debug("Initializing " + MetricsServer.class.getName());
- }
- metricsServer = new MetricsServer();
- metricsServer.setDAO(metricsDAO);
- metricsServer.setConfiguration(metricsConfiguration);
-
- DateTimeService dateTimeService = new DateTimeService();
- dateTimeService.setConfiguration(metricsConfiguration);
- metricsServer.setDateTimeService(dateTimeService);
- metricsServer.init(isNewInstall, serverInstallTime);
- }
-
- private String getRequiredStorageProperty(String property) {
- String value = System.getProperty(property);
- if (StringUtil.isEmpty(property)) {
- throw new IllegalStateException("The system property [" + property + "] is not set. The RHQ "
- + "server will not be able connect to the RHQ storage node(s). This property should be defined "
- + "in rhq-server.properties.");
- }
- return value;
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index cebc826..9d6cb6a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -28,7 +28,6 @@ import java.sql.Connection;
import java.util.Date;
import java.util.List;
import java.util.Properties;
-import java.util.UUID;
import javax.annotation.Resource;
import javax.ejb.ConcurrencyManagement;
@@ -49,7 +48,6 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.quartz.JobDataMap;
import org.quartz.SchedulerException;
import org.rhq.core.db.DatabaseTypeFactory;
@@ -67,8 +65,7 @@ import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.engine.internal.AlertConditionCacheCoordinator;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
-import org.rhq.enterprise.server.cassandra.CassandraClusterHeartBeatJob;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.cloud.TopologyManagerLocal;
import org.rhq.enterprise.server.cloud.instance.CacheConsistencyManagerLocal;
import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
@@ -93,6 +90,7 @@ import org.rhq.enterprise.server.scheduler.jobs.PurgePluginsJob;
import org.rhq.enterprise.server.scheduler.jobs.PurgeResourceTypesJob;
import org.rhq.enterprise.server.scheduler.jobs.SavedSearchResultCountRecalculationJob;
import org.rhq.enterprise.server.scheduler.jobs.StorageNodeMaintenanceJob;
+import org.rhq.enterprise.server.storage.StorageClusterHeartBeatJob;
import org.rhq.enterprise.server.system.SystemManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.concurrent.AlertSerializer;
@@ -146,6 +144,9 @@ public class StartupBean implements StartupLocal {
@EJB
private StorageClientManagerBean storageClientManager;
+ @EJB
+ private StorageClusterHeartBeatJob storageClusterHeartBeatJob;
+
@Resource
private TimerService timerService; // needed to schedule our plugin scanner
@@ -450,6 +451,7 @@ public class StartupBean implements StartupLocal {
}
storageClientManager.init();
+ storageClusterHeartBeatJob.scheduleJob();
}
/**
@@ -665,33 +667,9 @@ public class StartupBean implements StartupLocal {
log.error("Cannot create alert availability duration job.", e);
}
- scheduleCassandraClusterHeartBeatJob();
-
return;
}
- private void scheduleCassandraClusterHeartBeatJob() {
- String seeds = System.getProperty("rhq.cassandra.seeds");
- if (seeds != null) {
- seeds = seeds.replaceAll(";", ",");
- }
- String jobTrigger = "CassandraClusterHeartBeatTrigger - " + UUID.randomUUID().toString();
- String jobGroup = CassandraClusterHeartBeatJob.JOB_NAME + "Group";
-
- JobDataMap jobDataMap = new JobDataMap();
- jobDataMap.put(CassandraClusterHeartBeatJob.KEY_CONNECTION_TIMEOUT, "100");
- jobDataMap.put(CassandraClusterHeartBeatJob.KEY_CASSANDRA_HOSTS, seeds);
-
- try {
- schedulerBean.scheduleRepeatingJob(CassandraClusterHeartBeatJob.JOB_NAME, jobGroup, jobDataMap,
- CassandraClusterHeartBeatJob.class, true, false, 3000, 1000 * 60);
- } catch (SchedulerException e) {
- String msg = "Unable to schedule " + CassandraClusterHeartBeatJob.class.getSimpleName() + " job. The "
- + "server will reamin in maintenance mode without a manual override.";
- log.error(msg, e);
- }
- }
-
/**
* This seeds the agent clients cache with clients for all known agents. These clients will be started so they can
* immediately begin to send any persisted guaranteed messages that might already exist. This method must be called
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java
index 990e510..90ac6e7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java
@@ -48,7 +48,7 @@ import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.PermissionException;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.cloud.StatusManagerLocal;
import org.rhq.enterprise.server.measurement.instrumentation.MeasurementMonitor;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
index bab39fb..90ed917 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
@@ -90,7 +90,7 @@ import org.rhq.enterprise.server.alert.engine.AlertConditionCacheManagerLocal;
import org.rhq.enterprise.server.alert.engine.AlertConditionCacheStats;
import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.PermissionException;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.core.AgentManagerLocal;
import org.rhq.enterprise.server.measurement.instrumentation.MeasurementMonitor;
import org.rhq.enterprise.server.measurement.util.MeasurementDataManagerUtility;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MetricsManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MetricsManagerBean.java
index 8808514..d4ecc02 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MetricsManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MetricsManagerBean.java
@@ -36,7 +36,7 @@ import javax.ejb.TransactionAttributeType;
import org.rhq.core.domain.measurement.MeasurementAggregate;
import org.rhq.core.domain.measurement.MeasurementDataNumeric;
import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.server.metrics.MetricsServer;
import org.rhq.server.metrics.domain.AggregateNumericMetric;
import org.rhq.server.metrics.domain.RawNumericMetric;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 85350d0..d5ca8dc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -80,7 +80,7 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.enterprise.server.RHQConstants;
-import org.rhq.enterprise.server.cassandra.StorageClientManagerBean;
+import org.rhq.enterprise.server.storage.StorageClientManagerBean;
import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java
new file mode 100644
index 0000000..0c76dee
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java
@@ -0,0 +1,194 @@
+/*
+ *
+ * * RHQ Management Platform
+ * * Copyright (C) 2005-2012 Red Hat, Inc.
+ * * All rights reserved.
+ * *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License, version 2, as
+ * * published by the Free Software Foundation, and/or the GNU Lesser
+ * * General Public License, version 2.1, also as published by the Free
+ * * Software Foundation.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License and the GNU Lesser General Public License
+ * * for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * and the GNU Lesser General Public License along with this program;
+ * * if not, write to the Free Software Foundation, Inc.,
+ * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+package org.rhq.enterprise.server.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.ConcurrencyManagement;
+import javax.ejb.ConcurrencyManagementType;
+import javax.ejb.EJB;
+import javax.ejb.Singleton;
+
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.ProtocolOptions;
+import com.datastax.driver.core.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.cassandra.util.ClusterBuilder;
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.core.domain.cloud.StorageNode;
+import org.rhq.core.util.StringUtil;
+import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal;
+import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
+import org.rhq.server.metrics.DateTimeService;
+import org.rhq.server.metrics.MetricsConfiguration;
+import org.rhq.server.metrics.MetricsDAO;
+import org.rhq.server.metrics.MetricsServer;
+
+/**
+ * @author John Sanda
+ */
+@Singleton
+(a)ConcurrencyManagement(ConcurrencyManagementType.BEAN)
+public class StorageClientManagerBean {
+
+ private final Log log = LogFactory.getLog(StorageClientManagerBean.class);
+
+ private static final String USERNAME_PROP = "rhq.cassandra.username";
+ private static final String PASSWORD_PROP = "rhq.cassandra.password";
+ private static final String RHQ_KEYSPACE = "rhq";
+
+ @EJB
+ private ServerManagerLocal serverManager;
+
+ @EJB
+ private StorageNodeManagerLocal storageNodeManager;
+
+ private Session session;
+ private MetricsConfiguration metricsConfiguration;
+ private MetricsDAO metricsDAO;
+ private MetricsServer metricsServer;
+ private boolean initialized;
+
+ public synchronized void init() {
+ if (initialized) {
+ if (log.isDebugEnabled()) {
+ log.debug("Storage client subsystem is already initialized. Skipping initialization.");
+ }
+ return;
+ }
+
+ log.info("Initializing storage client subsystem");
+
+ //decide if there are no storage nodes persisted before doing anything
+ boolean isNewServerInstall = storageNodeManager.getStorageNodes().isEmpty();
+
+ storageNodeManager.scanForStorageNodes();
+
+ String username = getRequiredStorageProperty(USERNAME_PROP);
+ String password = getRequiredStorageProperty(PASSWORD_PROP);
+
+ metricsConfiguration = new MetricsConfiguration();
+ session = createSession(username, password, storageNodeManager.getStorageNodes());
+ metricsDAO = new MetricsDAO(session, metricsConfiguration);
+
+ Server server = serverManager.getServer();
+ initMetricsServer(isNewServerInstall, server.getCtime());
+
+ initialized = true;
+ log.info("Storage client subsystem is now initialized");
+ }
+
+ public synchronized void shutdown() {
+ if (!initialized) {
+ log.info("Storage client subsystem is already shut down. Skipping shutdown steps.");
+ return;
+ }
+
+ log.info("Shutting down storage client subsystem");
+ metricsServer.shutdown();
+ metricsDAO = null;
+ metricsServer = null;
+ session.getCluster().shutdown();
+ session = null;
+ initialized = false;
+ }
+
+ public MetricsDAO getMetricsDAO() {
+ return this.metricsDAO;
+ }
+
+ public MetricsServer getMetricsServer() {
+ return this.metricsServer;
+ }
+
+ public Session getSession() {
+ return this.session;
+ }
+
+ public MetricsConfiguration getMetricsConfiguration() {
+ return this.metricsConfiguration;
+ }
+
+ private Session createSession(String username, String password, List<StorageNode> storageNodes) {
+ if (log.isDebugEnabled()) {
+ log.debug("Initializing session to connect to storage node cluster");
+ }
+ List<String> hostNames = new ArrayList<String>();
+ for (StorageNode storageNode : storageNodes) {
+ hostNames.add(storageNode.getAddress());
+ }
+ int port = storageNodes.get(0).getCqlPort();
+
+ boolean compressionEnabled = Boolean.valueOf(System.getProperty("rhq.cassandra.client.compression-enabled",
+ "false"));
+ ProtocolOptions.Compression compression;
+ if (compressionEnabled) {
+ compression = ProtocolOptions.Compression.SNAPPY;
+ log.info("Compression has been enabled for the storage client. Be aware that if your storage nodes do " +
+ "not support compression then the client will not be able to connect to the storage cluster.");
+ } else {
+ compression = ProtocolOptions.Compression.NONE;
+ log.debug("Storage client compression is disabled");
+ }
+
+ Cluster cluster = new ClusterBuilder()
+ .addContactPoints(hostNames.toArray(new String[hostNames.size()]))
+ .withCredentials(username, password)
+ .withPort(port)
+ .withCompression(compression)
+ .build();
+
+ return cluster.connect(RHQ_KEYSPACE);
+ }
+
+ private void initMetricsServer(boolean isNewInstall, long serverInstallTime) {
+ if (log.isDebugEnabled()) {
+ log.debug("Initializing " + MetricsServer.class.getName());
+ }
+ metricsServer = new MetricsServer();
+ metricsServer.setDAO(metricsDAO);
+ metricsServer.setConfiguration(metricsConfiguration);
+
+ DateTimeService dateTimeService = new DateTimeService();
+ dateTimeService.setConfiguration(metricsConfiguration);
+ metricsServer.setDateTimeService(dateTimeService);
+ metricsServer.init(isNewInstall, serverInstallTime);
+ }
+
+ private String getRequiredStorageProperty(String property) {
+ String value = System.getProperty(property);
+ if (StringUtil.isEmpty(property)) {
+ throw new IllegalStateException("The system property [" + property + "] is not set. The RHQ "
+ + "server will not be able connect to the RHQ storage node(s). This property should be defined "
+ + "in rhq-server.properties.");
+ }
+ return value;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterHeartBeatJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterHeartBeatJob.java
new file mode 100644
index 0000000..6f58a06
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterHeartBeatJob.java
@@ -0,0 +1,126 @@
+package org.rhq.enterprise.server.storage;
+
+import static org.rhq.core.domain.cloud.Server.OperationMode.MAINTENANCE;
+import static org.rhq.core.domain.cloud.Server.OperationMode.NORMAL;
+
+import java.util.List;
+
+import javax.annotation.Resource;
+import javax.ejb.EJB;
+import javax.ejb.Singleton;
+import javax.ejb.Timeout;
+import javax.ejb.TimerConfig;
+import javax.ejb.TimerService;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.cassandra.ClusterInitService;
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.core.domain.cloud.StorageNode;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal;
+import org.rhq.enterprise.server.cloud.TopologyManagerLocal;
+import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
+
+/**
+ * This job runs periodically to verify that the server can connect to the storage cluster.
+ * If the server cannot connect to any nodes in the cluster, the server will be put into
+ * maintenance mode until it is able to connect to the cluster. See
+ * {@link #checkClusterHeartBeat()} for more details.
+ *
+ * @author John Sanda
+ */
+@Singleton
+public class StorageClusterHeartBeatJob {
+
+ private final Log log = LogFactory.getLog(StorageClusterHeartBeatJob.class);
+
+ @EJB
+ private ServerManagerLocal serverManager;
+
+ @EJB
+ private StorageNodeManagerLocal storageNodeManager;
+
+ @EJB
+ private TopologyManagerLocal topologyManager;
+
+ @EJB
+ private SubjectManagerLocal subjectManager;
+
+ @EJB
+ private StorageClientManagerBean storageClientManager;
+
+ @Resource
+ private TimerService timerService;
+
+ public void scheduleJob() {
+ long initialDelay = 3000;
+ long interval = 1000 * 60;
+
+ timerService.createIntervalTimer(initialDelay, interval, new TimerConfig(null, false));
+ }
+
+ /**
+ * <p>
+ * Runs periodically to verify that the server can connect to the storage cluster. If
+ * the server cannot connect to any nodes in the cluster, the server will be put into
+ * maintenance mode until a connection can be made to the cluster.
+ * </p>
+ * <p>
+ * While client requests are made using CQL commands going over the native transport
+ * layer introduced in Cassandra 1.2, connectivity is checked via JMX. The JMX call
+ * is made to determine whether or not the native transport is running. Trying to do
+ * the check using the CQL driver gets complicated and introduces some non-trivial
+ * overhead due to the fact that the driver is async.
+ * </p>
+ */
+ @Timeout
+ public void checkClusterHeartBeat() {
+ ClusterInitService clusterInitService = new ClusterInitService();
+ Server server = serverManager.getServer();
+ List<StorageNode> storageNodes = storageNodeManager.getStorageNodes();
+
+ if (storageNodes.isEmpty()) {
+ log.error("No storage nodes were found in the RHQ database. If this is your only RHQ server make sure " +
+ "that the rhq.cassandra.seeds property in <rhq-server-basedir>/bin/rhq-server.properties is " +
+ "properly configured. If you edit this property, you will have to restart the server for the change " +
+ "to take effect. The server will now go into maintenance mode since connectivity to storage " +
+ "nodes cannot be verified.");
+ putServerInMaintenanceMode(server);
+ } else {
+ boolean pingable = clusterInitService.ping(storageNodes, 1);
+ if (pingable) {
+ if (server.getOperationMode() != NORMAL) {
+ changeServerMode(server, NORMAL);
+ log.info("Restarting storage client subsystem...");
+ storageClientManager.init();
+ }
+ return;
+ }
+
+ if (log.isWarnEnabled()) {
+ log.warn(server + " is unable to connect to any Cassandra node. Server will go into maintenance mode.");
+ }
+ putServerInMaintenanceMode(server);
+ }
+ }
+
+ private void putServerInMaintenanceMode(Server rhqServer) {
+ changeServerMode(rhqServer, MAINTENANCE);
+ log.info("Preparing to shut down storage client subsystem");
+ storageClientManager.shutdown();
+ }
+
+ private void changeServerMode(Server rhqServer, Server.OperationMode mode) {
+ if (rhqServer.getOperationMode() == mode) {
+ return;
+ }
+
+ if (log.isInfoEnabled()) {
+ log.info("Moving " + rhqServer + " from " + rhqServer.getOperationMode() + " to " + mode);
+ }
+ topologyManager.updateServerMode(subjectManager.getOverlord(), new Integer[] {rhqServer.getId()}, mode);
+ }
+
+}
commit 72f114cb01f3286696be68912280906b1954febe
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Jun 18 15:59:02 2013 -0400
Fix upgrade issues
- fix agent upgrade of existing agent in the default location
(i.e. no --from-agent-dir specified)
- On Windows, ensure exit codes are passed back from the storage installer
and rhqctl scripts. The former is very important as otherwise errors
in the storage installer do not prevent an attempt to upgrade/install the
server.
diff --git a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
index 3e6c7e8..5c99b89 100644
--- a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
+++ b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
@@ -176,37 +176,26 @@ public class StorageInstaller {
Option basedirOption = new Option(null, "dir", true, "The directory where the storage node will be installed "
+ "The default directory will be " + storageBasedir);
- Option heapSizeOption = new Option(null, "heap-size", true, "The value to use for both the min and max heap. " +
- "This value is passed directly to the -Xms and -Xmx options of the Java executable. Defaults to " +
- defaultHeapSize);
+ Option heapSizeOption = new Option(null, "heap-size", true, "The value to use for both the min and max heap. "
+ + "This value is passed directly to the -Xms and -Xmx options of the Java executable. Defaults to "
+ + defaultHeapSize);
- Option heapNewSizeOption = new Option(null, "heap-new-size", true, "The value to use for the new generation " +
- "of the heap. This value is passed directly to the -Xmn option of the Java executable. Defaults to " +
- defaultHeapNewSize);
+ Option heapNewSizeOption = new Option(null, "heap-new-size", true, "The value to use for the new generation "
+ + "of the heap. This value is passed directly to the -Xmn option of the Java executable. Defaults to "
+ + defaultHeapNewSize);
- Option stackSizeOption = new Option(null, "stack-size", true, "The value to use for the thread stack size. " +
- "This value is passed directly to the -Xss option of the Java executable.");
+ Option stackSizeOption = new Option(null, "stack-size", true, "The value to use for the thread stack size. "
+ + "This value is passed directly to the -Xss option of the Java executable.");
- Option upgradeOption = new Option(null, "upgrade", true, "Upgrades an existing storage node. The directory " +
- "where the existing RHQ server is installed.");
+ Option upgradeOption = new Option(null, "upgrade", true, "Upgrades an existing storage node. The directory "
+ + "where the existing RHQ server is installed.");
upgradeOption.setArgName("RHQ_SERVER_DIR");
- options = new Options().addOption(new Option("h", "help", false, "Show this message."))
- .addOption(hostname)
- .addOption(seeds)
- .addOption(jmxPortOption)
- .addOption(startOption)
- .addOption(checkStatus)
- .addOption(commitLogOption)
- .addOption(dataDirOption)
- .addOption(savedCachesDirOption)
- .addOption(nativeTransportPortOption)
- .addOption(storagePortOption)
- .addOption(sslStoragePortOption)
- .addOption(basedirOption)
- .addOption(heapSizeOption)
- .addOption(heapNewSizeOption)
- .addOption(stackSizeOption)
+ options = new Options().addOption(new Option("h", "help", false, "Show this message.")).addOption(hostname)
+ .addOption(seeds).addOption(jmxPortOption).addOption(startOption).addOption(checkStatus)
+ .addOption(commitLogOption).addOption(dataDirOption).addOption(savedCachesDirOption)
+ .addOption(nativeTransportPortOption).addOption(storagePortOption).addOption(sslStoragePortOption)
+ .addOption(basedirOption).addOption(heapSizeOption).addOption(heapNewSizeOption).addOption(stackSizeOption)
.addOption(upgradeOption);
}
@@ -227,15 +216,15 @@ public class StorageInstaller {
File upgradeFromDir = new File(cmdLine.getOptionValue("upgrade", ""));
if (!upgradeFromDir.isDirectory()) {
- log.error("The value passed to the upgrade option is not a directory. The value must be a valid " +
- "path that points to the base directory of an existing RHQ server installation.");
+ log.error("The value passed to the upgrade option is not a directory. The value must be a valid "
+ + "path that points to the base directory of an existing RHQ server installation.");
return STATUS_INVALID_UPGRADE;
}
existingStorageDir = new File(upgradeFromDir, "rhq-storage");
if (!(existingStorageDir.exists() && existingStorageDir.isDirectory())) {
- log.error(existingStorageDir + " does not appear to be an existing RHQ storage node installtion. " +
- "Check the value that was passed to the upgrade option and make sure it specifies the base " +
- "directory of an existing RHQ server installation.");
+ log.error(existingStorageDir + " does not appear to be an existing RHQ storage node installtion. "
+ + "Check the value that was passed to the upgrade option and make sure it specifies the base "
+ + "directory of an existing RHQ server installation.");
return STATUS_INVALID_UPGRADE;
}
@@ -303,18 +292,24 @@ public class StorageInstaller {
commitLogDir = cmdLine.getOptionValue("commitlog", commitLogDir);
dataDir = cmdLine.getOptionValue("data", dataDir);
savedCachesDir = cmdLine.getOptionValue("saved-caches", savedCachesDir);
-
- // validate the three data directories are empty - if they are not, we are probably stepping on another storage node
- if (!isDirectoryEmpty(new File(commitLogDir))) {
- log.error("Commitlog directory is not empty: " + commitLogDir);
+ File commitLogDirFile = new File(commitLogDir);
+ File dataDirFile = new File(dataDir);
+ File savedCachesDirFile = new File(savedCachesDir);
+
+ // validate the three data directories are empty - if they are not, we are probably stepping on another storage node
+ if (!isDirectoryEmpty(commitLogDirFile)) {
+ log.error("Commitlog directory is not empty. It should not exist for a new Storage Node ["
+ + commitLogDirFile.getAbsolutePath() + "]");
return STATUS_DATA_DIR_NOT_EMPTY;
}
- if (!isDirectoryEmpty(new File(dataDir))) {
- log.error("Data directory is not empty: " + dataDir);
+ if (!isDirectoryEmpty(dataDirFile)) {
+ log.error("Data directory is not empty. It should not exist for a new Storage Node ["
+ + dataDirFile.getAbsolutePath() + "]");
return STATUS_DATA_DIR_NOT_EMPTY;
}
- if (!isDirectoryEmpty(new File(savedCachesDir))) {
- log.error("Saved caches directory is not empty: " + savedCachesDir);
+ if (!isDirectoryEmpty(savedCachesDirFile)) {
+ log.error("Saved caches directory is not empty. It should not exist for a new Storage Node ["
+ + savedCachesDirFile.getAbsolutePath() + "]");
return STATUS_DATA_DIR_NOT_EMPTY;
}
@@ -373,8 +368,8 @@ public class StorageInstaller {
PropertiesFileUpdate serverPropertiesUpdater = getServerProperties();
log.info("Updating rhq-server.properties...");
- serverPropertiesUpdater.update("rhq.cassandra.seeds", getSeedsProperty(hostname, jmxPort,
- nativeTransportPort));
+ serverPropertiesUpdater.update("rhq.cassandra.seeds",
+ getSeedsProperty(hostname, jmxPort, nativeTransportPort));
}
boolean startNode = Boolean.parseBoolean(cmdLine.getOptionValue("start", "true"));
@@ -423,6 +418,7 @@ public class StorageInstaller {
}
}
}
+
private boolean isDirectoryEmpty(File dir) {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
@@ -657,8 +653,8 @@ public class StorageInstaller {
int endIndex = line.lastIndexOf("\"");
if (startIndex == -1 || endIndex == -1) {
- log.error("Failed to parse the JMX port. Make sure that you have the JMX port defined on its " +
- "own line as follows, JMX_PORT=\"<jmx-port>\"");
+ log.error("Failed to parse the JMX port. Make sure that you have the JMX port defined on its "
+ + "own line as follows, JMX_PORT=\"<jmx-port>\"");
throw new RuntimeException("Cannot determine JMX port");
}
try {
@@ -671,10 +667,10 @@ public class StorageInstaller {
}
line = reader.readLine();
}
- log.error("Failed to parse the JMX port. Make sure that you have the JMX port defined on its " +
- "own line as follows, JMX_PORT=\"<jmx-port>\"");
+ log.error("Failed to parse the JMX port. Make sure that you have the JMX port defined on its "
+ + "own line as follows, JMX_PORT=\"<jmx-port>\"");
throw new RuntimeException("Cannot determine JMX port");
- } catch(IOException e) {
+ } catch (IOException e) {
log.error("Failed to parse JMX port. There was an unexpected IO error", e);
throw new RuntimeException("Failed to parse JMX port due to IO error: " + e.getMessage());
} finally {
@@ -684,8 +680,8 @@ public class StorageInstaller {
}
} catch (IOException e) {
if (log.isDebugEnabled()) {
- log.debug("An error occurred closing the " + BufferedReader.class.getName() + " used to " +
- "parse the JMX port", e);
+ log.debug("An error occurred closing the " + BufferedReader.class.getName() + " used to "
+ + "parse the JMX port", e);
} else {
log.warn("There was error closing the reader used to parse the JMX port: " + e.getMessage());
}
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat
index c9fd2ff..5b96ff0 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-storage-installer.bat
@@ -193,7 +193,10 @@ if defined RHQ_STORAGE_DEBUG echo _JBOSS_MODULEPATH: %_JBOSS_MODULEPATH%
echo "Starting RHQ Storage Installer ..."
rem start the AS instance with our main installer module
+
"%RHQ_SERVER_JAVA_EXE_FILE_PATH%" %RHQ_STORAGE_INSTALLER_JAVA_OPTS% %RHQ_STORAGE_INSTALLER_ADDITIONAL_JAVA_OPTS% -jar "%RHQ_SERVER_JBOSS_HOME%\jboss-modules.jar" -mp "%_JBOSS_MODULEPATH%" org.rhq.rhq-cassandra-installer %*
+if not errorlevel 1 goto done
+exit /B %ERRORLEVEL%
:done
endlocal
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat
index 16f4773..d86c4f7 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhqctl.bat
@@ -188,6 +188,8 @@ if defined RHQ_CONTROL_DEBUG echo _JBOSS_MODULEPATH: %_JBOSS_MODULEPATH%
rem start the AS instance with our main installer module
"%RHQ_SERVER_JAVA_EXE_FILE_PATH%" %RHQ_CONTROL_JAVA_OPTS% %RHQ_CONTROL_ADDITIONAL_JAVA_OPTS% -jar "%RHQ_SERVER_JBOSS_HOME%\jboss-modules.jar" -mp "%_JBOSS_MODULEPATH%" org.rhq.rhq-server-control %*
+if not errorlevel 1 goto done
+exit /B %ERRORLEVEL%
:done
endlocal
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
index 19bbf91..7611419 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
@@ -196,7 +196,7 @@ public class Upgrade extends AbstractInstall {
if (commandLine.hasOption(FROM_AGENT_DIR_OPTION)) {
agentDir = new File(commandLine.getOptionValue(FROM_AGENT_DIR_OPTION));
} else {
- agentDir = new File(getBaseDir(), AGENT_BASEDIR_NAME);
+ agentDir = getAgentBasedir();
}
startAgent(agentDir, true);
}
@@ -601,7 +601,7 @@ public class Upgrade extends AbstractInstall {
throw new FileNotFoundException("Missing agent to upgrade: " + oldAgentDir.getAbsolutePath());
}
} else {
- oldAgentDir = new File(rhqctlCommandLine.getOptionValue(FROM_SERVER_DIR_OPTION), AGENT_BASEDIR_NAME);
+ oldAgentDir = getAgentBasedir();
if (!oldAgentDir.isDirectory()) {
log.info("No agent found in the old server location... skipping agent upgrade");
return;
commit 95f453caea1996f5e6b0c695d6af1350b6544c68
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Jun 18 14:52:04 2013 -0500
A few fixes to the quartz job to use only SLSB calls.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java
index 3508009..c6a64fb 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageNodeMaintenanceJob.java
@@ -22,10 +22,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import javax.ejb.TransactionAttribute;
-import javax.ejb.TransactionAttributeType;
-import javax.persistence.Query;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
@@ -38,6 +34,7 @@ import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.operation.OperationRequestStatus;
import org.rhq.core.domain.operation.ResourceOperationHistory;
import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
@@ -68,10 +65,10 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
private final static String MAINTENANCE_OPERATION_NOTE = "Topology change maintenance.";
private final static String RUN_REPAIR_PROPERTY = "runRepair";
private final static String UPDATE_SEEDS_LIST = "updateSeedsList";
+ private final static String SEEDS_LIST = "seedsList";
private final static String SUCCEED_PROPERTY = "succeed";
@Override
- @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void executeJobCode(JobExecutionContext arg0) throws JobExecutionException {
//1. Wait for resouces to be linked to node storage nodes
waitForResouceLinks();
@@ -106,13 +103,10 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
List<String> endpoints = new ArrayList<String>();
try {
- //Set<Resource> childResources = resource.getChildResources();
-
- Query query = LookupUtil.getEntityManager()
- .createNamedQuery(Resource.QUERY_FIND_CHILDREN_ADMIN);
- query.setParameter("parent", resource);
- List<Resource> childResources = query.getResultList();
-
+ ResourceCriteria c = new ResourceCriteria();
+ c.addFilterParentResourceId(resource.getId());
+ List<Resource> childResources = LookupUtil.getResourceManager().findResourcesByCriteria(
+ LookupUtil.getSubjectManager().getOverlord(), c);
for (Resource childResource : childResources) {
if (STORAGE_SERVICE.equals(childResource.getName())) {
@@ -168,7 +162,7 @@ public class StorageNodeMaintenanceJob extends AbstractStatefulJob {
List<Property> properties = new ArrayList<Property>();
properties.add(new PropertySimple(RUN_REPAIR_PROPERTY, Boolean.TRUE));
properties.add(new PropertySimple(UPDATE_SEEDS_LIST, Boolean.FALSE));
- properties.add(new PropertyList("seedsList"));
+ properties.add(new PropertyList(SEEDS_LIST));
Configuration config = new Configuration();
config.setProperties(properties);
newSchedule.setParameters(config);
commit b2ba3573da88b04779589fb2c613cffb444fbc48
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Jun 18 12:14:34 2013 -0400
the default location for the agent is the parent dir of the --from-server-dir
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
index 001002c..19bbf91 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
@@ -72,7 +72,7 @@ public class Upgrade extends AbstractInstall {
FROM_AGENT_DIR_OPTION,
true,
"Full path to install directory of the RHQ Agent to be upgraded. Required only if an existing agent "
- + "exists and is not installed in the default location: <from-server-dir>/rhq-agent")
+ + "exists and is not installed in the default location: <from-server-dir>/../rhq-agent")
.addOption(null, FROM_SERVER_DIR_OPTION, true,
"Full path to install directory of the RHQ Server to be upgraded. Required.")
.addOption(
commit 639e1d6e7c71c4f49a8ad6cc24bbd72ad6518bbf
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Jun 18 10:41:47 2013 -0500
Add a Windows script for the new data migration module.
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.bat b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.bat
new file mode 100644
index 0000000..b168624
--- /dev/null
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.bat
@@ -0,0 +1,199 @@
+@echo off
+
+rem =============================================================================
+rem RHQ Data Migration Script
+rem
+rem This file is used to migrate metric data from SQL server to the new RHQ storage server on a
+rem Windows platform.
+rem
+rem This script is customizable by setting the following environment variables:
+rem
+rem RHQ_DATA_MIGRATION_DEBUG - If this is defined, the script will emit debug
+rem messages. If this is not defined or set to "false"
+rem debug messages are not emitted.
+rem
+rem RHQ_SERVER_HOME - Defines where the server's home install directory is.
+rem If not defined, it will be assumed to be the parent
+rem directory of the directory where this script lives.
+rem
+rem RHQ_SERVER_JBOSS_HOME - The location of the AS instance that will
+rem host RHQ. If this is set, it overrides any
+rem JBOSS_HOME that might be set. If this not
+rem set, JBOSS_HOME is used as a fallback. If
+rem neither is set, it is assumed the AS bundled
+rem under RHQ_SERVER_HOME\jbossas is to be used.
+rem
+rem RHQ_SERVER_JAVA_HOME - The location of the JRE that the server will
+rem use. This will be ignored if
+rem RHQ_SERVER_JAVA_EXE_FILE_PATH is set.
+rem If this and RHQ_SERVER_JAVA_EXE_FILE_PATH are
+rem not set, JAVA_HOME will be used.
+rem
+rem RHQ_SERVER_JAVA_EXE_FILE_PATH - Defines the full path to the Java
+rem executable to use. If this is set,
+rem RHQ_SERVER_JAVA_HOME is ignored.
+rem If this is not set, then
+rem $RHQ_SERVER_JAVA_HOME\bin\java
+rem is used.
+rem
+rem RHQ_DATA_MIGRATION_JAVA_OPTS - Java VM command line options to be
+rem passed into the Java VM. If this is not defined
+rem this script will pass in a default set of options.
+rem If you only want to add options to the defaults,
+rem then you will want to use
+rem RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS instead.
+rem
+rem RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS - additional Java VM command
+rem line options to be passed into the VM.
+rem This is added to RHQ_DATA_MIGRATION_JAVA_OPTS; it
+rem is mainly used to augment the
+rem default set of options. This can be
+rem left unset if it is not needed.
+rem
+rem =============================================================================
+
+setlocal
+
+rem if debug variable is set, it is assumed to be on, unless its value is false
+if "%RHQ_DATA_MIGRATION_DEBUG%" == "false" (
+ set RHQ_DATA_MIGRATION_DEBUG=
+)
+
+rem ----------------------------------------------------------------------
+rem Change directory so the current directory is the Server home.
+rem ----------------------------------------------------------------------
+
+set RHQ_SERVER_BIN_DIR_PATH=%~dp0
+
+if not defined RHQ_SERVER_HOME (
+ cd "%RHQ_SERVER_BIN_DIR_PATH%\.."
+) else (
+ cd "%RHQ_SERVER_HOME%" || (
+ echo Cannot go to the RHQ_SERVER_HOME directory: %RHQ_SERVER_HOME%
+ exit /B 1
+ )
+)
+
+set RHQ_SERVER_HOME=%CD%
+
+if defined RHQ_DATA_MIGRATION_DEBUG echo RHQ_SERVER_HOME: %RHQ_SERVER_HOME%
+
+rem ----------------------------------------------------------------------
+rem Determine what JBossAS instance to use.
+rem If RHQ_SERVER_JBOSS_HOME and JBOSS_HOME are both not defined, we will
+rem assume we are to run the embedded AS instance from the RHQ
+rem installation directory - RHQ_SERVER_HOME\jbossas
+rem ----------------------------------------------------------------------
+
+if not defined RHQ_SERVER_JBOSS_HOME (
+ if not defined JBOSS_HOME (
+ set RHQ_SERVER_JBOSS_HOME=%RHQ_SERVER_HOME%\jbossas
+ ) else (
+ if not exist "%JBOSS_HOME%" (
+ echo ERROR! JBOSS_HOME is not pointing to a valid AS directory
+ echo JBOSS_HOME: "%JBOSS_HOME%"
+ exit /B 1
+ )
+ set RHQ_SERVER_JBOSS_HOME=%JBOSS_HOME%
+ )
+) else (
+ cd %RHQ_SERVER_JBOSS_HOME% || (
+ echo ERROR! RHQ_SERVER_JBOSS_HOME is not pointing to a valid AS directory
+ echo RHQ_SERVER_JBOSS_HOME: "%RHQ_SERVER_JBOSS_HOME%"
+ exit /B 1
+ )
+)
+
+cd %RHQ_SERVER_JBOSS_HOME%
+set RHQ_SERVER_JBOSS_HOME=%CD%
+
+if defined RHQ_DATA_MIGRATION_DEBUG echo RHQ_SERVER_JBOSS_HOME: %RHQ_SERVER_JBOSS_HOME%
+
+
+if not exist "%RHQ_SERVER_JBOSS_HOME%\jboss-modules.jar" (
+ echo ERROR! RHQ_SERVER_JBOSS_HOME is not pointing to a valid AS instance
+ echo Missing "%RHQ_SERVER_JBOSS_HOME%\jboss-modules.jar"
+ exit /B 1
+)
+
+rem we want the rest of this script to be able to assume cwd is the RHQ install dir
+cd "%RHQ_SERVER_HOME%"
+
+
+rem ----------------------------------------------------------------------
+rem Create the logs directory
+rem ----------------------------------------------------------------------
+
+set _LOG_DIR_PATH=%RHQ_SERVER_HOME%\logs
+if not exist "%_LOG_DIR_PATH%" (
+ mkdir "%_LOG_DIR_PATH%"
+)
+
+
+rem ----------------------------------------------------------------------
+rem Find the Java executable and verify we have a VM available
+rem ----------------------------------------------------------------------
+
+if not defined RHQ_SERVER_JAVA_EXE_FILE_PATH (
+ if not defined RHQ_SERVER_JAVA_HOME (
+ if defined RHQ_DATA_MIGRATION_DEBUG echo No JRE found - will try to use JAVA_HOME: %JAVA_HOME%
+ set RHQ_SERVER_JAVA_HOME=%JAVA_HOME%
+ )
+)
+if not defined RHQ_SERVER_JAVA_EXE_FILE_PATH (
+ set RHQ_SERVER_JAVA_EXE_FILE_PATH=%RHQ_SERVER_JAVA_HOME%\bin\java.exe
+)
+
+if defined RHQ_DATA_MIGRATION_DEBUG echo RHQ_SERVER_JAVA_HOME: %RHQ_SERVER_JAVA_HOME%
+if defined RHQ_DATA_MIGRATION_DEBUG echo RHQ_SERVER_JAVA_EXE_FILE_PATH: %RHQ_SERVER_JAVA_EXE_FILE_PATH%
+
+if not exist "%RHQ_SERVER_JAVA_EXE_FILE_PATH%" (
+ echo There is no JVM available.
+ echo Please set RHQ_SERVER_JAVA_HOME or RHQ_SERVER_JAVA_EXE_FILE_PATH appropriately.
+ exit /B 1
+)
+
+
+rem ----------------------------------------------------------------------
+rem Prepare the VM command line options to be passed in
+rem ----------------------------------------------------------------------
+
+if not defined RHQ_DATA_MIGRATION_JAVA_OPTS (
+ set RHQ_DATA_MIGRATION_JAVA_OPTS=-Xms512M -Xmx512M -XX:PermSize=128M -XX:MaxPermSize=128M -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true
+)
+
+rem Add the JVM opts that we always want to specify, whether or not the user set RHQ_CCM_JAVA_OPTS.
+if defined RHQ_DATA_MIGRATION_DEBUG (
+ set _RHQ_LOGLEVEL=DEBUG
+) else (
+ set _RHQ_LOGLEVEL=INFO
+)
+
+
+rem debugging the logging level now for development/testing
+set RHQ_DATA_MIGRATION_JAVA_OPTS=%RHQ_DATA_MIGRATION_JAVA_OPTS% -Djava.awt.headless=true -Drhq.server.properties-file=%RHQ_SERVER_HOME%\bin\rhq-server.properties -Drhq.server.basedir=%RHQ_SERVER_HOME%
+
+rem Sample JPDA settings for remote socket debugging
+rem set RHQ_DATA_MIGRATION_JAVA_OPTS=%RHQ_DATA_MIGRATION_JAVA_OPTS% -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y
+
+if defined RHQ_DATA_MIGRATION_DEBUG echo "RHQ_DATA_MIGRATION_JAVA_OPTS: %RHQ_DATA_MIGRATION_JAVA_OPTS%"
+if defined RHQ_DATA_MIGRATION_DEBUG echo "RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS: %RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS%"
+
+
+rem ----------------------------------------------------------------------
+rem We need to add our own modules to the core set of JBossAS modules.
+rem ----------------------------------------------------------------------
+set _RHQ_MODULES_PATH=%RHQ_SERVER_HOME%\modules
+set _INTERNAL_MODULES_PATH=%RHQ_SERVER_JBOSS_HOME%\modules
+set _JBOSS_MODULEPATH=%_RHQ_MODULES_PATH%;%_INTERNAL_MODULES_PATH%
+
+if defined RHQ_DATA_MIGRATION_DEBUG echo _JBOSS_MODULEPATH: %_JBOSS_MODULEPATH%
+
+
+echo "Starting RHQ Data Migration ..."
+
+rem start the AS instance with our main data migration module
+"%RHQ_SERVER_JAVA_EXE_FILE_PATH%" %RHQ_DATA_MIGRATION_JAVA_OPTS% %RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS% -jar "%RHQ_SERVER_JBOSS_HOME%\jboss-modules.jar" -mp "%_JBOSS_MODULEPATH%" org.rhq.rhq-data-migration %*
+
+:done
+endlocal
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh
index 2b06879..5cc8780 100755
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh
@@ -3,7 +3,7 @@
# =============================================================================
# RHQ Data Migration Script
#
-# This file is used to migrate metric data from SQL server to the new RHQ storage Server on a
+# This file is used to migrate metric data from SQL server to the new RHQ storage server on a
# UNIX platform.
#
# This script is customizable by setting the following environment variables:
commit 26b1b5e27cedec19aab094f39ffdef41e5fc32b2
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jun 18 17:35:14 2013 +0200
BZ 965342 - make sure the alert definition is valid. From Elias Ross
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index e143fe4..1353e18 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -656,6 +656,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
if (alertConditionCategory == AlertConditionCategory.BASELINE) {
MeasurementDefinition def = alertCondition.getMeasurementDefinition();
+ def = entityManager.getReference(MeasurementDefinition.class, def.getId());
NumericType numType = def.getNumericType();
if (numType == null) {
def = entityManager.getReference(MeasurementDefinition.class, def.getId());
commit dd534f7759bd6fc6e9b3db4935b9183bcf85ac6a
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Jun 18 09:57:56 2013 -0500
Create a jboss module for the data migrator to allow easy injection of jdbc drivers and command line execution.
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 427fbc3..b88354a 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -29,6 +29,7 @@
<module>agent</module>
<module>agentupdate</module>
<module>server/server-metrics</module>
+ <module>server/data-migration</module>
<module>server/xml-schemas</module>
<module>server/jar</module>
<module>server/safe-invoker</module>
@@ -59,6 +60,7 @@
<module>agent</module>
<module>agentupdate</module>
<module>server/server-metrics</module>
+ <module>server/data-migration</module>
<module>server/xml-schemas</module>
<module>server/jar</module>
<module>server/safe-invoker</module>
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh
new file mode 100755
index 0000000..2b06879
--- /dev/null
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-data-migration.sh
@@ -0,0 +1,243 @@
+#!/bin/sh
+
+# =============================================================================
+# RHQ Data Migration Script
+#
+# This file is used to migrate metric data from SQL server to the new RHQ storage Server on a
+# UNIX platform.
+#
+# This script is customizable by setting the following environment variables:
+#
+# RHQ_DATA_MIGRATION_DEBUG - If this is defined, the script will emit debug
+# messages. If this is not defined or set to "false"
+# debug messages are not emitted.
+#
+# RHQ_SERVER_HOME - Defines where the server's home install directory is.
+# If not defined, it will be assumed to be the parent
+# directory of the directory where this script lives.
+#
+# RHQ_SERVER_JBOSS_HOME - The location of the AS instance that will
+# host RHQ. If this is set, it overrides any
+# JBOSS_HOME that might be set. If this not
+# set, JBOSS_HOME is used as a fallback. If
+# neither is set, it is assumed the AS bundled
+# under RHQ_SERVER_HOME/jbossas is to be used.
+#
+# RHQ_SERVER_JAVA_HOME - The location of the JRE that the server will
+# use. This will be ignored if
+# RHQ_SERVER_JAVA_EXE_FILE_PATH is set.
+# If this and RHQ_SERVER_JAVA_EXE_FILE_PATH are
+# not set, the Server's embedded JRE will be used.
+#
+# RHQ_SERVER_JAVA_EXE_FILE_PATH - Defines the full path to the Java
+# executable to use. If this is set,
+# RHQ_SERVER_JAVA_HOME is ignored.
+# If this is not set, then
+# $RHQ_SERVER_JAVA_HOME/bin/java
+# is used. If this and
+# RHQ_SERVER_JAVA_HOME are not set, the
+# Server's embedded JRE will be used.
+#
+# RHQ_DATA_MIGRATION_JAVA_OPTS - Java VM command line options to be
+# passed into the Java VM. If this is not defined
+# this script will pass in a default set of options.
+# If you only want to add options to the defaults,
+# then you will want to use
+# RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS instead.
+#
+# RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS - additional Java VM command
+# line options to be passed into the VM.
+# This is added to RHQ_DATA_MIGRATION_JAVA_OPTS; it
+# is mainly used to augment the
+# default set of options. This can be
+# left unset if it is not needed.
+#
+# If the embedded JRE is to be used but is not available, the fallback
+# JRE to be used will be determined by the JAVA_HOME environment variable.
+# =============================================================================
+
+debug_msg ()
+{
+ # if debug variable is set, it is assumed to be on, unless its value is false
+ if [ -n "$RHQ_DATA_MIGRATION_DEBUG" ] && [ "$RHQ_DATA_MIGRATION_DEBUG" != "false" ]; then
+ echo $1
+ fi
+}
+
+# ----------------------------------------------------------------------
+# Determine what specific platform we are running on.
+# Set some platform-specific variables.
+# ----------------------------------------------------------------------
+
+case "`uname`" in
+ CYGWIN*) _CYGWIN=true
+ ;;
+ Linux*) _LINUX=true
+ ;;
+ Darwin*) _DARWIN=true
+ ;;
+ SunOS*) _SOLARIS=true
+ ;;
+ AIX*) _AIX=true
+ ;;
+esac
+
+# only certain platforms support the -e argument for readlink
+if [ -n "${_LINUX}${_SOLARIS}${_CYGWIN}" ]; then
+ _READLINK_ARG="-e"
+fi
+
+# ----------------------------------------------------------------------
+# Determine the RHQ Server installation directory.
+# If RHQ_SERVER_HOME is not defined, we will assume we are running
+# directly from the server installation's bin directory.
+# ----------------------------------------------------------------------
+
+if [ -z "$RHQ_SERVER_HOME" ]; then
+ _DOLLARZERO=`readlink $_READLINK_ARG "$0" 2>/dev/null || echo "$0"`
+ RHQ_SERVER_HOME=`dirname "$_DOLLARZERO"`/..
+else
+ if [ ! -d "$RHQ_SERVER_HOME" ]; then
+ echo "ERROR! RHQ_SERVER_HOME is not pointing to a valid directory"
+ echo "RHQ_SERVER_HOME: $RHQ_SERVER_HOME"
+ exit 1
+ fi
+fi
+
+cd "$RHQ_SERVER_HOME"
+RHQ_SERVER_HOME=`pwd`
+
+debug_msg "RHQ_SERVER_HOME: $RHQ_SERVER_HOME"
+
+# ----------------------------------------------------------------------
+# Determine what JBossAS instance to use.
+# If RHQ_SERVER_JBOSS_HOME and JBOSS_HOME are both not defined, we will
+# assume we are to run the embedded AS instance from the RHQ
+# installation directory - RHQ_SERVER_HOME/jbossas
+# ----------------------------------------------------------------------
+
+if [ -z "$RHQ_SERVER_JBOSS_HOME" ]; then
+ if [ -z "$JBOSS_HOME" ]; then
+ RHQ_SERVER_JBOSS_HOME="${RHQ_SERVER_HOME}/jbossas"
+ else
+ if [ ! -d "$JBOSS_HOME" ]; then
+ echo "ERROR! JBOSS_HOME is not pointing to a valid AS directory"
+ echo "JBOSS_HOME: $JBOSS_HOME"
+ exit 1
+ fi
+ RHQ_SERVER_JBOSS_HOME="${JBOSS_HOME}"
+ fi
+else
+ if [ ! -d "$RHQ_SERVER_JBOSS_HOME" ]; then
+ echo "ERROR! RHQ_SERVER_JBOSS_HOME is not pointing to a valid AS directory"
+ echo "RHQ_SERVER_JBOSS_HOME: $RHQ_SERVER_JBOSS_HOME"
+ exit 1
+ fi
+fi
+
+cd "$RHQ_SERVER_JBOSS_HOME"
+RHQ_SERVER_JBOSS_HOME=`pwd`
+
+debug_msg "RHQ_SERVER_JBOSS_HOME: $RHQ_SERVER_JBOSS_HOME"
+
+if [ ! -f "${RHQ_SERVER_JBOSS_HOME}/jboss-modules.jar" ]; then
+ echo "ERROR! RHQ_SERVER_JBOSS_HOME is not pointing to a valid AS instance"
+ echo "Missing ${RHQ_SERVER_JBOSS_HOME}/jboss-modules.jar"
+ exit 1
+fi
+
+# we want the rest of this script to be able to assume cwd is the RHQ install dir
+cd "$RHQ_SERVER_HOME"
+
+# ----------------------------------------------------------------------
+# if we are on a Mac and JAVA_HOME is not set, then set it to /usr
+# as this is the default location.
+# ----------------------------------------------------------------------
+
+if [ -z "$JAVA_HOME" ]; then
+ if [ -n "$_DARWIN" ]; then
+ debug_msg "Running on Mac OS X, setting JAVA_HOME to /usr"
+ JAVA_HOME=/usr
+ fi
+fi
+
+# ----------------------------------------------------------------------
+# Create the logs directory
+# ----------------------------------------------------------------------
+
+_LOG_DIR_PATH="${RHQ_SERVER_HOME}/logs"
+if [ -n "$_CYGWIN" ]; then
+ _LOG_DIR_PATH=`cygpath --windows --path "$_LOG_DIR_PATH"`
+fi
+if [ ! -d "${_LOG_DIR_PATH}" ]; then
+ mkdir "${_LOG_DIR_PATH}"
+fi
+
+# ----------------------------------------------------------------------
+# Find the Java executable and verify we have a VM available
+# ----------------------------------------------------------------------
+
+if [ -z "$RHQ_SERVER_JAVA_EXE_FILE_PATH" ]; then
+ if [ -z "$RHQ_SERVER_JAVA_HOME" ]; then
+ RHQ_SERVER_JAVA_HOME="${RHQ_SERVER_HOME}/jre"
+ if [ -d "$RHQ_SERVER_JAVA_HOME" ]; then
+ debug_msg "Using the embedded JRE"
+ else
+ debug_msg "No embedded JRE found - will try to use JAVA_HOME: $JAVA_HOME"
+ RHQ_SERVER_JAVA_HOME="$JAVA_HOME"
+ fi
+ fi
+ debug_msg "RHQ_SERVER_JAVA_HOME: $RHQ_SERVER_JAVA_HOME"
+ RHQ_SERVER_JAVA_EXE_FILE_PATH="${RHQ_SERVER_JAVA_HOME}/bin/java"
+fi
+debug_msg "RHQ_SERVER_JAVA_EXE_FILE_PATH: $RHQ_SERVER_JAVA_EXE_FILE_PATH"
+
+if [ ! -f "$RHQ_SERVER_JAVA_EXE_FILE_PATH" ]; then
+ echo "There is no JVM available."
+ echo "Please set RHQ_SERVER_JAVA_HOME or RHQ_SERVER_JAVA_EXE_FILE_PATH appropriately."
+ exit 1
+fi
+
+# ----------------------------------------------------------------------
+# Prepare the VM command line options to be passed in
+# ----------------------------------------------------------------------
+
+if [ -z "$RHQ_DATA_MIGRATION_JAVA_OPTS" ]; then
+ RHQ_DATA_MIGRATION_JAVA_OPTS="-Xms512M -Xmx512M -XX:PermSize=128M -XX:MaxPermSize=128M -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true"
+fi
+
+# Add the JVM opts that we always want to specify, whether or not the user set RHQ_CCM_JAVA_OPTS.
+if [ -n "$RHQ_DATA_MIGRATION_DEBUG" ] && [ "$RHQ_DATA_MIGRATION_DEBUG" != "false" ]; then
+ _RHQ_LOGLEVEL="DEBUG"
+else
+ _RHQ_LOGLEVEL="INFO"
+fi
+
+# debugging the logging level now for development/testing
+RHQ_DATA_MIGRATION_JAVA_OPTS="${RHQ_DATA_MIGRATION_JAVA_OPTS} -Djava.awt.headless=true -Drhq.server.properties-file=${RHQ_SERVER_HOME}/bin/rhq-server.properties -Drhq.server.basedir=${RHQ_SERVER_HOME}"
+
+# Sample JPDA settings for remote socket debugging
+#RHQ_DATA_MIGRATION_JAVA_OPTS="${RHQ_DATA_MIGRATION_JAVA_OPTS} -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"
+
+debug_msg "RHQ_DATA_MIGRATION_JAVA_OPTS: $RHQ_DATA_MIGRATION_JAVA_OPTS"
+debug_msg "RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS: $RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS"
+
+# ----------------------------------------------------------------------
+# We need to add our own modules to the core set of JBossAS modules.
+# ----------------------------------------------------------------------
+_RHQ_MODULES_PATH="${RHQ_SERVER_HOME}/modules"
+_INTERNAL_MODULES_PATH="${RHQ_SERVER_JBOSS_HOME}/modules"
+if [ -n "$_CYGWIN" ]; then
+ _RHQ_MODULES_PATH=`cygpath --windows --path "$_RHQ_MODULES_PATH"`
+ _INTERNAL_MODULES_PATH=`cygpath --windows --path "$_INTERNAL_MODULES_PATH"`
+fi
+_JBOSS_MODULEPATH="${_RHQ_MODULES_PATH}:${_INTERNAL_MODULES_PATH}"
+debug_msg "_JBOSS_MODULEPATH: $_JBOSS_MODULEPATH"
+
+echo "Starting RHQ Data Migration ..."
+
+# start the AS instance with our main data migration module
+"$RHQ_SERVER_JAVA_EXE_FILE_PATH" ${RHQ_DATA_MIGRATION_JAVA_OPTS} ${RHQ_DATA_MIGRATION_ADDITIONAL_JAVA_OPTS} -jar "${RHQ_SERVER_JBOSS_HOME}/jboss-modules.jar" -mp "$_JBOSS_MODULEPATH" org.rhq.rhq-data-migration "$@"
+
+_EXIT_STATUS=$?
+exit $_EXIT_STATUS
diff --git a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
index 6090be8..839dbda 100644
--- a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
@@ -175,6 +175,10 @@
<unzip src="${settings.localRepository}/org/rhq/rhq-cassandra-installer/${project.version}/rhq-cassandra-installer-${project.version}.zip"
dest="${jboss.modules.dir}"/>
+ <echo>Adding data migration module to ${jboss.modules.dir}...</echo>
+ <unzip src="${settings.localRepository}/org/rhq/rhq-data-migration/${project.version}/rhq-data-migration-${project.version}.zip"
+ dest="${jboss.modules.dir}"/>
+
<echo>Adding RHQ Server Control module to ${jboss.modules.dir}...</echo>
<unzip src="${settings.localRepository}/org/rhq/rhq-server-control/${project.version}/rhq-server-control-${project.version}.zip"
dest="${jboss.modules.dir}"/>
diff --git a/modules/enterprise/server/data-migration/pom.xml b/modules/enterprise/server/data-migration/pom.xml
new file mode 100644
index 0000000..ed4b4c4
--- /dev/null
+++ b/modules/enterprise/server/data-migration/pom.xml
@@ -0,0 +1,213 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-parent</artifactId>
+ <version>4.8.0-SNAPSHOT</version>
+ <relativePath>../../../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>rhq-data-migration</artifactId>
+ <name>RHQ Cassandra Data Migration</name>
+
+ <properties>
+ <moduleName>org.rhq.${project.artifactId}</moduleName>
+ <joda-time.version>2.1</joda-time.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-server-metrics</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.0-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.datastax.cassandra</groupId>
+ <artifactId>cassandra-driver-core</artifactId>
+ <version>${cassandra.driver.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.7.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ <version>${joda-time.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/scripts/module-assembly.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>module-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-deps</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/dependencies</outputDirectory>
+ <artifactItems>
+ <artifactItem>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-server-metrics</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+ <artifactItem>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ <version>2.1</version>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.0-api</artifactId>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../../..</rhq.rootDir>
+ <rhq.containerDir>${rhq.rootDir}/${rhq.devContainerServerPath}</rhq.containerDir>
+ <rhq.deploymentDir>${rhq.containerDir}/modules/org/rhq/rhq-data-migration/main</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <target>
+ <mkdir dir="${rhq.deploymentDir}" />
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating ${deployment.file}...</echo>
+ <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <target>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting ${deployment.file}...</echo>
+ <delete file="${deployment.file}" />
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java
new file mode 100644
index 0000000..9578e73
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigrator.java
@@ -0,0 +1,309 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import javax.persistence.EntityManager;
+
+import com.datastax.driver.core.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.server.metrics.domain.MetricsTable;
+import org.rhq.server.metrics.migrator.workers.AggregateDataMigrator;
+import org.rhq.server.metrics.migrator.workers.CallableMigrationWorker;
+import org.rhq.server.metrics.migrator.workers.DeleteAllData;
+import org.rhq.server.metrics.migrator.workers.RawDataMigrator;
+
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class DataMigrator {
+
+ public enum DatabaseType {
+ Postgres, Oracle
+ }
+
+ public enum Task {
+ Migrate, Estimate
+ }
+
+ private interface RunnableWithException extends Runnable {
+ Exception getException();
+ }
+
+ private final Log log = LogFactory.getLog(DataMigrator.class);
+
+ public static final double UNDER_ESTIMATION_FACTOR = .15;
+ public static final int SQL_TIMEOUT = 6000000;
+ public static final int MAX_NUMBER_OF_FAILURES = 5;
+
+ private final DataMigratorConfiguration config;
+ private long estimation;
+
+ public DataMigrator(EntityManager entityManager, Session session, DatabaseType databaseType) {
+ this(entityManager, session, databaseType, false);
+ }
+
+ public DataMigrator(EntityManager entityManager, Session session, DatabaseType databaseType,
+ boolean experimentalDataSource) {
+
+ config = new DataMigratorConfiguration(entityManager, session, databaseType, experimentalDataSource);
+ config.setDeleteDataImmediatelyAfterMigration(false);
+ config.setDeleteAllDataAtEndOfMigration(false);
+ config.setRunRawDataMigration(true);
+ config.setRun1HAggregateDataMigration(true);
+ config.setRun6HAggregateDataMigration(true);
+ config.setRun1DAggregateDataMigration(true);
+ }
+
+ public void runRawDataMigration(boolean value) {
+ config.setRunRawDataMigration(value);
+ }
+
+ public void run1HAggregateDataMigration(boolean value) {
+ config.setRun1HAggregateDataMigration(value);
+ }
+
+ public void run6HAggregateDataMigration(boolean value) {
+ config.setRun6HAggregateDataMigration(value);
+ }
+
+ public void run1DAggregateDataMigration(boolean value) {
+ config.setRun1DAggregateDataMigration(value);
+ }
+
+ public void deleteDataImmediatelyAfterMigration() {
+ config.setDeleteDataImmediatelyAfterMigration(true);
+ config.setDeleteAllDataAtEndOfMigration(false);
+ }
+
+ public void deleteAllDataAtEndOfMigration() {
+ config.setDeleteAllDataAtEndOfMigration(true);
+ config.setDeleteDataImmediatelyAfterMigration(false);
+ }
+
+ public void preserveData() {
+ config.setDeleteAllDataAtEndOfMigration(false);
+ config.setDeleteDataImmediatelyAfterMigration(false);
+ }
+
+ public long estimate() throws Exception {
+ this.estimation = 0;
+ if (config.isRunRawDataMigration()) {
+ retryOnFailure(new RawDataMigrator(config), Task.Estimate);
+ }
+
+ if (config.isRun1HAggregateDataMigration()) {
+ retryOnFailure(new AggregateDataMigrator(MetricsTable.ONE_HOUR, config), Task.Estimate);
+ }
+
+ if (config.isRun6HAggregateDataMigration()) {
+ retryOnFailure(new AggregateDataMigrator(MetricsTable.SIX_HOUR, config), Task.Estimate);
+ }
+
+ if (config.isRun1DAggregateDataMigration()) {
+ retryOnFailure(new AggregateDataMigrator(MetricsTable.TWENTY_FOUR_HOUR, config), Task.Estimate);
+ }
+
+ if (config.isDeleteAllDataAtEndOfMigration()) {
+ retryOnFailure(new DeleteAllData(config), Task.Estimate);
+ }
+
+ estimation = (long) (estimation + estimation * UNDER_ESTIMATION_FACTOR);
+
+ return estimation;
+ }
+
+ public void migrateData() throws Exception {
+ if (config.isRunRawDataMigration()) {
+ retryOnFailure(new RawDataMigrator(config), Task.Migrate);
+ }
+
+ if (config.isRun1HAggregateDataMigration()) {
+ retryOnFailure(new AggregateDataMigrator(MetricsTable.ONE_HOUR, config), Task.Migrate);
+ }
+
+ if (config.isRun6HAggregateDataMigration()) {
+ retryOnFailure(new AggregateDataMigrator(MetricsTable.SIX_HOUR, config), Task.Migrate);
+ }
+
+ if (config.isRun1DAggregateDataMigration()) {
+ retryOnFailure(new AggregateDataMigrator(MetricsTable.TWENTY_FOUR_HOUR, config), Task.Migrate);
+ }
+
+ if (config.isDeleteAllDataAtEndOfMigration()) {
+ retryOnFailure(new DeleteAllData(config), Task.Migrate);
+ }
+ }
+
+ public void deleteOldData() throws Exception {
+ if (config.isDeleteAllDataAtEndOfMigration()) {
+ retryOnFailure(new DeleteAllData(config), Task.Migrate);
+ }
+ }
+
+ /**
+ * Retries the migration {@link #MAX_NUMBER_OF_FAILURES} times before
+ * failing the migration operation.
+ *
+ * @param migrator
+ * @throws Exception
+ */
+ private Thread retryOnFailure(final CallableMigrationWorker migrator, final Task task)
+ throws Exception {
+
+ RunnableWithException runnable = new RunnableWithException() {
+ private Exception exception;
+
+ @Override
+ public void run() {
+ int numberOfFailures = 0;
+ Exception caughtException = null;
+
+ log.info(migrator.getClass());
+
+ while (numberOfFailures < MAX_NUMBER_OF_FAILURES) {
+ try {
+ if (task == Task.Estimate) {
+ estimation += migrator.estimate();
+ } else {
+ migrator.migrate();
+ }
+ return;
+ } catch (Exception e) {
+ log.error("Migrator " + migrator.getClass() + " failed. Retrying!", e);
+
+ caughtException = e;
+ numberOfFailures++;
+ }
+ }
+
+ this.exception = caughtException;
+ }
+
+ @Override
+ public Exception getException() {
+ return this.exception;
+ }
+ };
+
+ Thread localThread = new Thread(runnable);
+ localThread.start();
+ localThread.join();
+
+ if (runnable.getException() != null) {
+ throw runnable.getException();
+ }
+
+ return localThread;
+ }
+
+ public class DataMigratorConfiguration {
+
+ private final EntityManager entityManager;
+ private final Session session;
+ private final DatabaseType databaseType;
+ private final boolean experimentalDataSource;
+
+ private boolean deleteDataImmediatelyAfterMigration;
+ private boolean deleteAllDataAtEndOfMigration;
+
+ private boolean runRawDataMigration;
+ private boolean run1HAggregateDataMigration;
+ private boolean run6HAggregateDataMigration;
+ private boolean run1DAggregateDataMigration;
+
+ public DataMigratorConfiguration(EntityManager entityManager, Session session, DatabaseType databaseType,
+ boolean experimentalDataSource) {
+ this.entityManager = entityManager;
+ this.session = session;
+ this.databaseType = databaseType;
+ this.experimentalDataSource = experimentalDataSource;
+ }
+
+ public boolean isDeleteDataImmediatelyAfterMigration() {
+ return deleteDataImmediatelyAfterMigration;
+ }
+
+ private void setDeleteDataImmediatelyAfterMigration(boolean deleteDataImmediatelyAfterMigration) {
+ this.deleteDataImmediatelyAfterMigration = deleteDataImmediatelyAfterMigration;
+ }
+
+ public boolean isDeleteAllDataAtEndOfMigration() {
+ return deleteAllDataAtEndOfMigration;
+ }
+
+ private void setDeleteAllDataAtEndOfMigration(boolean deleteAllDataAtEndOfMigration) {
+ this.deleteAllDataAtEndOfMigration = deleteAllDataAtEndOfMigration;
+ }
+
+ public boolean isRunRawDataMigration() {
+ return runRawDataMigration;
+ }
+
+ private void setRunRawDataMigration(boolean runRawDataMigration) {
+ this.runRawDataMigration = runRawDataMigration;
+ }
+
+ public boolean isRun1HAggregateDataMigration() {
+ return run1HAggregateDataMigration;
+ }
+
+ private void setRun1HAggregateDataMigration(boolean run1hAggregateDataMigration) {
+ run1HAggregateDataMigration = run1hAggregateDataMigration;
+ }
+
+ public boolean isRun6HAggregateDataMigration() {
+ return run6HAggregateDataMigration;
+ }
+
+ private void setRun6HAggregateDataMigration(boolean run6hAggregateDataMigration) {
+ run6HAggregateDataMigration = run6hAggregateDataMigration;
+ }
+
+ public boolean isRun1DAggregateDataMigration() {
+ return run1DAggregateDataMigration;
+ }
+
+ private void setRun1DAggregateDataMigration(boolean run1dAggregateDataMigration) {
+ run1DAggregateDataMigration = run1dAggregateDataMigration;
+ }
+
+ public EntityManager getEntityManager() {
+ return entityManager;
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ public DatabaseType getDatabaseType() {
+ return databaseType;
+ }
+
+ public boolean isExperimentalDataSource() {
+ return experimentalDataSource;
+ }
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java
new file mode 100644
index 0000000..86cb2fd
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/DataMigratorRunner.java
@@ -0,0 +1,674 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.sql.Driver;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.ProtocolOptions.Compression;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.exceptions.NoHostAvailableException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import org.rhq.server.metrics.migrator.DataMigrator.DatabaseType;
+
+
+/**
+ * @author Stefan Negrea
+ *
+ * Only postgres is supported by the runner, however the data migrator itself can run
+ * with any database.
+ *
+ * Maven command to run this from the command line:
+ *
+ * mvn install -DskipTests exec:java -Dexec.mainClass="org.rhq.server.metrics.DataMigratorRunner"
+ *
+ *
+ */
+@SuppressWarnings({ "static-access", "deprecation" })
+public class DataMigratorRunner {
+
+ private static final int DEFAULT_CASSANDRA_PORT = 9142;
+ private final Log log = LogFactory.getLog(DataMigratorRunner.class);
+
+ //Cassandra
+ private Option cassandraUserOption = OptionBuilder.withLongOpt("cassandra-user").hasArg().withType(String.class)
+ .withDescription("Cassandra user (default: rhqadmin)").create();
+ private Option cassandraPasswordOption = OptionBuilder.withLongOpt("cassandra-password").hasArg()
+ .withDescription("Cassandra password (default: rhqadmin)").withType(String.class).create();
+ private Option cassandraHostsOption = OptionBuilder.withLongOpt("cassandra-hosts").hasArg().withType(String.class)
+ .withDescription("Cassandra hosts, format host_ip_1,host_ip_2,... (default: 127.0.0.1")
+ .create();
+ private Option cassandraPortOption = OptionBuilder.withLongOpt("cassandra-port").hasArg().withType(Integer.class)
+ .withDescription("Cassandra native binary protocol port (default: 9142)").create();
+ private Option cassandraCompressionOption = OptionBuilder.withLongOpt("cassandra-compression").hasOptionalArg()
+ .withType(Boolean.class).withDescription("Enable compression for communication with Cassandra (default: true)")
+ .create();
+
+ //SQL
+ private Option sqlUserOption = OptionBuilder.withLongOpt("sql-user").hasArg().withType(String.class)
+ .withDescription("SQL server user (default: rhqadmin)").create();
+ private Option sqlPasswordOption = OptionBuilder.withLongOpt("sql-password").hasArg().withType(String.class)
+ .withDescription("SQL server password (default: rhqadmin)").create();
+ private Option sqlHostOption = OptionBuilder.withLongOpt("sql-host").hasArg().withType(String.class)
+ .withDescription("SQL server host address (default: localhost)").create();
+ private Option sqlPortOption = OptionBuilder.withLongOpt("sql-port").hasArg().withType(String.class)
+ .withDescription("SQL server port (default: 5432)").create();
+ private Option sqlDBOption = OptionBuilder.withLongOpt("sql-db").hasArg().withType(String.class)
+ .withDescription("SQL database (default: rhq)").create();
+
+ private Option sqlServerType = OptionBuilder.withLongOpt("sql-server-type").hasArg().withType(String.class)
+ .withDescription("SQL server type, only postgres and oracle are supported (default: postgres)").create();
+ private Option sqlPostgresServer = OptionBuilder.withLongOpt("sql-server-postgres").hasOptionalArg()
+ .withType(Boolean.class).withDescription("Postgres SQL server.").create();
+ private Option sqlOracleServer = OptionBuilder.withLongOpt("sql-server-oracle").hasOptionalArg()
+ .withType(Boolean.class)
+ .withDescription("Oracle SQL server.").create();
+
+ //Migration
+ private Option disableRawOption = OptionBuilder.withLongOpt("disable-raw-migration").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Disable raw table migration (default: false)").create();
+ private Option disable1HOption = OptionBuilder.withLongOpt("disable-1h-migration").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Disable 1 hour aggregates table migration (default: false)").create();
+ private Option disable6HOption = OptionBuilder.withLongOpt("disable-6h-migration").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Disable 6 hours aggregates table migration (default: false)").create();
+ private Option disable1DOption = OptionBuilder.withLongOpt("disable-1d-migration").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Disable 24 hours aggregates table migration (default: false)").create();
+ private Option preserveDataOption = OptionBuilder.withLongOpt("preserve-data").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Preserve SQL data post migration (default: true)").create();
+ private Option deleteDataOption = OptionBuilder.withLongOpt("delete-data").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Delete SQL data at the end of migration (default: false)").create();
+ private Option estimateOnlyOption = OptionBuilder.withLongOpt("estimate-only").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Only estimate how long the migration will take (default: false)").create();
+ private Option deleteOnlyOption = OptionBuilder.withLongOpt("delete-only").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Only delete data from the old SQL server, no migration will be performed (default: false)")
+ .create();
+ private Option experimentalExportOption = OptionBuilder.withLongOpt("experimental-export").hasOptionalArg().withType(Boolean.class)
+ .withDescription("Enable experimental bulk export for Postgres, option ignored for Oracle migration (default: false)")
+ .create();
+
+ //Runner
+ private Option helpOption = OptionBuilder.withLongOpt("help").create("h");
+ private Option debugLogOption = OptionBuilder.withLongOpt("debugLog")
+ .withDescription("Enable debug level logs for the communication with Cassandra and SQL Server (default: false)")
+ .create("X");
+ private Option configFileOption = OptionBuilder.withLongOpt("config-file").hasArg()
+ .withDescription("Configuration file. All the command line options can be set in a typical properties file. " +
+ "Command line arguments take precedence over default and configuration file options.")
+ .create();
+
+ private Map<Object, Object> configuration = new HashMap<Object, Object>();
+ private Options options;
+
+ /**
+ * @param args
+ * @throws ParseException
+ */
+ public static void main(String[] args) throws Exception {
+ initLogging();
+ try{
+ DataMigratorRunner runner = new DataMigratorRunner();
+ runner.configure(args);
+ runner.run();
+ } catch (HelpRequestedException h) {
+ //do nothing
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ System.exit(0);
+ }
+
+ private static void initLogging() {
+ Logger root = Logger.getRootLogger();
+ if (!root.getAllAppenders().hasMoreElements()) {
+ root.addAppender(new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)));
+ setLogLevel(Level.ERROR);
+ }
+ }
+
+ private static void setLogLevel(Level level) {
+ Logger root = Logger.getRootLogger();
+ root.setLevel(level);
+
+ Logger cassandraLogging = root.getLoggerRepository().getLogger("log4j.logger.org.apache.cassandra.cql.jdbc");
+ cassandraLogging.setLevel(level);
+
+ Logger cassandraDriverLogging = root.getLoggerRepository().getLogger("com.datastax.driver");
+ cassandraDriverLogging.setLevel(level);
+
+ Logger hibernateLogging = root.getLoggerRepository().getLogger("org.hibernate");
+ hibernateLogging.setLevel(Level.ERROR);
+
+ Logger migratorLogging = root.getLoggerRepository().getLogger("org.rhq");
+ if (Level.DEBUG.equals(level)) {
+ migratorLogging.setLevel(Level.ALL);
+ } else {
+ migratorLogging.setLevel(level);
+ }
+ }
+
+ private void configure(String args[]) throws Exception {
+ options = new Options();
+
+ options.addOption(cassandraUserOption);
+ options.addOption(cassandraPasswordOption);
+ options.addOption(cassandraHostsOption);
+ options.addOption(cassandraPortOption);
+ options.addOption(cassandraCompressionOption);
+
+ options.addOption(sqlUserOption);
+ options.addOption(sqlPasswordOption);
+ options.addOption(sqlHostOption);
+ options.addOption(sqlPortOption);
+ options.addOption(sqlDBOption);
+ options.addOption(sqlServerType);
+ options.addOption(sqlPostgresServer);
+ options.addOption(sqlOracleServer);
+
+ options.addOption(disableRawOption);
+ options.addOption(disable1HOption);
+ options.addOption(disable6HOption);
+ options.addOption(disable1DOption);
+ options.addOption(preserveDataOption);
+ options.addOption(deleteDataOption);
+ options.addOption(estimateOnlyOption);
+ options.addOption(deleteOnlyOption);
+ options.addOption(experimentalExportOption);
+
+ options.addOption(helpOption);
+ options.addOption(debugLogOption);
+ options.addOption(configFileOption);
+
+ CommandLine commandLine;
+ try {
+ CommandLineParser parser = new PosixParser();
+ commandLine = parser.parse(options, args);
+ } catch (Exception e) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.setWidth(120);
+ formatter.printHelp("DataMigrationRunner", options);
+ throw new Exception("Error parsing command line arguments");
+ }
+
+ if (commandLine.hasOption(helpOption.getLongOpt()) || commandLine.hasOption(helpOption.getOpt())) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("DataMigrationRunner", options);
+ throw new HelpRequestedException();
+ }
+
+ if (commandLine.hasOption(debugLogOption.getLongOpt()) || commandLine.hasOption(debugLogOption.getOpt())) {
+ DataMigratorRunner.setLogLevel(Level.DEBUG);
+ }
+
+ loadDefaultConfiguration();
+ if (commandLine.hasOption(configFileOption.getLongOpt())) {
+ loadConfigFile(commandLine.getOptionValue(configFileOption.getLongOpt()));
+ }
+
+ parseCassandraOptions(commandLine);
+ parseSQLOptions(commandLine);
+ parseMigrationOptions(commandLine);
+ }
+
+ /**
+ * Add default configuration options to the configuration store.
+ */
+ private void loadDefaultConfiguration() {
+ //default Cassandra configuration
+ configuration.put(cassandraUserOption, "rhqadmin");
+ configuration.put(cassandraPasswordOption, "rhqadmin");
+ configuration.put(cassandraHostsOption, new String[] { "127.0.0.1" });
+ configuration.put(cassandraPortOption, DEFAULT_CASSANDRA_PORT);
+ configuration.put(cassandraCompressionOption, true);
+
+ //default SQL configuration
+ configuration.put(sqlUserOption, "rhqadmin");
+ configuration.put(sqlPasswordOption, "rhqadmin");
+ configuration.put(sqlHostOption, "localhost");
+ configuration.put(sqlPortOption, "5432");
+ configuration.put(sqlDBOption, "rhq");
+ configuration.put(sqlServerType, "postgres");
+
+ //default runner options
+ configuration.put(disableRawOption, false);
+ configuration.put(disable1HOption, false);
+ configuration.put(disable6HOption, false);
+ configuration.put(disable1DOption, false);
+ configuration.put(preserveDataOption, true);
+ configuration.put(estimateOnlyOption, false);
+ configuration.put(deleteOnlyOption, false);
+ configuration.put(experimentalExportOption, false);
+ }
+
+ /**
+ * Load the configuration options from file and overlay them on top of the default
+ * options.
+ *
+ * @param file config file
+ */
+ private void loadConfigFile(String file) {
+ try {
+ File configFile = new File(file);
+ if (!configFile.exists()) {
+ throw new FileNotFoundException("Configuration file not found!");
+ }
+
+ Properties configProperties = new Properties();
+ FileInputStream stream = new FileInputStream(configFile);
+ configProperties.load(stream);
+ stream.close();
+
+ for (Object optionObject : options.getOptions()) {
+ Option option = (Option) optionObject;
+ Object optionValue;
+
+ if ((optionValue = configProperties.get(option.getLongOpt())) != null) {
+ log.debug("Configuration option loaded: " + option.getLongOpt() + " (" + option.getType() + ") -> "
+ + optionValue);
+
+ if (option.equals(cassandraHostsOption)) {
+ String[] cassandraHosts = parseCassandraHosts(optionValue.toString());
+ configuration.put(option, cassandraHosts);
+ } else if (option.equals(sqlServerType)) {
+ if ("oracle".equals(optionValue)) {
+ configuration.put(option, "oracle");
+ } else {
+ configuration.put(option, "postgres");
+ }
+ } else if (option.equals(sqlPostgresServer)) {
+ boolean value = tryParseBoolean(optionValue.toString(), true);
+ if (value == true) {
+ configuration.put(sqlServerType, "postgres");
+ }
+ } else if (option.equals(sqlOracleServer)) {
+ boolean value = tryParseBoolean(optionValue.toString(), true);
+ if (value == true) {
+ configuration.put(sqlServerType, "oracle");
+ }
+ } else if (option.getType().equals(Boolean.class)) {
+ configuration.put(option, tryParseBoolean(optionValue.toString(), true));
+ } else if (option.getType().equals(Integer.class)) {
+ configuration.put(option, tryParseInteger(optionValue.toString(), 0));
+ } else {
+ configuration.put(option, optionValue.toString());
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.error("Unable to load or process the configuration file.", e);
+ System.exit(1);
+ }
+
+ log.debug(configuration.toString());
+ }
+
+ /**
+ * Parse command line options for Cassandra.
+ *
+ * @param commandLine command line
+ * @throws NoHostAvailableException
+ */
+ private void parseCassandraOptions(CommandLine commandLine) throws Exception {
+ if (commandLine.hasOption(cassandraUserOption.getLongOpt())) {
+ configuration.put(cassandraUserOption, commandLine.getOptionValue(cassandraUserOption.getLongOpt()));
+ }
+
+ if (commandLine.hasOption(cassandraPasswordOption.getLongOpt())) {
+ configuration
+ .put(cassandraPasswordOption, commandLine.getOptionValue(cassandraPasswordOption.getLongOpt()));
+ }
+
+ if (commandLine.hasOption(cassandraHostsOption.getLongOpt())) {
+ String[] cassandraHosts = parseCassandraHosts(commandLine.getOptionValue(cassandraHostsOption.getLongOpt()));
+ configuration.put(cassandraHostsOption, cassandraHosts);
+ }
+
+ if (commandLine.hasOption(cassandraPortOption.getLongOpt())) {
+ Integer cassandraPort = tryParseInteger(commandLine.getOptionValue(cassandraPortOption.getLongOpt()),
+ DEFAULT_CASSANDRA_PORT);
+ configuration.put(cassandraPortOption, cassandraPort);
+ }
+
+ if (commandLine.hasOption(cassandraCompressionOption.getLongOpt())) {
+ boolean value = tryParseBoolean(commandLine.getOptionValue(cassandraCompressionOption.getLongOpt()), true);
+ configuration.put(cassandraCompressionOption, value);
+ }
+ }
+
+ /**
+ * Parse command line options for SQL.
+ *
+ * @param commandLine command line
+ * @throws NoHostAvailableException
+ */
+ private void parseSQLOptions(CommandLine commandLine) throws NoHostAvailableException {
+ if (commandLine.hasOption(sqlUserOption.getLongOpt())) {
+ configuration.put(sqlUserOption, commandLine.getOptionValue(sqlUserOption.getLongOpt()));
+ }
+
+ if (commandLine.hasOption(sqlPasswordOption.getLongOpt())) {
+ configuration.put(sqlPasswordOption, commandLine.getOptionValue(sqlPasswordOption.getLongOpt()));
+ }
+
+ if (commandLine.hasOption(sqlHostOption.getLongOpt())) {
+ configuration.put(sqlHostOption, commandLine.getOptionValue(sqlHostOption.getLongOpt()));
+ }
+
+ if (commandLine.hasOption(sqlPortOption.getLongOpt())) {
+ configuration.put(sqlPortOption, commandLine.getOptionValue(sqlPortOption.getLongOpt()));
+ }
+
+ if (commandLine.hasOption(sqlDBOption.getLongOpt())) {
+ configuration.put(sqlDBOption, commandLine.getOptionValue(sqlDBOption.getLongOpt()));
+ }
+
+ if (commandLine.hasOption(sqlServerType.getLongOpt())) {
+ if ("oracle".equals(commandLine.getOptionValue(sqlServerType.getLongOpt()))) {
+ configuration.put(sqlServerType, "oracle");
+ } else {
+ configuration.put(sqlServerType, "postgres");
+ }
+ } else if (commandLine.hasOption(sqlPostgresServer.getLongOpt())) {
+ configuration.put(sqlServerType, "postgres");
+ } else if (commandLine.hasOption(sqlOracleServer.getLongOpt())) {
+ configuration.put(sqlServerType, "oracle");
+ }
+ }
+
+ /**
+ * Parse command line options for the actual migration progress.
+ *
+ * @param commandLine
+ */
+ private void parseMigrationOptions(CommandLine commandLine) {
+ boolean value;
+
+ if (commandLine.hasOption(disableRawOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(disableRawOption.getLongOpt()), true);
+ configuration.put(disableRawOption, value);
+ }
+
+ if (commandLine.hasOption(disable1HOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(disable1HOption.getLongOpt()), true);
+ configuration.put(disable1HOption, value);
+ }
+
+ if (commandLine.hasOption(disable6HOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(disable6HOption.getLongOpt()), true);
+ configuration.put(disable6HOption, value);
+ }
+
+ if (commandLine.hasOption(disable1DOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(disable1DOption.getLongOpt()), true);
+ configuration.put(disable1DOption, value);
+ }
+
+ if (commandLine.hasOption(preserveDataOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(preserveDataOption.getLongOpt()), true);
+ configuration.put(preserveDataOption, value);
+ } else if (commandLine.hasOption(deleteDataOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(deleteDataOption.getLongOpt()), true);
+ configuration.put(preserveDataOption, value);
+ }
+
+ if (commandLine.hasOption(estimateOnlyOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(estimateOnlyOption.getLongOpt()), true);
+ configuration.put(estimateOnlyOption, value);
+ }
+
+ if (commandLine.hasOption(experimentalExportOption.getLongOpt())) {
+ value = tryParseBoolean(commandLine.getOptionValue(experimentalExportOption.getLongOpt()), true);
+ configuration.put(experimentalExportOption, value);
+ }
+ }
+
+ private void run() throws Exception {
+ log.debug("Creating Entity Manager");
+ EntityManager entityManager = this.createEntityManager();
+ log.debug("Done creating Entity Manager");
+
+ log.debug("Creating Cassandra session");
+ Session session = this.createCassandraSession();
+ log.debug("Done creating Cassandra session");
+
+ DatabaseType databaseType = DatabaseType.Postgres;
+ if ("oracle".equals(configuration.get(sqlServerType))) {
+ databaseType = databaseType.Oracle;
+ }
+ DataMigrator migrator = new DataMigrator(entityManager, session, databaseType, tryParseBoolean(
+ configuration.get(experimentalExportOption), false));
+
+ if (!(Boolean) configuration.get(deleteOnlyOption)) {
+ if ((Boolean) configuration.get(preserveDataOption)) {
+ migrator.preserveData();
+ } else {
+ migrator.deleteAllDataAtEndOfMigration();
+ }
+
+ migrator.runRawDataMigration(!(Boolean) configuration.get(disableRawOption));
+ migrator.run1HAggregateDataMigration(!(Boolean) configuration.get(disable1HOption));
+ migrator.run6HAggregateDataMigration(!(Boolean) configuration.get(disable6HOption));
+ migrator.run1DAggregateDataMigration(!(Boolean) configuration.get(disable1DOption));
+
+ System.out.println("Estimation process - starting\n");
+ long estimate = migrator.estimate();
+ System.out.println("The migration process will take approximately: "
+ + TimeUnit.MILLISECONDS.toMinutes(estimate) + " minutes (or " + estimate + " milliseconds)\n");
+ System.out.println("Estimation process - ended\n\n");
+
+ if (!(Boolean) configuration.get(estimateOnlyOption)) {
+ System.out.println("Migration process - starting\n");
+ long startTime = System.currentTimeMillis();
+ migrator.migrateData();
+ long duration = System.currentTimeMillis() - startTime;
+ System.out.println("The migration process took: " + TimeUnit.MILLISECONDS.toMinutes(duration)
+ + " minutes (or " + duration + " milliseconds)\n");
+ System.out.println("Migration process - ended\n");
+ }
+ } else {
+ migrator.deleteAllDataAtEndOfMigration();
+ migrator.runRawDataMigration(true);
+ migrator.run1HAggregateDataMigration(true);
+ migrator.run6HAggregateDataMigration(true);
+ migrator.run1DAggregateDataMigration(true);
+
+ System.out.println("Estimation process - starting\n");
+ long estimate = migrator.estimate();
+ System.out.println("The deletion of old data will take approximately: "
+ + TimeUnit.MILLISECONDS.toMinutes(estimate) + " minutes (or " + estimate + " milliseconds)\n");
+ System.out.println("Estimation process - ended\n\n");
+
+ if (!(Boolean) configuration.get(estimateOnlyOption)) {
+ System.out.println("Old data deletion process - starting\n");
+ long startTime = System.currentTimeMillis();
+ migrator.deleteOldData();
+ long duration = System.currentTimeMillis() - startTime;
+ System.out.println("The deletion process took: " + TimeUnit.MILLISECONDS.toMinutes(duration)
+ + " minutes (or " + duration + " milliseconds)\n");
+ System.out.println("Old data deletion process - ended\n");
+ }
+ }
+
+ /*if (entityManager != null) {
+ entityManager.close();
+ }
+ if (entityManagerFactory != null) {
+ entityManagerFactory.close();
+ }*/
+ }
+
+ /**
+ * Create a Cassandra session based on configuration options.
+ *
+ * @return Cassandra session
+ * @throws Exception
+ */
+ private Session createCassandraSession() throws Exception {
+ Compression selectedCompression = Compression.NONE;
+ if ((Boolean) configuration.get(cassandraCompressionOption)) {
+ selectedCompression = Compression.SNAPPY;
+ }
+
+ Cluster cluster = Cluster
+ .builder()
+ .addContactPoints((String[]) configuration.get(cassandraHostsOption))
+ .withPort((Integer) configuration.get(cassandraPortOption))
+ .withCompression(selectedCompression)
+ .withoutMetrics()
+ .withCredentials((String) configuration.get(cassandraUserOption),
+ (String) configuration.get(cassandraPasswordOption))
+ .build();
+
+ return cluster.connect("rhq");
+ }
+
+ /**
+ * Create a hibernate session to the SQL server.
+ *
+ * @return
+ * @throws Exception
+ */
+ private EntityManager createEntityManager() throws Exception {
+ Properties properties = new Properties();
+ properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
+ properties.put("hibernate.connection.username", (String) configuration.get(sqlUserOption));
+ properties.put("hibernate.connection.password", (String) configuration.get(sqlPasswordOption));
+ properties.put("javax.persistence.query.timeout", DataMigrator.SQL_TIMEOUT);
+ properties.put("hibernate.c3p0.timeout", DataMigrator.SQL_TIMEOUT);
+
+ if ("oracle".equals(configuration.get(sqlServerType))) {
+ String driverClassName = "oracle.jdbc.driver.OracleDriver";
+
+ try {
+ //Required to preload the driver manually.
+ //Without this the driver load will fail due to the packaging.
+ Class.forName(driverClassName);
+ } catch (ClassNotFoundException e) {
+ log.debug(e);
+ throw new Exception("Oracle SQL Driver class could not be loaded. Missing class: " + driverClassName);
+ }
+
+ properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
+ properties.put("hibernate.driver_class", driverClassName);
+ properties.put("hibernate.connection.url", "jdbc:oracle:thin:@" + (String) configuration.get(sqlHostOption)
+ + ":" + (String) configuration.get(sqlPortOption) + ":" + (String) configuration.get(sqlDBOption));
+ properties.put("hibernate.default_schema", (String) configuration.get(sqlDBOption));
+ properties.put("hibernate.connection.oracle.jdbc.ReadTimeout", DataMigrator.SQL_TIMEOUT);
+ } else {
+ String driverClassName = "org.postgresql.Driver";
+
+ try {
+ //Required to preload the driver manually.
+ //Without this the driver load will fail due to the packaging.
+ Class.forName(driverClassName);
+ } catch (ClassNotFoundException e) {
+ log.debug(e);
+ throw new Exception("Postgres SQL Driver class could not be loaded. Missing class: " + driverClassName);
+ }
+
+ properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
+ properties.put("hibernate.driver_class", driverClassName);
+ properties.put("hibernate.connection.url", "jdbc:postgresql://" + (String) configuration.get(sqlHostOption)
+ + ":" + (String) configuration.get(sqlPortOption) + "/" + (String) configuration.get(sqlDBOption));
+ }
+
+ log.debug("Creating entity manager with the following configuration:");
+ log.debug(properties);
+
+ Ejb3Configuration configuration = new Ejb3Configuration();
+ configuration.setProperties(properties);
+ EntityManagerFactory factory = configuration.buildEntityManagerFactory();
+ return factory.createEntityManager();
+ }
+
+ /**
+ * Parse Cassandra host information submitted in the form:
+ * host_addres,jmx_port,native_port|host_address_2,jmx_port,native_port
+ *
+ * @param stringValue
+ * @return
+ */
+ private String[] parseCassandraHosts(String stringValue) {
+ String[] seeds = stringValue.split(",");
+ return seeds;
+ }
+
+ /**
+ * @param value object value to parse
+ * @param defaultValue default value
+ * @return
+ */
+ private boolean tryParseBoolean(Object value, boolean defaultValue) {
+ try {
+ return Boolean.parseBoolean(value.toString());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * @param value object value to parse
+ * @param defaultValue default value
+ * @return
+ */
+ private Integer tryParseInteger(Object value, int defaultValue) {
+ try {
+ return Integer.parseInt(value.toString());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ @SuppressWarnings("serial")
+ private class HelpRequestedException extends Exception {
+ public HelpRequestedException() {
+ super("Help Requested");
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java
new file mode 100644
index 0000000..756d1b1
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataBulkExportSource.java
@@ -0,0 +1,124 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.util.stream.StreamUtil;
+
+/**
+ * @author Thomas Segismont
+ */
+public abstract class ExistingDataBulkExportSource implements ExistingDataSource {
+
+ private static final Log log = LogFactory.getLog(ExistingDataBulkExportSource.class);
+
+ protected static final int IO_BUFFER_SIZE = 1024 * 64;
+
+ protected static final String DELIMITER = "|";
+
+ private File existingDataFile;
+
+ private BufferedReader existingDataFileReader;
+
+ private int currentIndex;
+
+ public ExistingDataBulkExportSource() {
+ Random random = new Random();
+ String exportFileName = System.currentTimeMillis() + "." + random.nextInt() + ".export";
+ this.existingDataFile = new File(System.getProperty("java.io.tmpdir"), exportFileName);
+ }
+
+ @Override
+ public void initialize() throws Exception {
+ this.exportExistingData();
+ this.startReading();
+ }
+
+ @Override
+ public void close() throws Exception {
+ this.stopReading();
+ this.removeTempFile();
+ }
+
+ protected abstract void exportExistingData() throws Exception;
+
+ protected File getExistingDataFile() {
+ return existingDataFile;
+ }
+
+ protected void startReading() throws Exception {
+ if (!existingDataFile.exists() && !existingDataFile.isFile() && !existingDataFile.canRead()) {
+ throw new IllegalStateException();
+ }
+ existingDataFileReader = new BufferedReader(new FileReader(existingDataFile));
+ currentIndex = 0;
+ }
+
+ protected void stopReading() {
+ StreamUtil.safeClose(existingDataFileReader);
+ }
+
+ protected void removeTempFile(){
+ if(this.existingDataFile.exists()){
+ try{
+ this.existingDataFile.delete();
+ }catch(Exception e){
+ log.debug("Unable to clean temporary file " + this.existingDataFile, e);
+ }
+ }
+ }
+
+ @Override
+ public List<Object[]> getData(int fromIndex, int maxResults) throws Exception {
+ if (log.isDebugEnabled()) {
+ log.debug("Reading lines " + fromIndex + " to " + (fromIndex + maxResults));
+ }
+
+ if (fromIndex != currentIndex) {
+ throw new IllegalStateException();
+ }
+
+ List<Object[]> results = new LinkedList<Object[]>();
+ for (int i = 0; i < maxResults; i++) {
+ String nextLine = existingDataFileReader.readLine();
+ if (nextLine == null) {
+ break;
+ }
+ currentIndex++;
+ StringTokenizer stringTokenizer = new StringTokenizer(nextLine, DELIMITER);
+ Object[] row = new Object[stringTokenizer.countTokens()];
+ for (int j = 0; j < row.length; j++) {
+ row[j] = stringTokenizer.nextToken();
+ }
+ results.add(row);
+ }
+ return results;
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java
new file mode 100644
index 0000000..fde9096
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPABulkExportSource.java
@@ -0,0 +1,58 @@
+package org.rhq.server.metrics.migrator;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import javax.persistence.EntityManager;
+
+import org.hibernate.Session;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.core.util.stream.StreamUtil;
+
+/**
+ * @author Thomas Segismont
+ */
+public class ExistingDataJPABulkExportSource extends ExistingDataBulkExportSource {
+
+ private EntityManager entityManager;
+ private String selectNativeQuery;
+
+ public ExistingDataJPABulkExportSource(EntityManager entityManager, String selectNativeQuery) {
+ super();
+ }
+
+ protected void exportExistingData() throws Exception {
+ BufferedWriter fileWriter = null;
+ Connection connection = null;
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+ try {
+ fileWriter = new BufferedWriter(new FileWriter(getExistingDataFile()), IO_BUFFER_SIZE);
+ Session session = (Session) this.entityManager.getDelegate();
+ SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
+ ConnectionProvider cp = sfi.getConnectionProvider();
+ connection = cp.getConnection();
+ statement = connection.prepareStatement(this.selectNativeQuery);
+ resultSet = statement.executeQuery();
+ int columnCount = resultSet.getMetaData().getColumnCount();
+ while (resultSet.next()) {
+ for (int i = 1; i < columnCount + 1; i++) {
+ if (i > 1) {
+ fileWriter.write(DELIMITER);
+ }
+ fileWriter.write(resultSet.getString(i));
+ }
+ fileWriter.write("\n");
+ }
+ } finally {
+ StreamUtil.safeClose(fileWriter);
+ JDBCUtil.safeClose(connection, statement, resultSet);
+ }
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java
new file mode 100644
index 0000000..9aca36a
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataJPASource.java
@@ -0,0 +1,64 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Thomas Segismont
+ */
+public class ExistingDataJPASource implements ExistingDataSource {
+
+ private static final Log log = LogFactory.getLog(ExistingDataJPASource.class);
+
+ private EntityManager entityManager;
+ private String selectNativeQuery;
+
+ public ExistingDataJPASource(EntityManager entityManager, String selectNativeQuery) {
+ this.entityManager = entityManager;
+ this.selectNativeQuery = selectNativeQuery;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<Object[]> getData(int fromIndex, int maxResults) throws Exception {
+ if (log.isDebugEnabled()) {
+ log.debug("Reading lines " + fromIndex + " to " + (fromIndex + maxResults));
+ }
+
+ return (List<Object[]>) entityManager.createNativeQuery(selectNativeQuery).setFirstResult(fromIndex)
+ .setMaxResults(maxResults).getResultList();
+ }
+
+ @Override
+ public void initialize() {
+ //nothing to do since it just implements a simple query with limits
+ }
+
+ @Override
+ public void close() {
+ //nothing to do since it just implements a simple query with limits
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java
new file mode 100644
index 0000000..033c5d9
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingDataSource.java
@@ -0,0 +1,36 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import java.util.List;
+
+/**
+ * @author Thomas Segismont
+ */
+public interface ExistingDataSource {
+
+ static final int TIMEOUT = 6000000;
+
+ List<Object[]> getData(int fromIndex, int maxResults) throws Exception;
+
+ void initialize() throws Exception;
+
+ void close() throws Exception;
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java
new file mode 100644
index 0000000..2ba7e4a
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ExistingPostgresDataBulkExportSource.java
@@ -0,0 +1,80 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.sql.Connection;
+
+import javax.persistence.EntityManager;
+
+import org.hibernate.Session;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.postgresql.copy.CopyManager;
+import org.postgresql.core.BaseConnection;
+
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.core.util.stream.StreamUtil;
+
+/**
+ * @author Thomas Segismont
+ */
+public class ExistingPostgresDataBulkExportSource extends ExistingDataBulkExportSource {
+
+ private final EntityManager entityManager;
+ private final String selectNativeQuery;
+ private final int maxResults;
+
+ public ExistingPostgresDataBulkExportSource(EntityManager entityManager, String selectNativeQuery) {
+ this(entityManager, selectNativeQuery, -1);
+ }
+
+ public ExistingPostgresDataBulkExportSource(EntityManager entityManager, String selectNativeQuery, int maxResults) {
+ super();
+ this.entityManager = entityManager;
+ this.selectNativeQuery = selectNativeQuery;
+ this.maxResults = maxResults;
+ }
+
+ protected void exportExistingData() throws Exception {
+ BufferedWriter fileWriter = null;
+ Connection connection = null;
+ try {
+ fileWriter = new BufferedWriter(new FileWriter(getExistingDataFile()), IO_BUFFER_SIZE);
+ Session session = (Session) entityManager.getDelegate();
+ SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
+ ConnectionProvider cp = sfi.getConnectionProvider();
+ connection = cp.getConnection();
+ CopyManager copyManager = new CopyManager((BaseConnection) connection);
+
+ if (maxResults > 0) {
+ copyManager.copyOut("COPY (" + selectNativeQuery + " LIMIT " + maxResults
+ + ") TO STDOUT WITH DELIMITER '" + DELIMITER + "'", fileWriter);
+ } else {
+ copyManager.copyOut("COPY (" + selectNativeQuery + ") TO STDOUT WITH DELIMITER '" + DELIMITER + "'",
+ fileWriter);
+ }
+ } finally {
+ StreamUtil.safeClose(fileWriter);
+ JDBCUtil.safeClose(connection);
+ }
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java
new file mode 100644
index 0000000..42161a4
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/ScrollableDataSource.java
@@ -0,0 +1,156 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.Query;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.Session;
+import org.hibernate.StatelessSession;
+
+import org.rhq.server.metrics.migrator.DataMigrator.DatabaseType;
+
+/**
+ * @author Stefan Negrea
+ */
+public class ScrollableDataSource implements ExistingDataSource {
+
+ private static final Log log = LogFactory.getLog(ScrollableDataSource.class);
+
+ private final EntityManager entityManager;
+ private final DatabaseType databaseType;
+ private final String selectNativeQuery;
+ private final int maxResults;
+
+ private ScrollableResults results;
+ private StatelessSession session;
+ private int lastMigratedItemIndex;
+
+
+ public ScrollableDataSource(EntityManager entityManager, DatabaseType databaseType,
+ String selectNativeQuery) {
+ this(entityManager, databaseType, selectNativeQuery, -1);
+ }
+
+ public ScrollableDataSource(EntityManager entityManager, DatabaseType databaseType, String selectNativeQuery,
+ int maxResults) {
+ this.entityManager = entityManager;
+ this.databaseType = databaseType;
+ this.selectNativeQuery = selectNativeQuery;
+ this.maxResults = maxResults;
+ }
+
+ @Override
+ public List<Object[]> getData(int fromIndex, int maxResults) throws Exception {
+ if (fromIndex != lastMigratedItemIndex + 1) {
+ throw new Exception("Cursor error. " + fromIndex + " " + lastMigratedItemIndex);
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Reading lines " + fromIndex + " to " + (fromIndex + maxResults));
+ }
+
+ List<Object[]> resultList = new ArrayList<Object[]>();
+
+ int maxLimit = lastMigratedItemIndex + maxResults;
+
+ while (results.next()) {
+ resultList.add(results.get());
+
+ if (++lastMigratedItemIndex == maxLimit) {
+ break;
+ }
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Read lines " + fromIndex + " to " + (fromIndex + maxResults));
+ }
+
+ return resultList;
+ }
+
+ @Override
+ public void initialize() {
+ if (session != null || results != null) {
+ close();
+ }
+
+ session = ((Session) entityManager.getDelegate()).getSessionFactory().openStatelessSession();
+
+ this.prepareSQLSession();
+
+ if (log.isDebugEnabled()) {
+ if (maxResults >= 0) {
+ log.debug("Preparing the query with " + maxResults + " results.");
+ } else {
+ log.debug("Preparing the query with all the results.");
+ }
+ }
+
+ Query query = session.createSQLQuery(selectNativeQuery);
+ if (maxResults >= 0) {
+ query.setMaxResults(maxResults);
+ }
+ query.setFetchSize(30000);
+ query.setReadOnly(true);
+ query.setTimeout(TIMEOUT);
+ results = query.scroll(ScrollMode.FORWARD_ONLY);
+
+ lastMigratedItemIndex = -1;
+
+ if (log.isDebugEnabled()) {
+ if (maxResults >= 0) {
+ log.debug("Query prepared with " + maxResults + " results.");
+ } else {
+ log.debug("Query prepared with all the results.");
+ }
+ }
+ }
+
+ @Override
+ public void close() {
+ if (results != null) {
+ results.close();
+ results = null;
+ }
+
+ if (session != null) {
+ session.close();
+ session = null;
+ }
+ }
+
+ private void prepareSQLSession() {
+ if (DatabaseType.Postgres.equals(this.databaseType)) {
+ log.debug("Preparing SQL connection with timeout: " + DataMigrator.SQL_TIMEOUT);
+
+ Query query = session.createSQLQuery("SET LOCAL statement_timeout = " + DataMigrator.SQL_TIMEOUT);
+ query.setReadOnly(true);
+ query.executeUpdate();
+ }
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java
new file mode 100644
index 0000000..92bf37a
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/Telemetry.java
@@ -0,0 +1,57 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator;
+
+import org.apache.commons.lang.time.StopWatch;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class Telemetry {
+ private StopWatch generalTimer;
+ private StopWatch migrationTimer;
+
+ public Telemetry() {
+ this.generalTimer = new StopWatch();
+ this.migrationTimer = new StopWatch();
+ }
+
+ public StopWatch getGeneralTimer() {
+ return generalTimer;
+ }
+
+ public StopWatch getMigrationTimer() {
+ return migrationTimer;
+ }
+
+ public long getMigrationTime() {
+ return migrationTimer.getTime();
+ }
+
+ public long getGeneralTime() {
+ return generalTimer.getTime();
+ }
+
+ public long getNonMigrationTime() {
+ return this.getGeneralTime() - this.getMigrationTime();
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java
new file mode 100644
index 0000000..3c006be
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AbstractMigrationWorker.java
@@ -0,0 +1,123 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator.workers;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.StatelessSession;
+
+import org.rhq.server.metrics.migrator.DataMigrator;
+import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
+import org.rhq.server.metrics.migrator.DataMigrator.DatabaseType;
+import org.rhq.server.metrics.migrator.DataMigrator.Task;
+import org.rhq.server.metrics.migrator.ExistingDataSource;
+import org.rhq.server.metrics.migrator.ExistingPostgresDataBulkExportSource;
+import org.rhq.server.metrics.migrator.ScrollableDataSource;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public abstract class AbstractMigrationWorker {
+ private final Log log = LogFactory.getLog(AbstractMigrationWorker.class);
+
+ /**
+ * Returns a list of all the raw SQL metric tables.
+ * There is no equivalent in Cassandra, all raw data is stored in a single column family.
+ *
+ * @return SQL raw metric tables
+ */
+ protected static String[] getRawDataTables() {
+ int tableCount = 15;
+ String tablePrefix = "RHQ_MEAS_DATA_NUM_R";
+
+ String[] tables = new String[tableCount];
+ for (int i = 0; i < tableCount; i++) {
+ if (i < 10) {
+ tables[i] = tablePrefix + "0" + i;
+ } else {
+ tables[i] = tablePrefix + i;
+ }
+ }
+
+ return tables;
+ }
+
+ protected ExistingDataSource getExistingDataSource(String query, Task task, DataMigratorConfiguration config) {
+ if (Task.Migrate.equals(task)) {
+ if (DatabaseType.Oracle.equals(config.getDatabaseType())) {
+ return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query);
+ } else {
+ if (!config.isExperimentalDataSource()) {
+ return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query);
+ } else {
+ return new ExistingPostgresDataBulkExportSource(config.getEntityManager(), query);
+ }
+ }
+ } else if (Task.Estimate.equals(task)) {
+ int limit = CallableMigrationWorker.MAX_RECORDS_TO_LOAD_FROM_SQL
+ * (CallableMigrationWorker.NUMBER_OF_BATCHES_FOR_ESTIMATION + 1);
+
+ if (DatabaseType.Oracle.equals(config.getDatabaseType())) {
+ return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query, limit);
+ } else {
+ if (!config.isExperimentalDataSource()) {
+ return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query, limit);
+ } else {
+ return new ExistingPostgresDataBulkExportSource(config.getEntityManager(), query, limit);
+ }
+ }
+ }
+
+ return new ScrollableDataSource(config.getEntityManager(), config.getDatabaseType(), query);
+ }
+
+ protected void prepareSQLSession(StatelessSession session, DataMigratorConfiguration config) {
+ if (DatabaseType.Postgres.equals(config.getDatabaseType())) {
+ log.debug("Preparing SQL connection with timeout: " + DataMigrator.SQL_TIMEOUT);
+
+ org.hibernate.Query query = session.createSQLQuery("SET LOCAL statement_timeout = "
+ + DataMigrator.SQL_TIMEOUT);
+ query.setReadOnly(true);
+ query.executeUpdate();
+ }
+ }
+
+ protected StatelessSession getSQLSession(DataMigratorConfiguration config) {
+ StatelessSession session = ((org.hibernate.Session) config.getEntityManager().getDelegate())
+ .getSessionFactory().openStatelessSession();
+
+ prepareSQLSession(session, config);
+
+ return session;
+ }
+
+ protected void closeSQLSession(StatelessSession session) {
+ try {
+ if (session != null) {
+ session.close();
+ }
+ } catch (Exception e) {
+ //log.debug("Unable to close SQL stateless session. " + e);
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java
new file mode 100644
index 0000000..5511321
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/AggregateDataMigrator.java
@@ -0,0 +1,262 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator.workers;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.ttl;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.datastax.driver.core.ResultSetFuture;
+import com.datastax.driver.core.querybuilder.Batch;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.StatelessSession;
+
+import org.rhq.server.metrics.domain.AggregateType;
+import org.rhq.server.metrics.domain.MetricsTable;
+import org.rhq.server.metrics.migrator.DataMigrator;
+import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
+import org.rhq.server.metrics.migrator.DataMigrator.Task;
+import org.rhq.server.metrics.migrator.ExistingDataSource;
+import org.rhq.server.metrics.migrator.Telemetry;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class AggregateDataMigrator extends AbstractMigrationWorker implements CallableMigrationWorker {
+
+ private final Log log = LogFactory.getLog(AggregateDataMigrator.class);
+
+ private final DataMigratorConfiguration config;
+ private final String selectQuery;
+ private final String deleteQuery;
+ private final String countQuery;
+ private final MetricsTable metricsTable;
+ private final MetricsIndexUpdateAccumulator metricsIndexAccumulator;
+
+ /**
+ * @param query
+ * @param metricsTable
+ */
+ public AggregateDataMigrator(MetricsTable metricsTable, DataMigratorConfiguration config)
+ throws Exception {
+
+ this.metricsTable = metricsTable;
+ this.config = config;
+
+ if (MetricsTable.ONE_HOUR.equals(this.metricsTable)) {
+ this.selectQuery = MigrationQuery.SELECT_1H_DATA.toString();
+ this.deleteQuery = MigrationQuery.DELETE_1H_DATA.toString();
+ this.countQuery = MigrationQuery.COUNT_1H_DATA.toString();
+ } else if (MetricsTable.SIX_HOUR.equals(this.metricsTable)) {
+ this.selectQuery = MigrationQuery.SELECT_6H_DATA.toString();
+ this.deleteQuery = MigrationQuery.DELETE_6H_DATA.toString();
+ this.countQuery = MigrationQuery.COUNT_6H_DATA.toString();
+ } else if (MetricsTable.TWENTY_FOUR_HOUR.equals(this.metricsTable)) {
+ this.selectQuery = MigrationQuery.SELECT_1D_DATA.toString();
+ this.deleteQuery = MigrationQuery.DELETE_1D_DATA.toString();
+ this.countQuery = MigrationQuery.COUNT_1D_DATA.toString();
+ } else {
+ throw new Exception("MetricsTable " + metricsTable.toString() + " not supported by this migrator.");
+ }
+
+ metricsIndexAccumulator = new MetricsIndexUpdateAccumulator(metricsTable, config);
+ }
+
+ @Override
+ public long estimate() throws Exception {
+ long recordCount = this.getRowCount(this.countQuery);
+ log.debug("Retrieved record count for table " + metricsTable.toString() + " -- " + recordCount);
+
+ Telemetry telemetry = this.performMigration(Task.Estimate);
+ long estimatedTimeToMigrate = telemetry.getMigrationTime();
+
+ long estimation = (recordCount / (long) MAX_RECORDS_TO_LOAD_FROM_SQL / (long) NUMBER_OF_BATCHES_FOR_ESTIMATION)
+ * estimatedTimeToMigrate;
+
+ estimation += telemetry.getNonMigrationTime();
+
+ return estimation;
+ }
+
+ public void migrate() throws Exception {
+ performMigration(Task.Migrate);
+ if (config.isDeleteDataImmediatelyAfterMigration()) {
+ deleteTableData();
+ }
+ }
+
+ private long getRowCount(String countQuery) {
+ StatelessSession session = getSQLSession(config);
+
+ org.hibernate.Query query = session.createSQLQuery(countQuery);
+ query.setReadOnly(true);
+ query.setTimeout(DataMigrator.SQL_TIMEOUT);
+ long count = Long.parseLong(query.uniqueResult().toString());
+
+ closeSQLSession(session);
+
+ return count;
+ }
+
+ private void deleteTableData() throws Exception {
+ int failureCount = 0;
+ while (failureCount < MAX_NUMBER_OF_FAILURES) {
+ try {
+ StatelessSession session = getSQLSession(config);
+ session.getTransaction().begin();
+ org.hibernate.Query nativeQuery = session.createSQLQuery(this.deleteQuery);
+ nativeQuery.executeUpdate();
+ session.getTransaction().commit();
+ closeSQLSession(session);
+ log.info("- " + metricsTable.toString() + " - Cleaned -");
+ } catch (Exception e) {
+ log.error("Failed to delete " + metricsTable.toString()
+ + " data. Attempting to delete data one more time...");
+
+ failureCount++;
+ if (failureCount == MAX_NUMBER_OF_FAILURES) {
+ throw e;
+ }
+ }
+ }
+ }
+
+ private Telemetry performMigration(Task task) throws Exception {
+ Telemetry telemetry = new Telemetry();
+ telemetry.getGeneralTimer().start();
+
+ long numberOfBatchesMigrated = 0;
+
+ List<Object[]> existingData;
+ int failureCount;
+
+ int lastMigratedRecord = 0;
+ ExistingDataSource dataSource = getExistingDataSource(selectQuery, task, config);
+ dataSource.initialize();
+
+ telemetry.getMigrationTimer().start();
+ while (true) {
+ existingData = dataSource.getData(lastMigratedRecord, MAX_RECORDS_TO_LOAD_FROM_SQL);
+
+ if (existingData.size() == 0) {
+ break;
+ }
+
+ lastMigratedRecord += existingData.size();
+
+ failureCount = 0;
+ while (failureCount < MAX_NUMBER_OF_FAILURES) {
+ try {
+ insertDataToCassandra(existingData);
+ break;
+ } catch (Exception e) {
+ log.error("Failed to insert " + metricsTable.toString()
+ + " data. Attempting to insert the current batch of data one more time");
+ log.error(e);
+
+ failureCount++;
+ if (failureCount == MAX_NUMBER_OF_FAILURES) {
+ throw e;
+ }
+ }
+ }
+
+ log.info("- " + metricsTable + " - " + lastMigratedRecord + " -");
+
+ numberOfBatchesMigrated++;
+ if (Task.Estimate.equals(task) && numberOfBatchesMigrated >= NUMBER_OF_BATCHES_FOR_ESTIMATION) {
+ break;
+ }
+ }
+
+ metricsIndexAccumulator.drain();
+
+ telemetry.getMigrationTimer().stop();
+
+ dataSource.close();
+ telemetry.getGeneralTimer().stop();
+
+ return telemetry;
+ }
+
+ private void insertDataToCassandra(List<Object[]> existingData) throws Exception {
+ List<ResultSetFuture> resultSetFutures = new ArrayList<ResultSetFuture>();
+ Batch batch = QueryBuilder.batch();
+ int batchSize = 0;
+
+ //only need approximate TTL to speed up processing
+ //given that each batch is processed within seconds, getting the
+ //system time once per batch has minimal impact on the record retention
+ long creationTimeMillis;
+ long itemTTLSeconds;
+ long currentTimeMillis = System.currentTimeMillis();
+ long expectedTTLMillis = metricsTable.getTTLinMilliseconds();
+
+ for (Object[] rawMeasurement : existingData) {
+ creationTimeMillis = Long.parseLong(rawMeasurement[MigrationQuery.TIMESTAMP_INDEX].toString());
+ itemTTLSeconds = (expectedTTLMillis - currentTimeMillis + creationTimeMillis) / 1000l;
+
+ if (itemTTLSeconds > 0) {
+ int scheduleId = Integer.parseInt(rawMeasurement[MigrationQuery.SCHEDULE_INDEX].toString());
+ Date time = new Date(creationTimeMillis);
+
+ batch.add(QueryBuilder.insertInto(metricsTable.toString()).value("schedule_id", scheduleId)
+ .value("time", time).value("type", AggregateType.AVG.ordinal())
+ .value("value", Double.parseDouble(rawMeasurement[MigrationQuery.VALUE_INDEX].toString()))
+ .using(ttl((int) itemTTLSeconds)));
+
+ batch.add(QueryBuilder.insertInto(metricsTable.toString()).value("schedule_id", scheduleId)
+ .value("time", time).value("type", AggregateType.MIN.ordinal())
+ .value("value", Double.parseDouble(rawMeasurement[MigrationQuery.MIN_VALUE_INDEX].toString()))
+ .using(ttl((int) itemTTLSeconds)));
+
+ batch.add(QueryBuilder.insertInto(metricsTable.toString()).value("schedule_id", scheduleId)
+ .value("time", time).value("type", AggregateType.MAX.ordinal())
+ .value("value", Double.parseDouble(rawMeasurement[MigrationQuery.MAX_VALUE_INDEX].toString()))
+ .using(ttl((int) itemTTLSeconds)));
+
+ batchSize += 3;
+
+ metricsIndexAccumulator.add(scheduleId, creationTimeMillis);
+ }
+
+ if (batchSize >= MAX_AGGREGATE_BATCH_TO_CASSANDRA) {
+ resultSetFutures.add(config.getSession().executeAsync(batch));
+ batch = QueryBuilder.batch();
+ batchSize = 0;
+ }
+ }
+
+ if (batchSize != 0) {
+ resultSetFutures.add(config.getSession().executeAsync(batch));
+ }
+
+ for (ResultSetFuture future : resultSetFutures) {
+ future.get();
+ }
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java
new file mode 100644
index 0000000..05a7ac6
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/CallableMigrationWorker.java
@@ -0,0 +1,38 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator.workers;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public interface CallableMigrationWorker {
+
+ public static final int MAX_RECORDS_TO_LOAD_FROM_SQL = 30000;
+ public static final int MAX_RAW_BATCH_TO_CASSANDRA = 100;
+ public static final int MAX_AGGREGATE_BATCH_TO_CASSANDRA = 50;
+ public static final int NUMBER_OF_BATCHES_FOR_ESTIMATION = 4;
+ public static final int MAX_NUMBER_OF_FAILURES = 5;
+
+ long estimate() throws Exception;
+
+ void migrate() throws Exception;
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java
new file mode 100644
index 0000000..c1cb62c
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/DeleteAllData.java
@@ -0,0 +1,89 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator.workers;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.StatelessSession;
+
+import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class DeleteAllData extends AbstractMigrationWorker implements CallableMigrationWorker {
+
+ private final Log log = LogFactory.getLog(DeleteAllData.class);
+
+ private final DataMigratorConfiguration config;
+
+ public DeleteAllData(DataMigratorConfiguration config) {
+ this.config = config;
+ }
+
+ public void migrate() {
+ org.hibernate.Query nativeQuery;
+ StatelessSession session = getSQLSession(config);
+
+ if (config.isRun1HAggregateDataMigration()) {
+ session.getTransaction().begin();
+ nativeQuery = session.createSQLQuery(MigrationQuery.DELETE_1H_DATA.toString());
+ nativeQuery.executeUpdate();
+ session.getTransaction().commit();
+ log.info("- RHQ_MEASUREMENT_DATA_NUM_1H - Cleaned -");
+ }
+
+ if (config.isRun6HAggregateDataMigration()) {
+ session.getTransaction().begin();
+ nativeQuery = session.createSQLQuery(MigrationQuery.DELETE_6H_DATA.toString());
+ nativeQuery.executeUpdate();
+ session.getTransaction().commit();
+ log.info("- RHQ_MEASUREMENT_DATA_NUM_6H - Cleaned -");
+ }
+
+ if (config.isRun1DAggregateDataMigration()) {
+ session.getTransaction().begin();
+ nativeQuery = session.createSQLQuery(MigrationQuery.DELETE_1D_DATA.toString());
+ nativeQuery.executeUpdate();
+ session.getTransaction().commit();
+ log.info("- RHQ_MEASUREMENT_DATA_NUM_1D - Cleaned -");
+ }
+
+ if (config.isRunRawDataMigration()) {
+ for (String table : getRawDataTables()) {
+ session.getTransaction().begin();
+ String deleteAllData = String.format(MigrationQuery.DELETE_RAW_ALL_DATA.toString(), table);
+ nativeQuery = session.createSQLQuery(deleteAllData);
+ nativeQuery.executeUpdate();
+ session.getTransaction().commit();
+ log.info("- " + table + " - Cleaned -");
+ }
+ }
+
+ closeSQLSession(session);
+ }
+
+ @Override
+ public long estimate() throws Exception {
+ return 300000; // return return 5 minutes for now without any database side checks.
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java
new file mode 100644
index 0000000..d60ecf6d
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MetricsIndexUpdateAccumulator.java
@@ -0,0 +1,172 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator.workers;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.datastax.driver.core.BoundStatement;
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.ResultSetFuture;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.Query;
+import org.hibernate.StatelessSession;
+import org.joda.time.DateTime;
+import org.joda.time.Duration;
+
+import org.rhq.server.metrics.DateTimeService;
+import org.rhq.server.metrics.MetricsConfiguration;
+import org.rhq.server.metrics.domain.MetricsTable;
+import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class MetricsIndexUpdateAccumulator extends AbstractMigrationWorker {
+ private static final int MAX_SIZE = 3000;
+
+ private final Log log = LogFactory.getLog(MetricsIndexUpdateAccumulator.class);
+
+ private final DateTimeService dateTimeService = new DateTimeService();
+ private final MetricsConfiguration configuration = new MetricsConfiguration();
+ private final Map<Integer, Set<Long>> accumulator = new HashMap<Integer, Set<Long>>();
+
+ private final MetricsTable table;
+ private final DataMigratorConfiguration config;
+
+ private final long timeLimit;
+ private final PreparedStatement updateMetricsIndex;
+ private final Duration sliceDuration;
+ private final boolean validAccumulatorTable;
+
+ private int currentCount = 0;
+
+ public MetricsIndexUpdateAccumulator(MetricsTable table, DataMigratorConfiguration config) {
+ this.table = table;
+ this.config = config;
+
+ if (MetricsTable.RAW.equals(table) || MetricsTable.ONE_HOUR.equals(table)
+ || MetricsTable.SIX_HOUR.equals(table)) {
+ this.sliceDuration = configuration.getTimeSliceDuration(table);
+ this.timeLimit = this.getLastAggregationTime(table) - this.sliceDuration.getMillis();
+ this.updateMetricsIndex = config.getSession().prepare(
+ "INSERT INTO " + MetricsTable.INDEX.getTableName()
+ + " (bucket, time, schedule_id) VALUES (?, ?, ?)");
+ this.validAccumulatorTable = true;
+ } else {
+ this.timeLimit = Integer.MAX_VALUE;
+ this.updateMetricsIndex = null;
+ this.sliceDuration = null;
+ this.validAccumulatorTable = false;
+ }
+ }
+
+ public void add(int scheduleId, long timestamp) throws Exception {
+ if (validAccumulatorTable && timeLimit <= timestamp) {
+ long alignedTimeSlice = dateTimeService.getTimeSlice(timestamp, sliceDuration).getMillis();
+
+ if (accumulator.containsKey(scheduleId)) {
+ Set<Long> timestamps = accumulator.get(scheduleId);
+ if (!timestamps.contains(alignedTimeSlice)) {
+ timestamps.add(alignedTimeSlice);
+
+ currentCount++;
+ }
+ } else {
+ Set<Long> timestamps = new HashSet<Long>();
+ timestamps.add(timestamp);
+ accumulator.put(scheduleId, timestamps);
+
+ currentCount++;
+ }
+ }
+
+ if (currentCount > MAX_SIZE) {
+ drain();
+ }
+ }
+
+ public void drain() throws Exception {
+ if (log.isDebugEnabled()) {
+ log.debug("Draining metrics index accumulator with " + currentCount + " entries");
+ }
+
+ List<ResultSetFuture> resultSetFutures = new ArrayList<ResultSetFuture>();
+
+ for (Map.Entry<Integer, Set<Long>> entry : accumulator.entrySet()) {
+ for (Long timestamp : entry.getValue()) {
+ BoundStatement statement = updateMetricsIndex.bind(this.table.getTableName(), new Date(timestamp),
+ entry.getKey());
+ resultSetFutures.add(config.getSession().executeAsync(statement));
+ }
+ }
+
+ for (ResultSetFuture future : resultSetFutures) {
+ future.get();
+ }
+
+ accumulator.clear();
+ currentCount = 0;
+ }
+
+ private long getLastAggregationTime(MetricsTable migratedTable) {
+ StatelessSession session = getSQLSession(config);
+
+ long aggregationSlice = Integer.MAX_VALUE;
+ Duration duration = null;
+ String queryString = null;
+
+ if (MetricsTable.RAW.equals(migratedTable)) {
+ duration = configuration.getRawTimeSliceDuration();
+ queryString = MigrationQuery.MAX_TIMESTAMP_1H_DATA.toString();
+ } else if (MetricsTable.ONE_HOUR.equals(migratedTable)) {
+ duration = configuration.getOneHourTimeSliceDuration();
+ queryString = MigrationQuery.MAX_TIMESTAMP_6H_DATA.toString();
+ } else if (MetricsTable.SIX_HOUR.equals(migratedTable)) {
+ duration = configuration.getSixHourTimeSliceDuration();
+ queryString = MigrationQuery.MAX_TIMESTAMP_1D_DATA.toString();
+ }
+
+ if (duration != null && queryString != null) {
+ Query query = session.createSQLQuery(queryString);
+
+ Long timeStamp;
+ Object result = query.uniqueResult();
+ if(result != null){
+ String queryResult = query.uniqueResult().toString();
+ Long timestamp = Long.parseLong(queryResult);
+ aggregationSlice = dateTimeService.getTimeSlice(new DateTime(timestamp), duration).getMillis();
+ }
+ }
+
+ closeSQLSession(session);
+
+ return aggregationSlice;
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java
new file mode 100644
index 0000000..7f13349
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/MigrationQuery.java
@@ -0,0 +1,71 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator.workers;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public enum MigrationQuery {
+ SELECT_1H_DATA(
+ "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1H ORDER BY schedule_id, time_stamp"), SELECT_6H_DATA(
+ "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_6H ORDER BY schedule_id, time_stamp"), SELECT_1D_DATA(
+ "SELECT schedule_id, time_stamp, value, minvalue, maxvalue FROM RHQ_MEASUREMENT_DATA_NUM_1D ORDER BY schedule_id, time_stamp"),
+
+ DELETE_1H_DATA("DELETE FROM RHQ_MEASUREMENT_DATA_NUM_1H"), DELETE_6H_DATA("DELETE FROM RHQ_MEASUREMENT_DATA_NUM_6H"), DELETE_1D_DATA(
+ "DELETE FROM RHQ_MEASUREMENT_DATA_NUM_1D"),
+
+ COUNT_1H_DATA("SELECT COUNT(*) FROM RHQ_MEASUREMENT_DATA_NUM_1H"), COUNT_6H_DATA(
+ "SELECT COUNT(*) FROM RHQ_MEASUREMENT_DATA_NUM_6H"), COUNT_1D_DATA(
+ "SELECT COUNT(*) FROM RHQ_MEASUREMENT_DATA_NUM_1D"),
+
+ MAX_TIMESTAMP_1H_DATA("SELECT MAX(time_stamp) FROM RHQ_MEASUREMENT_DATA_NUM_1H"), MAX_TIMESTAMP_6H_DATA(
+ "SELECT MAX(time_stamp) FROM RHQ_MEASUREMENT_DATA_NUM_6H"), MAX_TIMESTAMP_1D_DATA(
+ "SELECT MAX(time_stamp) FROM RHQ_MEASUREMENT_DATA_NUM_1D"),
+
+ COUNT_RAW("SELECT COUNT(*) FROM %s"), SELECT_RAW_DATA(
+ "SELECT schedule_id, time_stamp, value FROM %s ORDER BY schedule_id, time_stamp"), DELETE_RAW_ALL_DATA(
+ "DELETE FROM %s"), DELETE_RAW_ENTRY("DELETE FROM %s WHERE schedule_id = ?");
+
+ public static final int SCHEDULE_INDEX = 0;
+ public static final int TIMESTAMP_INDEX = 1;
+ public static final int VALUE_INDEX = 2;
+ public static final int MIN_VALUE_INDEX = 3;
+ public static final int MAX_VALUE_INDEX = 4;
+
+ private String query;
+
+ private MigrationQuery(String query) {
+ this.query = query;
+ }
+
+ /**
+ * @return the query
+ */
+ public String getQuery() {
+ return query;
+ }
+
+ @Override
+ public String toString() {
+ return query;
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java
new file mode 100644
index 0000000..6680fd2
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/java/org/rhq/server/metrics/migrator/workers/RawDataMigrator.java
@@ -0,0 +1,250 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.server.metrics.migrator.workers;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.ttl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+import com.datastax.driver.core.ResultSetFuture;
+import com.datastax.driver.core.querybuilder.Batch;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.StatelessSession;
+
+import org.rhq.server.metrics.domain.MetricsTable;
+import org.rhq.server.metrics.migrator.DataMigrator;
+import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;
+import org.rhq.server.metrics.migrator.DataMigrator.Task;
+import org.rhq.server.metrics.migrator.ExistingDataSource;
+import org.rhq.server.metrics.migrator.Telemetry;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class RawDataMigrator extends AbstractMigrationWorker implements CallableMigrationWorker {
+ private final Log log = LogFactory.getLog(RawDataMigrator.class);
+
+ private final Queue<String> tablesNotProcessed = new LinkedList<String>(Arrays.asList(getRawDataTables()));
+ private final MetricsIndexUpdateAccumulator metricsIndexAccumulator;
+ private final DataMigratorConfiguration config;
+
+ public RawDataMigrator(DataMigratorConfiguration config) {
+ this.config = config;
+ this.metricsIndexAccumulator = new MetricsIndexUpdateAccumulator(MetricsTable.RAW, config);
+ }
+
+ public long estimate() throws Exception {
+ long recordCount = 0;
+ for (String table : getRawDataTables()) {
+ String countQuery = String.format(MigrationQuery.COUNT_RAW.toString(), table);
+ long tableRecordCount = this.getRowCount(countQuery);
+
+ log.debug("Retrieved record count for table " + table + " -- " + tableRecordCount);
+
+ recordCount += tableRecordCount;
+ }
+
+ Telemetry telemetry = this.performMigration(Task.Estimate);
+ long estimatedTimeToMigrate = telemetry.getMigrationTime();
+ long estimation = (recordCount / (long) MAX_RECORDS_TO_LOAD_FROM_SQL / (long) NUMBER_OF_BATCHES_FOR_ESTIMATION)
+ * estimatedTimeToMigrate;
+ estimation += telemetry.getNonMigrationTime();
+
+ return estimation;
+ }
+
+ public void migrate() throws Exception {
+ performMigration(Task.Migrate);
+ }
+
+ private long getRowCount(String countQuery) {
+ StatelessSession session = getSQLSession(config);
+
+ org.hibernate.Query query = session.createSQLQuery(countQuery);
+ query.setReadOnly(true);
+ query.setTimeout(DataMigrator.SQL_TIMEOUT);
+
+ long count = Long.parseLong(query.uniqueResult().toString());
+
+ closeSQLSession(session);
+
+ return count;
+ }
+
+ private Telemetry performMigration(Task task) throws Exception {
+ Telemetry telemetry = new Telemetry();
+ telemetry.getGeneralTimer().start();
+
+ long numberOfBatchesMigrated = 0;
+
+ List<Object[]> existingData;
+ int failureCount;
+
+ telemetry.getMigrationTimer().start();
+ telemetry.getMigrationTimer().suspend();
+
+ while (!tablesNotProcessed.isEmpty()) {
+ String table = tablesNotProcessed.peek();
+
+ String selectQuery = String.format(MigrationQuery.SELECT_RAW_DATA.toString(), table);
+
+ ExistingDataSource dataSource = getExistingDataSource(selectQuery, task, config);
+ dataSource.initialize();
+
+ log.info("Start migrating raw table: " + table);
+
+ telemetry.getMigrationTimer().resume();
+ int lastMigratedRecord = 0;
+ while (true) {
+ existingData = dataSource.getData(lastMigratedRecord, MAX_RECORDS_TO_LOAD_FROM_SQL);
+
+ if (existingData.size() == 0) {
+ break;
+ }
+
+ lastMigratedRecord += existingData.size();
+
+ failureCount = 0;
+ while (failureCount < MAX_NUMBER_OF_FAILURES) {
+ try {
+ insertDataToCassandra(existingData);
+ break;
+ } catch (Exception e) {
+ log.error("Failed to insert " + MetricsTable.RAW.toString()
+ + " data. Attempting to insert the current batch of data one more time");
+ log.error(e);
+
+ failureCount++;
+ if (failureCount == MAX_AGGREGATE_BATCH_TO_CASSANDRA) {
+ throw e;
+ }
+ }
+ }
+
+ log.info("- " + table + " - " + lastMigratedRecord + " -");
+
+ numberOfBatchesMigrated++;
+ if (Task.Estimate.equals(task) && numberOfBatchesMigrated >= NUMBER_OF_BATCHES_FOR_ESTIMATION) {
+ break;
+ }
+ }
+ telemetry.getMigrationTimer().suspend();
+
+ if (Task.Migrate.equals(task)) {
+ log.info("Done migrating raw table" + table + "---------------------");
+
+ if (config.isDeleteDataImmediatelyAfterMigration()) {
+ deleteTableData(table);
+ }
+ } else if (numberOfBatchesMigrated >= NUMBER_OF_BATCHES_FOR_ESTIMATION) {
+ break;
+ }
+
+ dataSource.close();
+ tablesNotProcessed.poll();
+ }
+
+ telemetry.getMigrationTimer().resume();
+ metricsIndexAccumulator.drain();
+ telemetry.getMigrationTimer().suspend();
+
+ telemetry.getGeneralTimer().stop();
+ return telemetry;
+ }
+
+ private void deleteTableData(String table) throws Exception {
+ String deleteQuery = String.format(MigrationQuery.DELETE_RAW_ENTRY.toString(), table);
+ int failureCount = 0;
+ while (failureCount < MAX_NUMBER_OF_FAILURES) {
+ try {
+ StatelessSession session = getSQLSession(config);
+ session.getTransaction().begin();
+ org.hibernate.Query nativeQuery = session.createSQLQuery(deleteQuery);
+ nativeQuery.executeUpdate();
+ session.getTransaction().commit();
+ closeSQLSession(session);
+ log.info("- " + table + " - Cleaned -");
+ } catch (Exception e) {
+ log.error("Failed to delete " + table + " data. Attempting to delete data one more time...");
+
+ failureCount++;
+ if (failureCount == MAX_NUMBER_OF_FAILURES) {
+ throw e;
+ }
+ }
+ }
+ }
+
+ private void insertDataToCassandra(List<Object[]> existingData) throws Exception {
+ List<ResultSetFuture> resultSetFutures = new ArrayList<ResultSetFuture>();
+ Batch batch = QueryBuilder.batch();
+ int batchSize = 0;
+
+ //only need approximate TTL to speed up processing
+ //given that each batch is processed within seconds, getting the
+ //system time once per batch has minimal impact on the record retention
+ long creationTimeMillis;
+ long itemTTLSeconds;
+ long currentTimeMillis = System.currentTimeMillis();
+ long expectedTTLMillis = MetricsTable.RAW.getTTLinMilliseconds();
+
+ for (Object[] rawDataPoint : existingData) {
+ creationTimeMillis = Long.parseLong(rawDataPoint[MigrationQuery.TIMESTAMP_INDEX].toString());
+ itemTTLSeconds = (expectedTTLMillis - currentTimeMillis + creationTimeMillis) / 1000l;
+
+ if (itemTTLSeconds > 0) {
+ int scheduleId = Integer.parseInt(rawDataPoint[MigrationQuery.SCHEDULE_INDEX].toString());
+ Date creationTime = new Date(creationTimeMillis);
+
+ batch.add(QueryBuilder.insertInto(MetricsTable.RAW.toString()).value("schedule_id", scheduleId)
+ .value("time", creationTime)
+ .value("value", Double.parseDouble(rawDataPoint[MigrationQuery.VALUE_INDEX].toString()))
+ .using(ttl((int) itemTTLSeconds)));
+ batchSize++;
+
+ metricsIndexAccumulator.add(scheduleId, creationTimeMillis);
+ }
+
+ if (batchSize >= MAX_RAW_BATCH_TO_CASSANDRA) {
+ resultSetFutures.add(config.getSession().executeAsync(batch));
+ batch = QueryBuilder.batch();
+ batchSize = 0;
+ }
+ }
+
+ if (batchSize != 0) {
+ resultSetFutures.add(config.getSession().executeAsync(batch));
+ }
+
+ for (ResultSetFuture future : resultSetFutures) {
+ future.get();
+ }
+ }
+}
diff --git a/modules/enterprise/server/data-migration/src/main/resources/logging.properties b/modules/enterprise/server/data-migration/src/main/resources/logging.properties
new file mode 100644
index 0000000..6b2a56e
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/resources/logging.properties
@@ -0,0 +1,31 @@
+# Additional logger names to configure (root logger is always configured)
+loggers=org.rhq, org.rhq.storage.installer.StorageInstaller, org.rhq.cassandra.Deployer
+
+# Root logger level
+logger.level=${rhq.storage.installer.loglevel:INFO}
+# Root logger handlers
+logger.handlers=FILE,CONSOLE
+
+logger.org.rhq.level=WARN
+logger.org.rhq.storage.installer.StorageInstaller.level=INFO
+logger.org.rhq.cassandra.Deployer.level=INFO
+
+# Console handler configuration
+handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
+handler.CONSOLE.properties=autoFlush
+handler.CONSOLE.level=${rhq.storage.installer.loglevel:INFO}
+handler.CONSOLE.autoFlush=true
+handler.CONSOLE.formatter=PATTERN
+
+# File handler configuration
+handler.FILE=org.jboss.logmanager.handlers.FileHandler
+handler.FILE.level=${rhq.storage.installer.loglevel:INFO}
+handler.FILE.properties=autoFlush,fileName
+handler.FILE.autoFlush=true
+handler.FILE.fileName=${rhq.storage.installer.logdir:.}/rhq-storage-installer.log
+handler.FILE.formatter=PATTERN
+
+# Formatter pattern configuration
+formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
+formatter.PATTERN.properties=pattern
+formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n
diff --git a/modules/enterprise/server/data-migration/src/main/resources/module/main/module.xml b/modules/enterprise/server/data-migration/src/main/resources/module/main/module.xml
new file mode 100644
index 0000000..78d2ac7
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/resources/module/main/module.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<module xmlns="urn:jboss:module:1.0" name="${moduleName}">
+ <main-class name="org.rhq.server.metrics.migrator.DataMigratorRunner"/>
+
+ <resources>
+ <resource-root path="${project.build.finalName}.jar"/>
+ <resource-root path="rhq-server-metrics-${project.version}.jar"/>
+ <resource-root path="joda-time-${joda-time.version}.jar"/>
+ <resource-root path="hibernate-core-${hibernate.version}.jar"/>
+ <resource-root path="hibernate-entitymanager-${hibernate.version}.jar"/>
+ <resource-root path="hibernate-jpa-2.0-api-${hibernate-jpa-2.0-api.version}.jar"/>
+ </resources>
+
+ <dependencies>
+ <module name="javax.transaction.api"/>
+ <module name="org.rhq.postgres"/>
+ <module name="javax.persistence.api"/>
+ <module name="javax.api"/>
+ <module name="org.dom4j"/>
+ <module name="org.apache.commons.logging"/>
+ <module name="org.apache.commons.cli"/>
+ <module name="org.apache.commons.lang"/>
+ <module name="org.apache.log4j"/>
+ <module name="sun.jdk"/>
+ <module name="org.jboss.logmanager" services="import"/>
+ <module name="org.jboss.logging"/>
+ <module name="org.rhq.oracle" optional="true" />
+ <module name="com.datastax.cassandra.cassandra-driver-core"/>
+ <module name="org.hibernate.commons-annotations" services="import"/>
+ </dependencies>
+</module>
diff --git a/modules/enterprise/server/data-migration/src/main/scripts/module-assembly.xml b/modules/enterprise/server/data-migration/src/main/scripts/module-assembly.xml
new file mode 100644
index 0000000..30dd591
--- /dev/null
+++ b/modules/enterprise/server/data-migration/src/main/scripts/module-assembly.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<assembly>
+ <id>module-assembly</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <baseDirectory>${project.build.finalName}-module</baseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>${project.build.outputDirectory}/module</directory>
+ <outputDirectory>/org/rhq/${artifactId}</outputDirectory>
+ <includes>
+ <include>main/module.xml</include>
+ </includes>
+ <fileMode>0644</fileMode>
+ <directoryMode>0755</directoryMode>
+ </fileSet>
+ <fileSet>
+ <directory>${project.build.directory}</directory>
+ <outputDirectory>/org/rhq/${artifactId}/main</outputDirectory>
+ <includes>
+ <include>${project.build.finalName}.jar</include>
+ </includes>
+ <fileMode>0644</fileMode>
+ <directoryMode>0755</directoryMode>
+ </fileSet>
+ <fileSet>
+ <directory>${project.build.directory}/dependencies</directory>
+ <outputDirectory>/org/rhq/${artifactId}/main</outputDirectory>
+ <fileMode>0644</fileMode>
+ <directoryMode>0755</directoryMode>
+ </fileSet>
+ </fileSets>
+</assembly>
+
diff --git a/modules/enterprise/server/pom.xml b/modules/enterprise/server/pom.xml
index 8b33103..9973f81 100644
--- a/modules/enterprise/server/pom.xml
+++ b/modules/enterprise/server/pom.xml
@@ -26,6 +26,7 @@
<modules>
<module>xml-schemas</module>
<module>server-metrics</module>
+ <module>data-migration</module>
<module>jar</module>
<module>sars</module>
<module>plugins</module>
commit 9ee055d0f7f62a16f5ce2f3e31f8e66c58e260be
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Jun 18 09:55:42 2013 -0500
Still use the classloader to get resource stream when code not packaged in a JAR file.
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
index be69c08..4f74a78 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java
@@ -183,7 +183,7 @@ public class AbstractManager {
URL resourceFolderURL = this.getClass().getClassLoader().getResource(folder);
if (resourceFolderURL.getProtocol().equals("file")) {
- stream = this.getClass().getResourceAsStream(folder);
+ stream = this.getClass().getClassLoader().getResourceAsStream(folder);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String updateFile;
commit fbf28d964e4b4bf03a1414c77e9aaabbeeacf843
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Jun 18 11:16:13 2013 -0400
do not mention "pre-4.8" or any version number in help/error messages since it won't be helpful to JON users
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
index 8f714a6..001002c 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
@@ -91,14 +91,14 @@ public class Upgrade extends AbstractInstall {
null,
STORAGE_DATA_ROOT_DIR,
true,
- "This option is valid only when upgrading from a pre 4.8 system. Use this option to specify a non-default base "
+ "This option is valid only when upgrading from older systems that did not have storage nodes. Use this option to specify a non-default base "
+ "directory for the data directories created by the storage node. For example, if the default directory is "
+ "not writable for the current user (/var/lib on Linux) or if you simply prefer a different location. ")
.addOption(
null,
STORAGE_CONFIG_OPTION,
true,
- "This option is valid only when upgrading from a pre 4.8 system. Use this option to specify non-default storage "
+ "This option is valid only when upgrading from older systems that did not have storage nodes. Use this option to specify non-default storage "
+ "installer options. It is the path to a properties file with keys that correspond to option names of the "
+ "storage installer. Each property will be translated into an option that is passed to the storage "
+ "installer. See example.storage.properties for examples.")
@@ -106,7 +106,7 @@ public class Upgrade extends AbstractInstall {
null,
RUN_DATA_MIGRATION,
true,
- "This option is valid only when upgrading from a pre 4.8 system. The existing metric data needs to migrate to "
+ "This option is valid only when upgrading from older systems that did not have storage nodes. The existing metric data needs to migrate to "
+ "the metric storage. The upgrade process can trigger this or give you an estimate on the duration. If you want "
+ "to have fine control over the process, please run the migrator on the command line. Options are none (do "
+ "nothing), estimate (estimate the migration time only), print-command (print the command line for a manual run), "
@@ -678,17 +678,17 @@ public class Upgrade extends AbstractInstall {
if (isRhq48OrLater(commandLine)) {
if (commandLine.hasOption(STORAGE_DATA_ROOT_DIR)) {
errors.add("The option --" + STORAGE_DATA_ROOT_DIR
- + " is valid only for upgrades from pre RHQ 4.8 systems.");
+ + " is valid only for upgrades from older systems that did not have storage nodes.");
}
if (commandLine.hasOption(STORAGE_CONFIG_OPTION)) {
errors.add("The option --" + STORAGE_CONFIG_OPTION
- + " is valid only for upgrades from pre RHQ 4.8 systems.");
+ + " is valid only for upgrades from older systems that did not have storage nodes.");
}
if (commandLine.hasOption(RUN_DATA_MIGRATION)) {
errors.add("The option --" + RUN_DATA_MIGRATION
- + " is valid only for upgrades from pre RHQ 4.8 systems.");
+ + " is valid only for upgrades from older systems that did not have storage nodes.");
}
}
@@ -727,7 +727,8 @@ public class Upgrade extends AbstractInstall {
}
private void printDataMigrationNotice() {
- log.info("\n================\n" + "If this was an upgrade from a RHQ version before 4.8,\n "
+ log.info("\n================\n"
+ + "If this was an upgrade from older systems that did not have storage nodes,\n "
+ "you need to run the data migration job to transfer stored (historic)\n"
+ "metrics data from the relational database into the new storage.\n"
+ "Until the migration has run, that historic data is not available \n" + "in e.g. the charting views.\n\n"
commit a49dd9677bd7204a34861c0e6d3bc337b664dff3
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Jun 18 11:06:30 2013 -0400
More Upgrade fixes
- Allow --storage-config option for upgrade. This is valid only for the case
when upping from pre 4.8 to support the SN install.
- Fix Windows issue when copying over old key/trust store settings
- Enhance the help text a little for the pre 48 options
diff --git a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
index de6a324..8f714a6 100644
--- a/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
+++ b/modules/enterprise/server/server-control/src/main/java/org/rhq/server/control/command/Upgrade.java
@@ -91,18 +91,26 @@ public class Upgrade extends AbstractInstall {
null,
STORAGE_DATA_ROOT_DIR,
true,
- "You can use this option to use a different base directory for all the data directories created by the storage node e.g. "
- + "if the default directory is not writable for the current user (which is under /var/lib on Linux). "
- + "This is only used if the storage node needs to be newly installed during the upgrade process; otherwise, "
- + "an error will result if you specify this option. ")
+ "This option is valid only when upgrading from a pre 4.8 system. Use this option to specify a non-default base "
+ + "directory for the data directories created by the storage node. For example, if the default directory is "
+ + "not writable for the current user (/var/lib on Linux) or if you simply prefer a different location. ")
+ .addOption(
+ null,
+ STORAGE_CONFIG_OPTION,
+ true,
+ "This option is valid only when upgrading from a pre 4.8 system. Use this option to specify non-default storage "
+ + "installer options. It is the path to a properties file with keys that correspond to option names of the "
+ + "storage installer. Each property will be translated into an option that is passed to the storage "
+ + "installer. See example.storage.properties for examples.")
.addOption(
null,
RUN_DATA_MIGRATION,
true,
- "By default you ned to migrate metrics from a pre RHQ 4.8 system. The upgrade process can trigger this or "
- + "give you an estimate on the duration. If you want to have fine control over the process, please run the "
- + "migrator on the command line. Options are none (do nothing), estimate (estimate the migration time only), "
- + "print-command (print the command line for a manual run) , do-it (run the migration)");
+ "This option is valid only when upgrading from a pre 4.8 system. The existing metric data needs to migrate to "
+ + "the metric storage. The upgrade process can trigger this or give you an estimate on the duration. If you want "
+ + "to have fine control over the process, please run the migrator on the command line. Options are none (do "
+ + "nothing), estimate (estimate the migration time only), print-command (print the command line for a manual run), "
+ + "do-it (run the migration)");
options.getOption(AGENT_AUTOSTART_OPTION).setOptionalArg(true);
}
@@ -550,9 +558,10 @@ public class Upgrade extends AbstractInstall {
}
String absPath = propertyValue.replace("${jboss.server.config.dir}", oldServerConfigDir.getAbsolutePath());
- absPath = absPath.replace("${jboss.server.home.dir}/conf", oldServerConfigDir.getAbsolutePath());
+ absPath = absPath.replace("${jboss.server.home.dir}/conf",
+ useForwardSlash(oldServerConfigDir.getAbsolutePath()));
if (absPath.startsWith("conf/")) {
- absPath = absPath.replaceFirst("conf", oldServerConfigDir.getAbsolutePath());
+ absPath = absPath.replaceFirst("conf", useForwardSlash(oldServerConfigDir.getAbsolutePath()));
}
referredFile = new File(absPath);
}
@@ -579,6 +588,10 @@ public class Upgrade extends AbstractInstall {
return;
}
+ private String useForwardSlash(String path) {
+ return (null != path) ? path.replace('\\', '/') : null;
+ }
+
private void upgradeAgent(CommandLine rhqctlCommandLine) throws IOException {
try {
File oldAgentDir;
@@ -664,7 +677,18 @@ public class Upgrade extends AbstractInstall {
if (isRhq48OrLater(commandLine)) {
if (commandLine.hasOption(STORAGE_DATA_ROOT_DIR)) {
- errors.add("You cannot use the option --" + STORAGE_DATA_ROOT_DIR + " for your installation.");
+ errors.add("The option --" + STORAGE_DATA_ROOT_DIR
+ + " is valid only for upgrades from pre RHQ 4.8 systems.");
+ }
+
+ if (commandLine.hasOption(STORAGE_CONFIG_OPTION)) {
+ errors.add("The option --" + STORAGE_CONFIG_OPTION
+ + " is valid only for upgrades from pre RHQ 4.8 systems.");
+ }
+
+ if (commandLine.hasOption(RUN_DATA_MIGRATION)) {
+ errors.add("The option --" + RUN_DATA_MIGRATION
+ + " is valid only for upgrades from pre RHQ 4.8 systems.");
}
}
commit 6ef385601d660ebfd63940254f74058081beb8d1
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jun 18 16:18:42 2013 +0200
BZ 970970 hide traits in the table that are disabled to be orthogonal with the metrics.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
index 3a2a2c1..3abcbaf 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
@@ -51,12 +51,14 @@ public class MeasurementDataTraitCriteria extends Criteria {
public static final String FILTER_FIELD_GROUP_ID = "groupId";
public static final String FILTER_FIELD_DEFINITION_ID = "definitionId";
public static final String FILTER_FIELD_MAX_TIMESTAMP = "maxTimestamp";
+ public static final String FILTER_FIELD_ENABLED = "enabled";
private Integer filterScheduleId; // requires overrides
private Integer filterResourceId; // requires overrides
private Integer filterGroupId; // requires overrides
private Integer filterDefinitionId; // requires overrides
private Integer filterMaxTimestamp; // requires overrides
+ private Boolean filterEnabled; // requires overrides
private boolean fetchSchedule;
@@ -78,6 +80,7 @@ public class MeasurementDataTraitCriteria extends Criteria {
+ " FROM MeasurementDataTrait mdt "
+ " WHERE mdt.id.scheduleId = " + getAlias() + ".id.scheduleId ) " //
+ " AND 1 = ?");
+ filterOverrides.put(FILTER_FIELD_ENABLED, "schedule.enabled = ?");
sortOverrides.put(SORT_FIELD_TIMESTAMP, "id.timestamp");
sortOverrides.put(SORT_FIELD_DISPLAY_NAME, "schedule.definition.displayName");
@@ -115,6 +118,10 @@ public class MeasurementDataTraitCriteria extends Criteria {
this.filterMaxTimestamp = 1;
}
+ public void addFilterEnabled(boolean filterEnabled) {
+ this.filterEnabled = filterEnabled;
+ }
+
public void fetchSchedule(boolean fetchSchedule) {
this.fetchSchedule = fetchSchedule;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
index e640d1d..625e56c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
@@ -77,7 +77,7 @@ public abstract class AbstractMeasurementDataTraitDataSource extends
DataSourceIntegerField idField = new DataSourceIntegerField(FIELD_METRIC_SCHED_ID, MSG.dataSource_traits_field_definitionID());
idField.setHidden(true);
fields.add(idField);
-
+
DataSourceIntegerField nameField = new DataSourceIntegerField(FIELD_METRIC_NAME, MSG.common_title_name());
nameField.setHidden(true);
fields.add(nameField);
@@ -88,7 +88,7 @@ public abstract class AbstractMeasurementDataTraitDataSource extends
/**
* The view that contains the list grid which will display this datasource's data will call this
* method to get the field information which is used to control the display of the data.
- *
+ *
* @return list grid fields used to display the datasource data
*/
public ArrayList<ListGridField> getListGridFields() {
@@ -164,6 +164,8 @@ public abstract class AbstractMeasurementDataTraitDataSource extends
criteria.addFilterDefinitionId(definitionId);
} else if (fieldName.equals(MeasurementDataTraitCriteria.FILTER_FIELD_MAX_TIMESTAMP)) {
criteria.addFilterMaxTimestamp();
+ } else if (fieldName.equals(MeasurementDataTraitCriteria.FILTER_FIELD_ENABLED)) {
+ criteria.addFilterEnabled(true);
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
index 3fe81a1..e03ffb7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
@@ -71,6 +71,7 @@ public class TraitsView extends AbstractMeasurementDataTraitListView {
criteria.addCriteria(MeasurementDataTraitCriteria.FILTER_FIELD_RESOURCE_ID, resourceId);
criteria.addCriteria(MeasurementDataTraitCriteria.FILTER_FIELD_MAX_TIMESTAMP, true);
+ criteria.addCriteria(MeasurementDataTraitCriteria.FILTER_FIELD_ENABLED, true);
return criteria;
}
commit ae274f9ad05eb0f150e9cf956d54271d57ea6ac0
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jun 18 16:02:58 2013 +0200
Add a description for the operations endpoint and mark it as experimental.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 60cfdd7..5e8e68e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -48,6 +48,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiError;
import com.wordnik.swagger.annotations.ApiErrors;
import com.wordnik.swagger.annotations.ApiOperation;
@@ -92,6 +93,9 @@ import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Stateless
@Interceptors(SetCallerInterceptor.class)
+@Api(value = "Endpoints for operations - EXPERIMENTAL",
+ description = "These endpoints deal with scheduling of operations and retrieval of operation results. " +
+ "These are working, but may still change in the next RHQ release.")
public class OperationsHandlerBean extends AbstractRestBean {
@EJB
commit 935c69a34c0aec87c202d68d1b90ff1276057d6a
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue Jun 18 14:54:28 2013 +0200
Bug 975384 - Error displaying calltime data due to SQL error
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java
index a209338..a68026e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,9 +13,10 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.enterprise.server.measurement;
import java.sql.Connection;
commit f3843b8625d02037dac035ffa2b8d7e158caaaeb
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue Jun 18 14:13:18 2013 +0200
BZ 975384 disable adding the sort by id.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java
index 0c91abc..a209338 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/CallTimeDataManagerBean.java
@@ -216,6 +216,7 @@ public class CallTimeDataManagerBean implements CallTimeDataManagerLocal, CallTi
criteria.addFilterAutoGroupParentResourceId(context.parentResourceId);
criteria.addFilterAutoGroupResourceTypeId(context.resourceTypeId);
}
+ criteria.setSupportsAddSortId(false);
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
String replacementSelectList = "" //
commit 96402a582dd391c68bbc7f3f27f6129b3bcb0830
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jun 18 09:44:10 2013 +0200
Get this to compile again and bump the JRuby version.
diff --git a/modules/enterprise/server/plugins/alert-scriptlang/pom.xml b/modules/enterprise/server/plugins/alert-scriptlang/pom.xml
index e8413db..090e0ed 100644
--- a/modules/enterprise/server/plugins/alert-scriptlang/pom.xml
+++ b/modules/enterprise/server/plugins/alert-scriptlang/pom.xml
@@ -4,11 +4,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
+ <properties>
+ <jruby.version>1.7.3</jruby.version>
+ </properties>
- <parent>
+ <parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.3.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
@@ -21,7 +24,7 @@
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
- <version>1.4.0</version>
+ <version>${jruby.version}</version>
</dependency>
</dependencies>
@@ -35,7 +38,7 @@
<build>
<plugins>
<plugin>
- <artifactId>maven-dependency-plugin</artifactId>
+ <artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-jruby-jar</id>
@@ -48,7 +51,7 @@
<artifactItem>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
- <version>1.4.0</version>
+ <version>${jruby.version}</version>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
@@ -134,6 +137,6 @@
</plugins>
</build>
</profile>
-
+
</profiles>
</project>
diff --git a/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java b/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java
index bac51fb..77fe4b7 100644
--- a/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java
+++ b/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2009 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.plugins.alertScriptlang;
@@ -32,7 +32,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
import org.rhq.core.domain.alert.notification.SenderResult;
import org.rhq.enterprise.server.alert.AlertManagerLocal;
import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
@@ -51,7 +50,7 @@ public class ScriptLangSender extends AlertSender<ScriptLangComponent> {
String scriptName = alertParameters.getSimpleValue("name", null);
if (scriptName == null) {
- return new SenderResult(ResultState.FAILURE, "No script given");
+ return SenderResult.getSimpleFailure("No script given");
}
String language = alertParameters.getSimpleValue("language", "jruby");
@@ -62,13 +61,13 @@ public class ScriptLangSender extends AlertSender<ScriptLangComponent> {
if (engine==null) {
- return new SenderResult(ResultState.FAILURE,"Script engine with name [" + language + "] does not exist");
+ return SenderResult.getSimpleFailure("Script engine with name [" + language + "] does not exist");
}
File file = new File(pluginComponent.baseDir + scriptName);
if (!file.exists() || !file.canRead()) {
- return new SenderResult(ResultState.FAILURE,
- "Script [" + scriptName + "] does not exist or is not readable at [" + file.getAbsolutePath()+"]");
+ return SenderResult.getSimpleFailure(
+ "Script [" + scriptName + "] does not exist or is not readable at [" + file.getAbsolutePath() + "]");
}
Object result;
@@ -97,15 +96,15 @@ public class ScriptLangSender extends AlertSender<ScriptLangComponent> {
result = ((Invocable) engine).invokeFunction("sendAlert", args);
if (result == null) {
- return new SenderResult(ResultState.FAILURE,"Script ]" + scriptName + "] returned null, so success is unknown");
+ return SenderResult.getSimpleFailure("Script ]" + scriptName + "] returned null, so success is unknown");
}
if (result instanceof SenderResult)
return (SenderResult) result;
- return new SenderResult(ResultState.SUCCESS, "Sending via script resulted in " + result.toString());
+ return SenderResult.getSimpleSuccess("Sending via script resulted in " + result.toString());
} catch (Exception e) {
e.printStackTrace();
- return new SenderResult(ResultState.FAILURE, "Sending via [" + scriptName + "] failed: " + e.getMessage());
+ return SenderResult.getSimpleFailure("Sending via [" + scriptName + "] failed: " + e.getMessage());
}
}
}
diff --git a/modules/enterprise/server/plugins/alert-scriptlang/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/alert-scriptlang/src/main/resources/META-INF/rhq-serverplugin.xml
index 30c89a0..352be33 100644
--- a/modules/enterprise/server/plugins/alert-scriptlang/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/modules/enterprise/server/plugins/alert-scriptlang/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -25,7 +25,6 @@
<c:simple-property name="scriptfolder" type="file" default="/scripts"/>
</serverplugin:plugin-configuration>
-->
-
<!-- How does this sender show up in drop downs etc -->
<short-name>Scriptlang</short-name>
commit 12c501fce9d48589b67a9af2acfef323529dbb51
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jun 18 09:43:45 2013 +0200
BZ 949659 Cope with an alert plugin having an empty <alert-configuration>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java
index 0e38bb8..d5b3c94 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java
@@ -37,6 +37,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
+import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.alert.AlertDefinitionContext;
import org.rhq.core.domain.alert.notification.AlertNotification;
@@ -88,7 +89,7 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc
* AlertDefinitionManager.updateAlertDefinition() to perform the actual modifications and persistence.
* If we use an attached AlertDefinity entity at this layer, modify the set of notifications, then call
* into AlertDefinitionManager.updateAlertDefinition() which executes in a new transaction, the work will
- * actually be performed twice - once at each layer. This would result in either duplicate notifications
+ * actually be performed twice - once at each layer. This would result in either duplicate notifications
* (in the case of adding notifications) or Hibernate exceptions (in the case of removing notifications,
* which are attempted twice for each being removed).
*
@@ -96,7 +97,7 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc
* the Hibernate session, a better method is to just execute the add/removal logic for the AlertNotification(s)
* outside a transaction and then call AlertDefinitionManager.updateAlertNotification() which starts a new
* transaction to do all of its logic.
- *
+ *
* Note: for AlertNotification updates to work properly, alertDefinitionManager.getAlertDefinitionById() must
* eagerly load the List<AlertNotification> on the returned AlertDefinition
*/
@@ -134,10 +135,10 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc
public void updateAlertNotification(Subject subject, int alertDefinitionId, AlertNotification notification) {
AlertDefinition alertDefinition = getDetachedAlertDefinition(alertDefinitionId); // permissions check first
- /*
+ /*
* NULL notifications used to perform cascade updates from template and group level for alert senders
* that leverage custom UIs, which have a completely external methodology for loading/saving the data
- * into and out of configuration object(s) associated with an AlertNotification.
+ * into and out of configuration object(s) associated with an AlertNotification.
*/
if (notification != null) {
// remove then add is a cheap way of performing an update
@@ -209,10 +210,17 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc
AlertPluginDescriptorType descriptor = (AlertPluginDescriptorType) serverPluginsBean
.getServerPluginDescriptor(key);
//ConfigurationDefinition pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor.getPluginConfiguration());
- ConfigurationDefinition pluginConfigurationDefinition = ConfigurationMetadataParser.parse("alerts:"
- + pluginName, descriptor.getAlertConfiguration());
+ ConfigurationDescriptor alertConfiguration = descriptor.getAlertConfiguration();
+ if (alertConfiguration==null || alertConfiguration.getConfigurationProperty()== null || alertConfiguration.getConfigurationProperty().isEmpty()) {
+ // User either provided no <alert-configuration> or an empty one
+ return new ConfigurationDefinition("alerts:"+pluginName,"No properties given");
+ }
+ else {
+ ConfigurationDefinition pluginConfigurationDefinition = ConfigurationMetadataParser.parse("alerts:"
+ + pluginName, alertConfiguration);
- return pluginConfigurationDefinition;
+ return pluginConfigurationDefinition;
+ }
} catch (Exception e) {
LOG.error(e);
return null;
commit 9348431e6c1127d1346b57915ddaed0920c12e0e
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Jun 17 22:35:55 2013 -0400
provide defaults for heap and heap new size.
diff --git a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
index 860865d..3e6c7e8 100644
--- a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
+++ b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
@@ -116,6 +116,10 @@ public class StorageInstaller {
private String savedCachesDir = dirPrefix + "/rhq/storage/saved_caches";
+ private String defaultHeapSize = "512M";
+
+ private String defaultHeapNewSize = "128M";
+
public StorageInstaller() {
String basedir = System.getProperty("rhq.server.basedir");
serverBasedir = new File(basedir);
@@ -173,10 +177,12 @@ public class StorageInstaller {
+ "The default directory will be " + storageBasedir);
Option heapSizeOption = new Option(null, "heap-size", true, "The value to use for both the min and max heap. " +
- "This value is passed directly to the -Xms and -Xmx options of the Java executable.");
+ "This value is passed directly to the -Xms and -Xmx options of the Java executable. Defaults to " +
+ defaultHeapSize);
Option heapNewSizeOption = new Option(null, "heap-new-size", true, "The value to use for the new generation " +
- "of the heap. This value is passed directly to the -Xmn option of the Java executable");
+ "of the heap. This value is passed directly to the -Xmn option of the Java executable. Defaults to " +
+ defaultHeapNewSize);
Option stackSizeOption = new Option(null, "stack-size", true, "The value to use for the thread stack size. " +
"This value is passed directly to the -Xss option of the Java executable.");
@@ -332,13 +338,8 @@ public class StorageInstaller {
// TODO set defaults for read/write/range timeouts
- if (cmdLine.hasOption("heap-size")) {
- deploymentOptions.setHeapSize(cmdLine.getOptionValue("heap-size"));
- }
-
- if (cmdLine.hasOption("heap-new-size")) {
- deploymentOptions.setHeapNewSize(cmdLine.getOptionValue("heap-new-size"));
- }
+ deploymentOptions.setHeapSize(cmdLine.getOptionValue("heap-size", defaultHeapSize));
+ deploymentOptions.setHeapNewSize(cmdLine.getOptionValue("heap-new-size", defaultHeapNewSize));
if (cmdLine.hasOption("stack-size")) {
deploymentOptions.setStackSize(cmdLine.getOptionValue("stack-size"));
commit 2af4dc8f7ea5155f77a9cdbc4820492260a705a9
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Jun 17 22:20:52 2013 -0400
fix bug for parsing jmx port and only set rhq.cassandra.seeds with local node info
Previously the storage installer would set rhq.cassandra.seeds using whatever
values it received for the --seeds option. It cannot do that because each node
can have a different value for its jmx port.
diff --git a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
index a9fa699..860865d 100644
--- a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
+++ b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java
@@ -64,7 +64,6 @@ import org.rhq.cassandra.DeploymentOptions;
import org.rhq.cassandra.DeploymentOptionsFactory;
import org.rhq.cassandra.installer.RMIContextFactory;
import org.rhq.core.util.PropertiesFileUpdate;
-import org.rhq.core.util.StringUtil;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.file.FileUtil;
@@ -101,7 +100,7 @@ public class StorageInstaller {
private int rpcPort = 9160;
- private int nativeTransportPort = 9142;
+ private int defaultNativeTransportPort = 9142;
private int storagePort = 7100;
@@ -138,7 +137,7 @@ public class StorageInstaller {
jmxPortOption.setArgName("PORT");
Option nativeTransportPortOption = new Option("c", "client-port", true, "The port on which to "
- + "listen for client requests. Defaults to " + nativeTransportPort);
+ + "listen for client requests. Defaults to " + defaultNativeTransportPort);
nativeTransportPortOption.setArgName("PORT");
Option storagePortOption = new Option(null, "storage-port", true, "The port on which to listen for requests "
@@ -263,11 +262,8 @@ public class StorageInstaller {
replaceFile(new File(oldConfDir, cassandraEnv), cassandraEnvFile);
replaceFile(new File(oldConfDir, log4j), new File(newConfDir, log4j));
- jmxPort = parseJmxPort(cassandraEnvFile);
-
log.info("Finished installing RHQ Storage Node.");
- PropertiesFileUpdate serverPropertiesUpdater = getServerProperties();
log.info("Updating rhq-server.properties...");
File yamlFile = new File(newConfDir, "cassandra.yaml");
@@ -276,14 +272,7 @@ public class StorageInstaller {
hostname = (String) config.get("listen_address");
- List seedProviderList = (List) config.get("seed_provider");
- Map seedProvider = (Map) seedProviderList.get(0);
- List paramsList = (List) seedProvider.get("parameters");
- Map params = (Map) paramsList.get(0);
- // TODO What should we do if the seeds option is also set?
- // Should we replace or merge?
- String seeds = (String) params.get("seeds");
- serverPropertiesUpdater.update("rhq.cassandra.seeds", getSeedsProperty(seeds, jmxPort));
+ jmxPort = parseJmxPort(cassandraEnvFile);
} else {
if (cmdLine.hasOption("dir")) {
File basedir = new File(cmdLine.getOptionValue("dir"));
@@ -324,6 +313,7 @@ public class StorageInstaller {
}
jmxPort = getPort(cmdLine, "jmx-port", defaultJmxPort);
+ int nativeTransportPort = getPort(cmdLine, "client-port", defaultNativeTransportPort);
deploymentOptions.setCommitLogDir(commitLogDir);
deploymentOptions.setDataDir(dataDir);
@@ -332,7 +322,7 @@ public class StorageInstaller {
deploymentOptions.setLoggingLevel("INFO");
deploymentOptions.setRpcPort(rpcPort);
deploymentOptions.setJmxPort(jmxPort);
- deploymentOptions.setNativeTransportPort(getPort(cmdLine, "client-port", nativeTransportPort));
+ deploymentOptions.setNativeTransportPort(nativeTransportPort);
deploymentOptions.setStoragePort(getPort(cmdLine, "storage-port", storagePort));
deploymentOptions.setSslStoragePort(getPort(cmdLine, "ssl-storage-port", sslStoragePort));
@@ -382,7 +372,8 @@ public class StorageInstaller {
PropertiesFileUpdate serverPropertiesUpdater = getServerProperties();
log.info("Updating rhq-server.properties...");
- serverPropertiesUpdater.update("rhq.cassandra.seeds", getSeedsProperty(seeds, jmxPort));
+ serverPropertiesUpdater.update("rhq.cassandra.seeds", getSeedsProperty(hostname, jmxPort,
+ nativeTransportPort));
}
boolean startNode = Boolean.parseBoolean(cmdLine.getOptionValue("start", "true"));
@@ -483,13 +474,8 @@ public class StorageInstaller {
return new PropertiesFileUpdate(file.getAbsolutePath());
}
- private String getSeedsProperty(String seeds, int jmxPort) {
- String[] hosts = seeds.split(",");
- List<String> list = new ArrayList<String>(hosts.length);
- for (String host : hosts) {
- list.add(host + "|" + jmxPort + "|" + nativeTransportPort);
- }
- return StringUtil.collectionToString(list);
+ private String getSeedsProperty(String hostname, int jmxPort, int nativeTransportPort) {
+ return hostname + "|" + jmxPort + "|" + nativeTransportPort;
}
private String startNode(DeploymentOptions deploymentOptions) throws Exception {
@@ -682,6 +668,7 @@ public class StorageInstaller {
}
return port;
}
+ line = reader.readLine();
}
log.error("Failed to parse the JMX port. Make sure that you have the JMX port defined on its " +
"own line as follows, JMX_PORT=\"<jmx-port>\"");
10 years, 11 months