You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2014/12/10 19:00:45 UTC

[01/28] incubator-nifi git commit: NIFI-145: Initial commit of bootstrap module

Repository: incubator-nifi
Updated Branches:
  refs/heads/nifi-27 fef807136 -> 2f2474efb


NIFI-145: Initial commit of bootstrap module


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/567dfc79
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/567dfc79
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/567dfc79

Branch: refs/heads/nifi-27
Commit: 567dfc794c565854850b7e223601528f2a3fd814
Parents: 203e83e
Author: Mark Payne <ma...@hotmail.com>
Authored: Tue Dec 9 08:48:07 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Tue Dec 9 08:48:07 2014 -0500

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 nifi-bootstrap/pom.xml                          |  18 ++
 .../java/org/apache/nifi/bootstrap/RunNiFi.java | 176 +++++++++++++++++++
 .../org/apache/nifi/bootstrap/ShutdownHook.java |  14 ++
 4 files changed, 209 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/567dfc79/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index f026df6..6d4eca9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 target
 .project
 .settings
+.classpath
 nbactions.xml
 .DS_Store
 

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/567dfc79/nifi-bootstrap/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/pom.xml b/nifi-bootstrap/pom.xml
new file mode 100644
index 0000000..b620c84
--- /dev/null
+++ b/nifi-bootstrap/pom.xml
@@ -0,0 +1,18 @@
+<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/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.apache.nifi</groupId>
+		<artifactId>nifi-parent</artifactId>
+		<version>0.0.1-SNAPSHOT</version>
+	</parent>
+
+	<artifactId>nifi-bootstrap</artifactId>
+	<packaging>jar</packaging>
+
+	<name>nifi-bootstrap</name>
+
+	<dependencies>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/567dfc79/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
new file mode 100644
index 0000000..afa1f47
--- /dev/null
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
@@ -0,0 +1,176 @@
+package org.apache.nifi.bootstrap;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+
+/**
+ * Bootstrap class to run Apache NiFi.
+ * 
+ * This class looks for the bootstrap.conf file by looking in the following places (in order):
+ * <ol>
+ * 	<li>First argument to the program</li>
+ *  <li>Java System Property named {@code org.apache.nifi.bootstrap.config.file}</li>
+ *  <li>${NIFI_HOME}/./conf/bootstrap.conf, where ${NIFI_HOME} references an environment variable {@code NIFI_HOME}</li>
+ *  <li>./conf/bootstrap.conf, where {@code .} represents the working directory.
+ * </ol>
+ *
+ * If the {@code bootstrap.conf} file cannot be found, throws a {@code FileNotFoundException].
+ */
+public class RunNiFi {
+	public static final String DEFAULT_CONFIG_FILE = "./conf/boostrap.conf";
+	public static final String DEFAULT_NIFI_PROPS_FILE = "./conf/nifi.properties";
+	
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public static void main(final String[] args) throws IOException, InterruptedException {
+		final ProcessBuilder builder = new ProcessBuilder();
+
+		String configFilename = (args.length > 0) ? args[0] : System.getProperty("org.apache.nifi.boostrap.config.file");
+		
+		if ( configFilename == null ) {
+			final String nifiHome = System.getenv("NIFI_HOME");
+			if ( nifiHome != null ) {
+				final File nifiHomeFile = new File(nifiHome.trim());
+				final File configFile = new File(nifiHomeFile, DEFAULT_CONFIG_FILE);
+				configFilename = configFile.getAbsolutePath();
+			}
+		}
+		
+		if ( configFilename == null ) {
+			configFilename = DEFAULT_CONFIG_FILE;
+		}
+		
+		final File configFile = new File(configFilename);
+		if ( !configFile.exists() ) {
+			throw new FileNotFoundException(DEFAULT_CONFIG_FILE);
+		}
+		
+		final Properties properties = new Properties();
+		try (final FileInputStream fis = new FileInputStream(configFile)) {
+			properties.load(fis);
+		}
+		
+		final Map<String, String> props = new HashMap<>();
+		props.putAll( (Map) properties );
+
+		final String specifiedWorkingDir = props.get("working.dir");
+		if ( specifiedWorkingDir != null ) {
+			builder.directory(new File(specifiedWorkingDir));
+		}
+
+		final File workingDir = builder.directory();
+		
+		final String libFilename = replaceNull(props.get("lib.dir"), "./lib").trim();
+		File libDir = getFile(libFilename, workingDir);
+		
+		final String confFilename = replaceNull(props.get("conf.dir"), "./conf").trim();
+		File confDir = getFile(confFilename, workingDir);
+		
+		String nifiPropsFilename = props.get("props.file");
+		if ( nifiPropsFilename == null ) {
+			if ( confDir.exists() ) {
+				nifiPropsFilename = new File(confDir, "nifi.properties").getAbsolutePath();
+			} else {
+				nifiPropsFilename = DEFAULT_CONFIG_FILE;
+			}
+		}
+		
+		nifiPropsFilename = nifiPropsFilename.trim();
+		
+		final List<String> javaAdditionalArgs = new ArrayList<>();
+		for ( final Map.Entry<String, String> entry : props.entrySet() ) {
+			final String key = entry.getKey();
+			final String value = entry.getValue();
+			
+			if ( key.startsWith("java.arg") ) {
+				javaAdditionalArgs.add(value);
+			}
+		}
+		
+		final File[] libFiles = libDir.listFiles(new FilenameFilter() {
+			@Override
+			public boolean accept(final File dir, final String filename) {
+				return filename.toLowerCase().endsWith(".jar");
+			}
+		});
+		
+		if ( libFiles == null || libFiles.length == 0 ) {
+			throw new RuntimeException("Could not find lib directory at " + libDir.getAbsolutePath());
+		}
+		
+		final File[] confFiles = confDir.listFiles();
+		if ( confFiles == null || confFiles.length == 0 ) {
+			throw new RuntimeException("Could not find conf directory at " + confDir.getAbsolutePath());
+		}
+
+		final Path workingDirPath = workingDir.toPath();
+		final List<String> cpFiles = new ArrayList<>(confFiles.length + libFiles.length);
+		cpFiles.add(confDir.getAbsolutePath());
+		for ( final File file : libFiles ) {
+			final Path path = workingDirPath.relativize(file.toPath());
+			final String cpPath = path.toString();
+			cpFiles.add(cpPath);
+		}
+		
+		final StringBuilder classPathBuilder = new StringBuilder();
+		for (int i=0; i < cpFiles.size(); i++) {
+			final String filename = cpFiles.get(i);
+			classPathBuilder.append(filename);
+			if ( i < cpFiles.size() - 1 ) {
+				classPathBuilder.append(File.pathSeparatorChar);
+			}
+		}
+
+		final String classPath = classPathBuilder.toString();
+		String javaCmd = props.get("java");
+		if ( javaCmd == null ) {
+			javaCmd = "java";
+		}
+		
+		final List<String> cmd = new ArrayList<>();
+		cmd.add(javaCmd);
+		cmd.add("-classpath");
+		cmd.add(classPath);
+		cmd.addAll(javaAdditionalArgs);
+		cmd.add("-Dnifi.properties.file.path=" + nifiPropsFilename);
+		cmd.add("org.apache.nifi.NiFi");
+		
+		builder.command(cmd).inheritIO();
+		
+		final StringBuilder cmdBuilder = new StringBuilder();
+		for ( final String s : cmd ) {
+			cmdBuilder.append(s).append(" ");
+		}
+		System.out.println("Starting Apache NiFi...");
+		System.out.println("Working Directory: " + workingDir.getAbsolutePath());
+		System.out.println("Command: " + cmdBuilder.toString());
+
+		final Process proc = builder.start();
+		Runtime.getRuntime().addShutdownHook(new ShutdownHook(proc));
+		final int statusCode = proc.waitFor();
+		System.out.println("Apache NiFi exited with Status Code " + statusCode);
+	}
+	
+	
+	private static File getFile(final String filename, final File workingDir) {
+		File libDir = new File(filename);
+		if ( !libDir.isAbsolute() ) {
+			libDir = new File(workingDir, filename);
+		}
+		
+		return libDir;
+	}
+	
+	private static String replaceNull(final String value, final String replacement) {
+		return (value == null) ? replacement : value;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/567dfc79/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
new file mode 100644
index 0000000..55e1f45
--- /dev/null
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
@@ -0,0 +1,14 @@
+package org.apache.nifi.bootstrap;
+
+public class ShutdownHook extends Thread {
+	private final Process nifiProcess;
+	
+	public ShutdownHook(final Process nifiProcess) {
+		this.nifiProcess = nifiProcess;
+	}
+	
+	@Override
+	public void run() {
+		nifiProcess.destroy();
+	}
+}


[05/28] incubator-nifi git commit: NIFIDEV-145: Bug fixes and pulled bootstrap into the assembly pom

Posted by mc...@apache.org.
NIFIDEV-145: Bug fixes and pulled bootstrap into the assembly pom


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/e544191f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/e544191f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/e544191f

Branch: refs/heads/nifi-27
Commit: e544191f1d59dbaf9aec6e1bd708bbe013c6661a
Parents: eed4a9b
Author: Mark Payne <ma...@hotmail.com>
Authored: Tue Dec 9 14:37:31 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Tue Dec 9 14:37:31 2014 -0500

----------------------------------------------------------------------
 assemblies/nifi/pom.xml                         |  5 +++++
 .../java/org/apache/nifi/bootstrap/RunNiFi.java | 22 +++++++++++---------
 2 files changed, 17 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e544191f/assemblies/nifi/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/nifi/pom.xml b/assemblies/nifi/pom.xml
index ec06a23..556b8fe 100644
--- a/assemblies/nifi/pom.xml
+++ b/assemblies/nifi/pom.xml
@@ -120,6 +120,11 @@
             <version>${framework.version}</version>
         </dependency>
         <dependency>
+        	<groupId>org.apache.nifi</groupId>
+        	<artifactId>nifi-bootstrap</artifactId>
+        	<version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-resources</artifactId>
             <version>${framework.version}</version>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e544191f/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
index ea3e566..54932c8 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
@@ -30,7 +30,6 @@ import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -250,7 +249,13 @@ public class RunNiFi {
 			builder.directory(new File(specifiedWorkingDir));
 		}
 
-		final File workingDir = builder.directory();
+		final File bootstrapConfigAbsoluteFile = bootstrapConfigFile.getAbsoluteFile();
+		final File binDir = bootstrapConfigAbsoluteFile.getParentFile();
+		final File workingDir = binDir.getParentFile();
+		
+		if ( specifiedWorkingDir == null ) {
+			builder.directory(workingDir);
+		}
 		
 		final String libFilename = replaceNull(props.get("lib.dir"), "./lib").trim();
 		File libDir = getFile(libFilename, workingDir);
@@ -295,13 +300,10 @@ public class RunNiFi {
 			throw new RuntimeException("Could not find conf directory at " + confDir.getAbsolutePath());
 		}
 
-		final Path workingDirPath = workingDir.toPath();
 		final List<String> cpFiles = new ArrayList<>(confFiles.length + libFiles.length);
 		cpFiles.add(confDir.getAbsolutePath());
 		for ( final File file : libFiles ) {
-			final Path path = workingDirPath.relativize(file.toPath());
-			final String cpPath = path.toString();
-			cpFiles.add(cpPath);
+			cpFiles.add(file.getAbsolutePath());
 		}
 		
 		final StringBuilder classPathBuilder = new StringBuilder();
@@ -380,12 +382,12 @@ public class RunNiFi {
 	}
 	
 	private File getFile(final String filename, final File workingDir) {
-		File libDir = new File(filename);
-		if ( !libDir.isAbsolute() ) {
-			libDir = new File(workingDir, filename);
+		File file = new File(filename);
+		if ( !file.isAbsolute() ) {
+			file = new File(workingDir, filename);
 		}
 		
-		return libDir;
+		return file;
 	}
 	
 	private String replaceNull(final String value, final String replacement) {


[27/28] incubator-nifi git commit: NIFI-27: - Latest version of codemirror.

Posted by mc...@apache.org.
NIFI-27:
- Latest version of codemirror.

Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/9180b7d4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/9180b7d4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/9180b7d4

Branch: refs/heads/nifi-27
Commit: 9180b7d4a1c05200cddeb946da120643c627037a
Parents: b61a1de
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Dec 10 12:56:04 2014 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Wed Dec 10 12:56:04 2014 -0500

----------------------------------------------------------------------
 .../src/main/webapp/WEB-INF/pages/canvas.jsp    |    4 +-
 .../src/main/webapp/js/codemirror/LICENSE       |   38 +-
 .../js/codemirror/addon/edit/matchbrackets.js   |  125 -
 .../js/codemirror/addon/hint/show-hint.css      |   54 +-
 .../js/codemirror/addon/hint/show-hint.js       |  411 -
 .../js/codemirror/lib/codemirror-compressed.js  |   16 +
 .../webapp/js/codemirror/lib/codemirror.css     |  282 +-
 .../main/webapp/js/codemirror/lib/codemirror.js | 8488 ------------------
 8 files changed, 228 insertions(+), 9190 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
index 09c8207..a40b745 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
@@ -33,9 +33,7 @@
         <link rel="stylesheet" href="js/jquery/minicolors/jquery.minicolors.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
-        <script type="text/javascript" src="js/codemirror/lib/codemirror.js"></script>
-        <script type="text/javascript" src="js/codemirror/addon/edit/matchbrackets.js"></script>
-        <script type="text/javascript" src="js/codemirror/addon/hint/show-hint.js"></script>
+        <script type="text/javascript" src="js/codemirror/lib/codemirror-compressed.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-1.7.min.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
         <script type="text/javascript" src="js/jquery/jquery.center.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/LICENSE
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/LICENSE b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/LICENSE
old mode 100755
new mode 100644
index 4f1e9d1..d21bbea
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/LICENSE
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/LICENSE
@@ -1,19 +1,19 @@
-Copyright (C) 2013 by Marijn Haverbeke <ma...@gmail.com> and others
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
+Copyright (C) 2014 by Marijn Haverbeke <ma...@gmail.com> and others
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/edit/matchbrackets.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/edit/matchbrackets.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/edit/matchbrackets.js
deleted file mode 100755
index 5f91f9b..0000000
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/edit/matchbrackets.js
+++ /dev/null
@@ -1,125 +0,0 @@
-(function (mod) {
-    if (typeof exports == "object" && typeof module == "object") // CommonJS
-        mod(require("../../lib/codemirror"));
-    else if (typeof define == "function" && define.amd) // AMD
-        define(["../../lib/codemirror"], mod);
-    else // Plain browser env
-        mod(CodeMirror);
-})(function (CodeMirror) {
-    var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
-            (document.documentMode == null || document.documentMode < 8);
-
-    var Pos = CodeMirror.Pos;
-
-    var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
-
-    function findMatchingBracket(cm, where, strict, config) {
-        var line = cm.getLineHandle(where.line), pos = where.ch - 1;
-        var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
-        if (!match)
-            return null;
-        var dir = match.charAt(1) == ">" ? 1 : -1;
-        if (strict && (dir > 0) != (pos == where.ch))
-            return null;
-        var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
-
-        var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
-        return {from: Pos(where.line, pos), to: found && found.pos,
-            match: found && found.ch == match.charAt(0), forward: dir > 0};
-    }
-
-    function scanForBracket(cm, where, dir, style, config) {
-        var maxScanLen = (config && config.maxScanLineLength) || 10000;
-        var maxScanLines = (config && config.maxScanLines) || 500;
-
-        var stack = [], re = /[(){}[\]]/;
-        var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
-                : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
-        for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
-            var line = cm.getLine(lineNo);
-            if (!line)
-                continue;
-            var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
-            if (line.length > maxScanLen)
-                continue;
-            if (lineNo == where.line)
-                pos = where.ch - (dir < 0 ? 1 : 0);
-            for (; pos != end; pos += dir) {
-                var ch = line.charAt(pos);
-                if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
-                    var match = matching[ch];
-                    if ((match.charAt(1) == ">") == (dir > 0))
-                        stack.push(ch);
-                    else if (!stack.length)
-                        return {pos: Pos(lineNo, pos), ch: ch};
-                    else
-                        stack.pop();
-                }
-            }
-        }
-    }
-
-    function matchBrackets(cm, autoclear, config) {
-        // Disable brace matching in long lines, since it'll cause hugely slow updates
-        var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
-        var marks = [], ranges = cm.listSelections();
-        for (var i = 0; i < ranges.length; i++) {
-            var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
-            if (match && cm.getLine(match.from.line).length <= maxHighlightLen &&
-                    match.to && cm.getLine(match.to.line).length <= maxHighlightLen) {
-                var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
-                marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
-                if (match.to)
-                    marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
-            }
-        }
-
-        if (marks.length) {
-            // Kludge to work around the IE bug from issue #1193, where text
-            // input stops going to the textare whever this fires.
-            if (ie_lt8 && cm.state.focused)
-                cm.display.input.focus();
-
-            var clear = function () {
-                cm.operation(function () {
-                    for (var i = 0; i < marks.length; i++)
-                        marks[i].clear();
-                });
-            };
-            if (autoclear)
-                setTimeout(clear, 800);
-            else
-                return clear;
-        }
-    }
-
-    var currentlyHighlighted = null;
-    function doMatchBrackets(cm) {
-        cm.operation(function () {
-            if (currentlyHighlighted) {
-                currentlyHighlighted();
-                currentlyHighlighted = null;
-            }
-            currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
-        });
-    }
-
-    CodeMirror.defineOption("matchBrackets", false, function (cm, val, old) {
-        if (old && old != CodeMirror.Init)
-            cm.off("cursorActivity", doMatchBrackets);
-        if (val) {
-            cm.state.matchBrackets = typeof val == "object" ? val : {};
-            cm.on("cursorActivity", doMatchBrackets);
-        }
-    });
-
-    CodeMirror.defineExtension("matchBrackets", function () {
-        matchBrackets(this, true);
-    });
-    CodeMirror.defineExtension("findMatchingBracket", function (pos, strict) {
-        return findMatchingBracket(this, pos, strict);
-    });
-    CodeMirror.defineExtension("scanForBracket", function (pos, dir, style) {
-        return scanForBracket(this, pos, dir, style);
-    });
-});

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.css
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.css b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.css
old mode 100755
new mode 100644
index 44449b2..924e638
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.css
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.css
@@ -1,38 +1,38 @@
 .CodeMirror-hints {
-    position: absolute;
-    z-index: 10;
-    overflow: hidden;
-    list-style: none;
+  position: absolute;
+  z-index: 10;
+  overflow: hidden;
+  list-style: none;
 
-    margin: 0;
-    padding: 2px;
+  margin: 0;
+  padding: 2px;
 
-    -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-    -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-    box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-    border-radius: 3px;
-    border: 1px solid silver;
+  -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  border-radius: 3px;
+  border: 1px solid silver;
 
-    background: white;
-    font-size: 90%;
-    font-family: monospace;
+  background: white;
+  font-size: 90%;
+  font-family: monospace;
 
-    max-height: 20em;
-    overflow-y: auto;
+  max-height: 20em;
+  overflow-y: auto;
 }
 
 .CodeMirror-hint {
-    margin: 0;
-    padding: 0 4px;
-    border-radius: 2px;
-    max-width: 19em;
-    overflow: hidden;
-    white-space: pre;
-    color: black;
-    cursor: pointer;
+  margin: 0;
+  padding: 0 4px;
+  border-radius: 2px;
+  max-width: 19em;
+  overflow: hidden;
+  white-space: pre;
+  color: black;
+  cursor: pointer;
 }
 
-.CodeMirror-hint-active {
-    background: #08f;
-    color: white;
+li.CodeMirror-hint-active {
+  background: #08f;
+  color: white;
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.js
deleted file mode 100755
index c820fdd..0000000
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/addon/hint/show-hint.js
+++ /dev/null
@@ -1,411 +0,0 @@
-(function (mod) {
-    if (typeof exports == "object" && typeof module == "object") // CommonJS
-        mod(require("../../lib/codemirror"));
-    else if (typeof define == "function" && define.amd) // AMD
-        define(["../../lib/codemirror"], mod);
-    else // Plain browser env
-        mod(CodeMirror);
-})(function (CodeMirror) {
-    "use strict";
-
-    var HINT_ELEMENT_CLASS = "CodeMirror-hint";
-    var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
-
-    CodeMirror.showHint = function (cm, getHints, options) {
-        // We want a single cursor position.
-        if (cm.listSelections().length > 1 || cm.somethingSelected())
-            return;
-        if (getHints == null) {
-            if (options && options.async)
-                return;
-            else
-                getHints = CodeMirror.hint.auto;
-        }
-
-        if (cm.state.completionActive)
-            cm.state.completionActive.close();
-
-        var completion = cm.state.completionActive = new Completion(cm, getHints, options || {});
-        CodeMirror.signal(cm, "startCompletion", cm);
-        if (completion.options.async)
-            getHints(cm, function (hints) {
-                completion.showHints(hints);
-            }, completion.options);
-        else
-            return completion.showHints(getHints(cm, completion.options));
-    };
-
-    function Completion(cm, getHints, options) {
-        this.cm = cm;
-        this.getHints = getHints;
-        this.options = options;
-        this.widget = this.onClose = null;
-    }
-
-    Completion.prototype = {
-        close: function () {
-            if (!this.active())
-                return;
-            this.cm.state.completionActive = null;
-
-            if (this.widget)
-                this.widget.close();
-            if (this.onClose)
-                this.onClose();
-            CodeMirror.signal(this.cm, "endCompletion", this.cm);
-        },
-        active: function () {
-            return this.cm.state.completionActive == this;
-        },
-        pick: function (data, i) {
-            var completion = data.list[i];
-            if (completion.hint)
-                completion.hint(this.cm, data, completion);
-            else
-                this.cm.replaceRange(getText(completion), completion.from || data.from, completion.to || data.to);
-            CodeMirror.signal(data, "pick", completion);
-            this.close();
-        },
-        showHints: function (data) {
-            if (!data || !data.list.length || !this.active())
-                return this.close();
-
-            if (this.options.completeSingle != false && data.list.length == 1)
-                this.pick(data, 0);
-            else
-                this.showWidget(data);
-        },
-        showWidget: function (data) {
-            this.widget = new Widget(this, data);
-            CodeMirror.signal(data, "shown");
-
-            var debounce = 0, completion = this, finished;
-            var closeOn = this.options.closeCharacters || /[\s()\[\]{};:>,]/;
-            var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
-
-            var requestAnimationFrame = window.requestAnimationFrame || function (fn) {
-                return setTimeout(fn, 1000 / 60);
-            };
-            var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
-
-            function done() {
-                if (finished)
-                    return;
-                finished = true;
-                completion.close();
-                completion.cm.off("cursorActivity", activity);
-                if (data)
-                    CodeMirror.signal(data, "close");
-            }
-
-            function update() {
-                if (finished)
-                    return;
-                CodeMirror.signal(data, "update");
-                if (completion.options.async)
-                    completion.getHints(completion.cm, finishUpdate, completion.options);
-                else
-                    finishUpdate(completion.getHints(completion.cm, completion.options));
-            }
-            function finishUpdate(data_) {
-                data = data_;
-                if (finished)
-                    return;
-                if (!data || !data.list.length)
-                    return done();
-                completion.widget = new Widget(completion, data);
-            }
-
-            function clearDebounce() {
-                if (debounce) {
-                    cancelAnimationFrame(debounce);
-                    debounce = 0;
-                }
-            }
-
-            function activity() {
-                clearDebounce();
-                var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
-                if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
-                        pos.ch < startPos.ch || completion.cm.somethingSelected() ||
-                        (pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
-                    completion.close();
-                } else {
-                    debounce = requestAnimationFrame(update);
-                    if (completion.widget)
-                        completion.widget.close();
-                }
-            }
-            this.cm.on("cursorActivity", activity);
-            this.onClose = done;
-        }
-    };
-
-    function getText(completion) {
-        if (typeof completion == "string")
-            return completion;
-        else
-            return completion.text;
-    }
-
-    function buildKeyMap(options, handle) {
-        var baseMap = {
-            Up: function () {
-                handle.moveFocus(-1);
-            },
-            Down: function () {
-                handle.moveFocus(1);
-            },
-            PageUp: function () {
-                handle.moveFocus(-handle.menuSize() + 1, true);
-            },
-            PageDown: function () {
-                handle.moveFocus(handle.menuSize() - 1, true);
-            },
-            Home: function () {
-                handle.setFocus(0);
-            },
-            End: function () {
-                handle.setFocus(handle.length - 1);
-            },
-            Enter: handle.pick,
-            Tab: handle.pick,
-            Esc: handle.close
-        };
-        var ourMap = options.customKeys ? {} : baseMap;
-        function addBinding(key, val) {
-            var bound;
-            if (typeof val != "string")
-                bound = function (cm) {
-                    return val(cm, handle);
-                };
-            // This mechanism is deprecated
-            else if (baseMap.hasOwnProperty(val))
-                bound = baseMap[val];
-            else
-                bound = val;
-            ourMap[key] = bound;
-        }
-        if (options.customKeys)
-            for (var key in options.customKeys)
-                if (options.customKeys.hasOwnProperty(key))
-                    addBinding(key, options.customKeys[key]);
-        if (options.extraKeys)
-            for (var key in options.extraKeys)
-                if (options.extraKeys.hasOwnProperty(key))
-                    addBinding(key, options.extraKeys[key]);
-        return ourMap;
-    }
-
-    function getHintElement(hintsElement, el) {
-        while (el && el != hintsElement) {
-            if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement)
-                return el;
-            el = el.parentNode;
-        }
-    }
-
-    function Widget(completion, data) {
-        this.completion = completion;
-        this.data = data;
-        var widget = this, cm = completion.cm, options = completion.options;
-
-        var hints = this.hints = document.createElement("ul");
-        hints.className = "CodeMirror-hints";
-        this.selectedHint = options.getDefaultSelection ? options.getDefaultSelection(cm, options, data) : 0;
-
-        var completions = data.list;
-        for (var i = 0; i < completions.length; ++i) {
-            var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
-            var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
-            if (cur.className != null)
-                className = cur.className + " " + className;
-            elt.className = className;
-            if (cur.render)
-                cur.render(elt, data, cur);
-            else
-                elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
-            elt.hintId = i;
-        }
-
-        var pos = cm.cursorCoords(options.alignWithWord !== false ? data.from : null);
-        var left = pos.left, top = pos.bottom, below = true;
-        hints.style.left = left + "px";
-        hints.style.top = top + "px";
-        // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
-        var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
-        var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
-        (options.container || document.body).appendChild(hints);
-        var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
-        if (overlapY > 0) {
-            var height = box.bottom - box.top, curTop = box.top - (pos.bottom - pos.top);
-            if (curTop - height > 0) { // Fits above cursor
-                hints.style.top = (top = curTop - height) + "px";
-                below = false;
-            } else if (height > winH) {
-                hints.style.height = (winH - 5) + "px";
-                hints.style.top = (top = pos.bottom - box.top) + "px";
-                var cursor = cm.getCursor();
-                if (data.from.ch != cursor.ch) {
-                    pos = cm.cursorCoords(cursor);
-                    hints.style.left = (left = pos.left) + "px";
-                    box = hints.getBoundingClientRect();
-                }
-            }
-        }
-        var overlapX = box.left - winW;
-        if (overlapX > 0) {
-            if (box.right - box.left > winW) {
-                hints.style.width = (winW - 5) + "px";
-                overlapX -= (box.right - box.left) - winW;
-            }
-            hints.style.left = (left = pos.left - overlapX) + "px";
-        }
-
-        cm.addKeyMap(this.keyMap = buildKeyMap(options, {
-            moveFocus: function (n, avoidWrap) {
-                widget.changeActive(widget.selectedHint + n, avoidWrap);
-            },
-            setFocus: function (n) {
-                widget.changeActive(n);
-            },
-            menuSize: function () {
-                return widget.screenAmount();
-            },
-            length: completions.length,
-            close: function () {
-                completion.close();
-            },
-            pick: function () {
-                widget.pick();
-            },
-            data: data
-        }));
-
-        if (options.closeOnUnfocus !== false) {
-            var closingOnBlur;
-            cm.on("blur", this.onBlur = function () {
-                closingOnBlur = setTimeout(function () {
-                    completion.close();
-                }, 100);
-            });
-            cm.on("focus", this.onFocus = function () {
-                clearTimeout(closingOnBlur);
-            });
-        }
-
-        var startScroll = cm.getScrollInfo();
-        cm.on("scroll", this.onScroll = function () {
-            var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
-            var newTop = top + startScroll.top - curScroll.top;
-            var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
-            if (!below)
-                point += hints.offsetHeight;
-            if (point <= editor.top || point >= editor.bottom)
-                return completion.close();
-            hints.style.top = newTop + "px";
-            hints.style.left = (left + startScroll.left - curScroll.left) + "px";
-        });
-
-        CodeMirror.on(hints, "dblclick", function (e) {
-            var t = getHintElement(hints, e.target || e.srcElement);
-            if (t && t.hintId != null) {
-                widget.changeActive(t.hintId);
-                widget.pick();
-            }
-        });
-
-        CodeMirror.on(hints, "click", function (e) {
-            var t = getHintElement(hints, e.target || e.srcElement);
-            if (t && t.hintId != null) {
-                widget.changeActive(t.hintId);
-                if (options.completeOnSingleClick)
-                    widget.pick();
-            }
-        });
-
-        CodeMirror.on(hints, "mousedown", function () {
-            setTimeout(function () {
-                cm.focus();
-            }, 20);
-        });
-
-        CodeMirror.signal(data, "select", completions[0], hints.firstChild);
-        return true;
-    }
-
-    Widget.prototype = {
-        close: function () {
-            if (this.completion.widget != this)
-                return;
-            this.completion.widget = null;
-            this.hints.parentNode.removeChild(this.hints);
-            this.completion.cm.removeKeyMap(this.keyMap);
-
-            var cm = this.completion.cm;
-            if (this.completion.options.closeOnUnfocus !== false) {
-                cm.off("blur", this.onBlur);
-                cm.off("focus", this.onFocus);
-            }
-            cm.off("scroll", this.onScroll);
-        },
-        pick: function () {
-            this.completion.pick(this.data, this.selectedHint);
-        },
-        changeActive: function (i, avoidWrap) {
-            if (i >= this.data.list.length)
-                i = avoidWrap ? this.data.list.length - 1 : 0;
-            else if (i < 0)
-                i = avoidWrap ? 0 : this.data.list.length - 1;
-            if (this.selectedHint == i)
-                return;
-            var node = this.hints.childNodes[this.selectedHint];
-            node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
-            node = this.hints.childNodes[this.selectedHint = i];
-            node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
-            if (node.offsetTop < this.hints.scrollTop)
-                this.hints.scrollTop = node.offsetTop - 3;
-            else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
-                this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
-            CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
-        },
-        screenAmount: function () {
-            return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
-        }
-    };
-
-    CodeMirror.registerHelper("hint", "auto", function (cm, options) {
-        var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
-        if (helpers.length) {
-            for (var i = 0; i < helpers.length; i++) {
-                var cur = helpers[i](cm, options);
-                if (cur && cur.list.length)
-                    return cur;
-            }
-        } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
-            if (words)
-                return CodeMirror.hint.fromList(cm, {words: words});
-        } else if (CodeMirror.hint.anyword) {
-            return CodeMirror.hint.anyword(cm, options);
-        }
-    });
-
-    CodeMirror.registerHelper("hint", "fromList", function (cm, options) {
-        var cur = cm.getCursor(), token = cm.getTokenAt(cur);
-        var found = [];
-        for (var i = 0; i < options.words.length; i++) {
-            var word = options.words[i];
-            if (word.slice(0, token.string.length) == token.string)
-                found.push(word);
-        }
-
-        if (found.length)
-            return {
-                list: found,
-                from: CodeMirror.Pos(cur.line, token.start),
-                to: CodeMirror.Pos(cur.line, token.end)
-            };
-    });
-
-    CodeMirror.commands.autocomplete = CodeMirror.showHint;
-});


[09/28] incubator-nifi git commit: Merge branch 'bootstrap' into develop

Posted by mc...@apache.org.
Merge branch 'bootstrap' into develop


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/cce36335
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/cce36335
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/cce36335

Branch: refs/heads/nifi-27
Commit: cce36335e1d22a6664d907c55e617d8807bcee90
Parents: 5ebf3b5 192d782
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 11:08:55 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 11:08:55 2014 -0500

----------------------------------------------------------------------
 assemblies/nifi/pom.xml                         |   5 +
 .../apache/nifi/controller/FlowController.java  |  15 +
 .../repository/FileSystemRepository.java        |   4 +-
 .../WriteAheadFlowFileRepository.java           |   7 +-
 .../scheduling/StandardProcessScheduler.java    |   3 +
 .../java/org/apache/nifi/engine/FlowEngine.java |  15 +
 .../src/main/resources/bin/nifi-status.bat      |  32 ++
 .../resources/src/main/resources/bin/nifi.sh    | 193 +---------
 .../src/main/resources/bin/run-nifi.bat         |  32 ++
 .../src/main/resources/bin/start-nifi.bat       |  32 ++
 .../src/main/resources/bin/stop-nifi.bat        |  32 ++
 .../src/main/resources/conf/bootstrap.conf      |  16 +
 .../java/org/apache/nifi/BootstrapListener.java | 234 ++++++++++++
 .../src/main/java/org/apache/nifi/NiFi.java     |  40 +-
 nifi-bootstrap/pom.xml                          |  17 +-
 .../apache/nifi/bootstrap/BootstrapCodec.java   |  89 +++++
 .../org/apache/nifi/bootstrap/NiFiListener.java | 116 ++++++
 .../java/org/apache/nifi/bootstrap/RunNiFi.java | 370 +++++++++++++++++--
 .../org/apache/nifi/bootstrap/ShutdownHook.java |  69 +++-
 .../exception/InvalidCommandException.java      |  37 ++
 20 files changed, 1136 insertions(+), 222 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/cce36335/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
----------------------------------------------------------------------
diff --cc nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
index 6fedfb7,81ae384..ad90d5b
--- a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
@@@ -21,40 -21,7 +21,12 @@@
  DIRNAME=`dirname "$0"`
  PROGNAME=`basename "$0"`
  
- #
- # Sourcing environment settings for NIFI similar to tomcats setenv
- #
- NIFI_SCRIPT="nifi.sh"
- export NIFI_SCRIPT
- if [ -f "$DIRNAME/setenv.sh" ]; then
-   . "$DIRNAME/setenv.sh"
- fi
- 
- #
- # Check/Set up some easily accessible MIN/MAX params for JVM mem usage
- #
- if [ "x$JAVA_MIN_MEM" = "x" ]; then
-     JAVA_MIN_MEM=512M
-     export JAVA_MIN_MEM
- fi
- if [ "x$JAVA_MAX_MEM" = "x" ]; then
-     JAVA_MAX_MEM=512M
-     export JAVA_MAX_MEM
- fi
- if [ "x$JAVA_PERMSIZE" = "x" ]; then
-     JAVA_PERMSIZE=128M
-     export JAVA_PERMSIZE
- fi
- if [ "x$JAVA_MAX_PERMSIZE" = "x" ]; then
-     JAVA_MAX_PERMSIZE=128M
-     export JAVA_MAX_PERMSIZE
- fi
  
 +#
 +#Readlink is not available on all systems. Change variable to appropriate alternative as part of OS detection
 +#
 +
 +READLINK="readlink"
  
  warn() {
      echo "${PROGNAME}: $*"


[04/28] incubator-nifi git commit: NIFI-145: Added batch scripts and a simple bootstrap.conf file and fixed ShutdownHook to be Java 7 compliant

Posted by mc...@apache.org.
NIFI-145: Added batch scripts and a simple bootstrap.conf file and fixed ShutdownHook to be Java 7 compliant


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/eed4a9bb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/eed4a9bb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/eed4a9bb

Branch: refs/heads/nifi-27
Commit: eed4a9bb810ceb5a366009c8379b06ed80b833f3
Parents: 6465704
Author: Mark Payne <ma...@hotmail.com>
Authored: Tue Dec 9 13:51:15 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Tue Dec 9 13:51:15 2014 -0500

----------------------------------------------------------------------
 .../src/main/resources/bin/nifi-status.bat      | 15 +++++++++
 .../src/main/resources/bin/start-nifi.bat       | 15 +++++++++
 .../src/main/resources/bin/stop-nifi.bat        | 15 +++++++++
 .../src/main/resources/conf/bootstrap.conf      |  9 ++++++
 .../org/apache/nifi/bootstrap/ShutdownHook.java | 33 +++++++++++++++-----
 5 files changed, 79 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/eed4a9bb/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat
new file mode 100644
index 0000000..9b88349
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat
@@ -0,0 +1,15 @@
+@echo off
+
+rem Use JAVA_HOME if it's set; otherwise, just use java
+IF "%JAVA_HOME%"=="" (SET JAVA_EXE=java) ELSE (SET JAVA_EXE=%JAVA_HOME%\bin\java.exe)
+
+SET LIB_DIR=%~dp0..\lib
+SET CONF_DIR=%~dp0..\conf
+
+SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
+SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+
+SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
+SET BOOTSTRAP_ACTION=status
+
+cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %BOOTSTRAP_ACTION%

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/eed4a9bb/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat
new file mode 100644
index 0000000..c088672
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat
@@ -0,0 +1,15 @@
+@echo off
+
+rem Use JAVA_HOME if it's set; otherwise, just use java
+IF "%JAVA_HOME%"=="" (SET JAVA_EXE=java) ELSE (SET JAVA_EXE=%JAVA_HOME%\bin\java.exe)
+
+SET LIB_DIR=%~dp0..\lib
+SET CONF_DIR=%~dp0..\conf
+
+SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
+SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+
+SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
+SET BOOTSTRAP_ACTION=start
+
+cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %BOOTSTRAP_ACTION%

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/eed4a9bb/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat
new file mode 100644
index 0000000..753b09f
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat
@@ -0,0 +1,15 @@
+@echo off
+
+rem Use JAVA_HOME if it's set; otherwise, just use java
+IF "%JAVA_HOME%"=="" (SET JAVA_EXE=java) ELSE (SET JAVA_EXE=%JAVA_HOME%\bin\java.exe)
+
+SET LIB_DIR=%~dp0..\lib
+SET CONF_DIR=%~dp0..\conf
+
+SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
+SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+
+SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
+SET BOOTSTRAP_ACTION=stop
+
+cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %BOOTSTRAP_ACTION%

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/eed4a9bb/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf b/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf
new file mode 100644
index 0000000..97d48f8
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf
@@ -0,0 +1,9 @@
+lib.dir=./lib
+conf.dir=./conf
+java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true
+
+java.arg.2=-Xms256m
+java.arg.3=-Xmx512m
+
+# Enable Remote Debugging
+#java.arg.2=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/eed4a9bb/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
index 142d984..f804c7c 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
@@ -53,19 +53,36 @@ public class ShutdownHook extends Thread {
 			}
 		}
 		
-		try {
-			nifiProcess.waitFor(WAIT_SECONDS, TimeUnit.SECONDS);
-		} catch (final InterruptedException ie) {
-		}
-
-		if ( nifiProcess.isAlive() ) {
-			System.out.println("NiFi has not finished shutting down after " + WAIT_SECONDS + " seconds. Killing process.");
+		System.out.println("Waiting for Apache NiFi to finish shutting down...");
+		final long startWait = System.nanoTime();
+		while ( isAlive(nifiProcess) ) {
+			final long waitNanos = System.nanoTime() - startWait;
+			final long waitSeconds = TimeUnit.NANOSECONDS.toSeconds(waitNanos);
+			if ( waitSeconds >= WAIT_SECONDS ) {
+				if ( isAlive(nifiProcess) ) {
+					System.out.println("NiFi has not finished shutting down after " + WAIT_SECONDS + " seconds. Killing process.");
+					nifiProcess.destroy();
+				}
+				break;
+			} else {
+				try {
+					Thread.sleep(1000L);
+				} catch (final InterruptedException ie) {}
+			}
 		}
-		nifiProcess.destroy();
 		
 		final File statusFile = runner.getStatusFile();
 		if ( !statusFile.delete() ) {
 			System.err.println("Failed to delete status file " + statusFile.getAbsolutePath());
 		}
 	}
+	
+	private boolean isAlive(final Process process) {
+		try {
+			process.exitValue();
+			return false;
+		} catch (final IllegalThreadStateException itse) {
+			return true;
+		}
+	}
 }


[14/28] incubator-nifi git commit: NIFI-27: - Latest version of D3.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b61a1def/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
index f570082..178207e 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
@@ -60,13 +60,6 @@ nf.StatusHistory = (function () {
     };
 
     /**
-     * version 3.4+ of D3 provides a mechanism for specifying
-     * a number of custom formatters. this achieves similar function
-     * until we're able to upgrade.
-     */
-    var timeFormats = null;
-
-    /**
      * The time offset of the server.
      */
     var serverTimeOffset = null;
@@ -373,26 +366,21 @@ nf.StatusHistory = (function () {
                 visible: instances[instance.id] === true
             });
         });
-
+        
         // --------------------------
         // custom time axis formatter
         // --------------------------
 
-        // create the formatting function
-        var customTimeFormat = function (d) {
-            var formatter;
-
-            // identify the most appropriate formatter for this date
-            $.each(timeFormats, function (_, timeFormat) {
-                if (timeFormat[1](d)) {
-                    formatter = timeFormat;
-                    return false;
-                }
-            });
-
-            // return the formatter date
-            return formatter[0](d);
-        };
+        var customTimeFormat = d3.time.format.multi([
+            [':%S.%L', function (d) { return d.getMilliseconds(); }], 
+            [':%S', function (d) { return d.getSeconds(); }],
+            ['%H:%M', function (d) { return d.getMinutes(); }],
+            ['%H:%M', function (d) { return d.getHours(); }],
+            ['%a %d', function (d) { return d.getDay() && d.getDate() !== 1; }],
+            ['%b %d', function (d) { return d.getDate() !== 1; }],
+            ['%B', function (d) { return d.getMonth(); }],
+            ['%Y', function () { return true; }]
+        ]);
 
         // ----------
         // main chart
@@ -1136,34 +1124,6 @@ nf.StatusHistory = (function () {
         init: function (timeOffset) {
             serverTimeOffset = timeOffset;
 
-            // initialize the time formats
-            timeFormats = [
-                [d3.time.format(':%S.%L'), function (d) {
-                        return d.getMilliseconds();
-                    }],
-                [d3.time.format(':%S'), function (d) {
-                        return d.getSeconds();
-                    }],
-                [d3.time.format('%H:%M'), function (d) {
-                        return d.getMinutes();
-                    }],
-                [d3.time.format('%H:%M'), function (d) {
-                        return d.getHours();
-                    }],
-                [d3.time.format('%a %d'), function (d) {
-                        return d.getDay() && d.getDate() !== 1;
-                    }],
-                [d3.time.format('%b %d'), function (d) {
-                        return d.getDate() !== 1;
-                    }],
-                [d3.time.format('%B'), function (d) {
-                        return d.getMonth();
-                    }],
-                [d3.time.format('%Y'), function () {
-                        return true;
-                    }]
-            ];
-
             nf.Common.addHoverEffect('#status-history-refresh-button', 'button-refresh', 'button-refresh-hover').click(function () {
                 var statusHistory = $('#status-history-dialog').data('status-history');
                 if (statusHistory !== null) {


[12/28] incubator-nifi git commit: NIFI-145: Fixed stack trace that occassionally occurs on shutdown

Posted by mc...@apache.org.
NIFI-145: Fixed stack trace that occassionally occurs on shutdown


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/f63cd9a1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/f63cd9a1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/f63cd9a1

Branch: refs/heads/nifi-27
Commit: f63cd9a15ee42715ff0b70873f30f3954242a957
Parents: 97f8ab0
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 12:17:32 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 12:17:32 2014 -0500

----------------------------------------------------------------------
 .../src/main/java/org/apache/nifi/bootstrap/RunNiFi.java       | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/f63cd9a1/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
index af783a1..1b82a3c 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
@@ -397,7 +397,11 @@ public class RunNiFi {
 					} catch (final InterruptedException ie) {
 					}
 				} else {
-					runtime.removeShutdownHook(shutdownHook);
+				    try {
+				        runtime.removeShutdownHook(shutdownHook);
+				    } catch (final IllegalStateException ise) {
+				        // happens when already shutting down
+				    }
 					
 					if (autoRestartNiFi) {
 						System.out.println("Apache NiFi appears to have died. Restarting...");


[17/28] incubator-nifi git commit: NIFI-27: - Latest version of qtip2.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.js
index de35e9a..411a0f8 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.js
@@ -1,706 +1,5 @@
-/*
- * qTip2 - Pretty powerful tooltips
- * http://craigsworks.com/projects/qtip2/
- *
- * Version: 2.0.0pre
- * Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com
- *
- * Dual licensed under MIT or GPLv2 licenses
- *   http://en.wikipedia.org/wiki/MIT_License
- *   http://en.wikipedia.org/wiki/GNU_General_Public_License
- *
- * Date: Thu Apr 26 20:40:09 2012 +0100
- *//*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true *//*global window: false, jQuery: false, console: false, define: false */// Uses AMD or browser globals to create a jQuery plugin.
-(function (a) {
-    typeof define == "function" && define.amd ? define(["jquery"], a) : a(jQuery)
-})(function (a) {
-    "use strict";
-    function v() {
-        v.history = v.history || [], v.history.push(arguments);
-        if ("object" == typeof console) {
-            var a = console[console.warn ? "warn" : "log"], b = Array.prototype.slice.call(arguments), c;
-            typeof arguments[0] == "string" && (b[0] = "qTip2: " + b[0]), c = a.apply ? a.apply(console, b) : a(b)
-        }
-    }
-    function w(b) {
-        var e;
-        if (!b || "object" != typeof b)
-            return c;
-        if (b.metadata === d || "object" != typeof b.metadata)
-            b.metadata = {type: b.metadata};
-        if ("content"in b) {
-            if (b.content === d || "object" != typeof b.content || b.content.jquery)
-                b.content = {text: b.content};
-            e = b.content.text || c, !a.isFunction(e) && (!e && !e.attr || e.length < 1 || "object" == typeof e && !e.jquery) && (b.content.text = c);
-            if ("title"in b.content) {
-                if (b.content.title === d || "object" != typeof b.content.title)
-                    b.content.title = {text: b.content.title};
-                e = b.content.title.text || c, !a.isFunction(e) && (!e && !e.attr || e.length < 1 || "object" == typeof e && !e.jquery) && (b.content.title.text = c)
-            }
-        }
-        return"position"in b && (b.position === d || "object" != typeof b.position) && (b.position = {my: b.position, at: b.position}), "show"in b && (b.show === d || "object" != typeof b.show) && (b.show.jquery ? b.show = {target: b.show} : b.show = {event: b.show}), "hide"in b && (b.hide === d || "object" != typeof b.hide) && (b.hide.jquery ? b.hide = {target: b.hide} : b.hide = {event: b.hide}), "style"in b && (b.style === d || "object" != typeof b.style) && (b.style = {classes: b.style}), a.each(g, function () {
-            this.sanitize && this.sanitize(b)
-        }), b
-    }
-    function x(r, s, v, x) {
-        function H(a) {
-            var b = 0, c, d = s, e = a.split(".");
-            while (d = d[e[b++]])
-                b < e.length && (c = d);
-            return[c || s, e.pop()]
-        }
-        function I() {
-            var a = s.style.widget;
-            D.toggleClass(k, a).toggleClass(n, s.style.def && !a), F.content.toggleClass(k + "-content", a), F.titlebar && F.titlebar.toggleClass(k + "-header", a), F.button && F.button.toggleClass(j + "-icon", !a)
-        }
-        function J(a) {
-            F.title && (F.titlebar.remove(), F.titlebar = F.title = F.button = d, a !== c && y.reposition())
-        }
-        function K() {
-            var b = s.content.title.button, d = typeof b == "string", e = d ? b : "Close tooltip";
-            F.button && F.button.remove(), b.jquery ? F.button = b : F.button = a("<a />", {"class": "ui-state-default ui-tooltip-close " + (s.style.widget ? "" : j + "-icon"), title: e, "aria-label": e}).prepend(a("<span />", {"class": "ui-icon ui-icon-close", html: "&times;"})), F.button.appendTo(F.titlebar).attr("role", "button").click(function (a) {
-                return D.hasClass(l) || y.hide(a), c
-            }), y.redraw()
-        }
-        function L() {
-            var c = A + "-title";
-            F.titlebar && J(), F.titlebar = a("<div />", {"class": j + "-titlebar " + (s.style.widget ? "ui-widget-header" : "")}).append(F.title = a("<div />", {id: c, "class": j + "-title", "aria-atomic": b})).insertBefore(F.content).delegate(".ui-tooltip-close", "mousedown keydown mouseup keyup mouseout", function (b) {
-                a(this).toggleClass("ui-state-active ui-state-focus", b.type.substr(-4) === "down")
-            }).delegate(".ui-tooltip-close", "mouseover mouseout", function (b) {
-                a(this).toggleClass("ui-state-hover", b.type === "mouseover")
-            }), s.content.title.button ? K() : y.rendered && y.redraw()
-        }
-        function M(a) {
-            var b = F.button, d = F.title;
-            if (!y.rendered)
-                return c;
-            a ? (d || L(), K()) : b.remove()
-        }
-        function N(b, d) {
-            var e = F.title;
-            if (!y.rendered || !b)
-                return c;
-            a.isFunction(b) && (b = b.call(r, G.event, y));
-            if (b === c || !b && b !== "")
-                return J(c);
-            b.jquery && b.length > 0 ? e.empty().append(b.css({display: "block"})) : e.html(b), y.redraw(), d !== c && y.rendered && D[0].offsetWidth > 0 && y.reposition(G.event)
-        }
-        function O(b, d) {
-            function g(b) {
-                function i(e) {
-                    e && (delete h[e.src], clearTimeout(y.timers.img[e.src]), a(e).unbind(E)), a.isEmptyObject(h) && (y.redraw(), d !== c && y.reposition(G.event), b())
-                }
-                var g, h = {};
-                if ((g = f.find("img[src]:not([height]):not([width])")).length === 0)
-                    return i();
-                g.each(function (b, c) {
-                    if (h[c.src] !== e)
-                        return;
-                    var d = 0, f = 3;
-                    (function g() {
-                        if (c.height || c.width || d > f)
-                            return i(c);
-                        d += 1, y.timers.img[c.src] = setTimeout(g, 700)
-                    })(), a(c).bind("error" + E + " load" + E, function () {
-                        i(this)
-                    }), h[c.src] = c
-                })
-            }
-            var f = F.content;
-            return!y.rendered || !b ? c : (a.isFunction(b) && (b = b.call(r, G.event, y) || ""), b.jquery && b.length > 0 ? f.empty().append(b.css({display: "block"})) : f.html(b), y.rendered < 0 ? D.queue("fx", g) : (C = 0, g(a.noop)), y)
-        }
-        function P() {
-            function j(a) {
-                if (D.hasClass(l))
-                    return c;
-                clearTimeout(y.timers.show), clearTimeout(y.timers.hide);
-                var d = function () {
-                    y.toggle(b, a)
-                };
-                s.show.delay > 0 ? y.timers.show = setTimeout(d, s.show.delay) : d()
-            }
-            function k(b) {
-                if (D.hasClass(l) || B || C)
-                    return c;
-                var f = a(b.relatedTarget || b.target), g = f.closest(m)[0] === D[0], h = f[0] === e.show[0];
-                clearTimeout(y.timers.show), clearTimeout(y.timers.hide);
-                if (d.target === "mouse" && g || s.hide.fixed && /mouse(out|leave|move)/.test(b.type) && (g || h)) {
-                    try {
-                        b.preventDefault(), b.stopImmediatePropagation()
-                    } catch (i) {
-                    }
-                    return
-                }
-                s.hide.delay > 0 ? y.timers.hide = setTimeout(function () {
-                    y.hide(b)
-                }, s.hide.delay) : y.hide(b)
-            }
-            function n(a) {
-                if (D.hasClass(l))
-                    return c;
-                clearTimeout(y.timers.inactive), y.timers.inactive = setTimeout(function () {
-                    y.hide(a)
-                }, s.hide.inactive)
-            }
-            function o(a) {
-                y.rendered && D[0].offsetWidth > 0 && y.reposition(a)
-            }
-            var d = s.position, e = {show: s.show.target, hide: s.hide.target, viewport: a(d.viewport), document: a(document), body: a(document.body), window: a(window)}, g = {show: a.trim("" + s.show.event).split(" "), hide: a.trim("" + s.hide.event).split(" ")}, i = a.browser.msie && parseInt(a.browser.version, 10) === 6;
-            D.bind("mouseenter" + E + " mouseleave" + E, function (a) {
-                var b = a.type === "mouseenter";
-                b && y.focus(a), D.toggleClass(p, b)
-            }), s.hide.fixed && (e.hide = e.hide.add(D), D.bind("mouseover" + E, function () {
-                D.hasClass(l) || clearTimeout(y.timers.hide)
-            })), /mouse(out|leave)/i.test(s.hide.event) ? s.hide.leave === "window" && e.window.bind("mouseout" + E + " blur" + E, function (a) {
-                /select|option/.test(a.target) && !a.relatedTarget && y.hide(a)
-            }) : /mouse(over|enter)/i.test(s.show.event) && e.hide.bind("mouseleave" + E, function (a) {
-                clearTimeout(y.timers.show)
-            }), ("" + s.hide.event).indexOf("unfocus") > -1 && d.container.closest("html").bind("mousedown" + E, function (b) {
-                var c = a(b.target), d = y.rendered && !D.hasClass(l) && D[0].offsetWidth > 0, e = c.parents(m).filter(D[0]).length > 0;
-                c[0] !== r[0] && c[0] !== D[0] && !e && !r.has(c[0]).length && !c.attr("disabled") && y.hide(b)
-            }), "number" == typeof s.hide.inactive && (e.show.bind("qtip-" + v + "-inactive", n), a.each(f.inactiveEvents, function (a, b) {
-                e.hide.add(F.tooltip).bind(b + E + "-inactive", n)
-            })), a.each(g.hide, function (b, c) {
-                var d = a.inArray(c, g.show), f = a(e.hide);
-                d > -1 && f.add(e.show).length === f.length || c === "unfocus" ? (e.show.bind(c + E, function (a) {
-                    D[0].offsetWidth > 0 ? k(a) : j(a)
-                }), delete g.show[d]) : e.hide.bind(c + E, k)
-            }), a.each(g.show, function (a, b) {
-                e.show.bind(b + E, j)
-            }), "number" == typeof s.hide.distance && e.show.add(D).bind("mousemove" + E, function (a) {
-                var b = G.origin || {}, c = s.hide.distance, d = Math.abs;
-                (d(a.pageX - b.pageX) >= c || d(a.pageY - b.pageY) >= c) && y.hide(a)
-            }), d.target === "mouse" && (e.show.bind("mousemove" + E, function (a) {
-                h = {pageX: a.pageX, pageY: a.pageY, type: "mousemove"}
-            }), d.adjust.mouse && (s.hide.event && (D.bind("mouseleave" + E, function (a) {
-                (a.relatedTarget || a.target) !== e.show[0] && y.hide(a)
-            }), F.target.bind("mouseenter" + E + " mouseleave" + E, function (a) {
-                G.onTarget = a.type === "mouseenter"
-            })), e.document.bind("mousemove" + E, function (a) {
-                y.rendered && G.onTarget && !D.hasClass(l) && D[0].offsetWidth > 0 && y.reposition(a || h)
-            }))), (d.adjust.resize || e.viewport.length) && (a.event.special.resize ? e.viewport : e.window).bind("resize" + E, o), (e.viewport.length || i && D.css("position") === "fixed") && e.viewport.bind("scroll" + E, o)
-        }
-        function Q() {
-            var b = [s.show.target[0], s.hide.target[0], y.rendered && F.tooltip[0], s.position.container[0], s.position.viewport[0], window, document];
-            y.rendered ? a([]).pushStack(a.grep(b, function (a) {
-                return typeof a == "object"
-            })).unbind(E) : s.show.target.unbind(E + "-create")
-        }
-        var y = this, z = document.body, A = j + "-" + v, B = 0, C = 0, D = a(), E = ".qtip-" + v, F, G;
-        y.id = v, y.rendered = c, y.destroyed = c, y.elements = F = {target: r}, y.timers = {img: {}}, y.options = s, y.checks = {}, y.plugins = {}, y.cache = G = {event: {}, target: a(), disabled: c, attr: x, onTarget: c}, y.checks.builtin = {"^id$": function (d, e, g) {
-                var h = g === b ? f.nextid : g, i = j + "-" + h;
-                h !== c && h.length > 0 && !a("#" + i).length && (D[0].id = i, F.content[0].id = i + "-content", F.title[0].id = i + "-title")
-            }, "^content.text$": function (a, b, c) {
-                O(c)
-            }, "^content.title.text$": function (a, b, c) {
-                if (!c)
-                    return J();
-                !F.title && c && L(), N(c)
-            }, "^content.title.button$": function (a, b, c) {
-                M(c)
-            }, "^position.(my|at)$": function (a, b, c) {
-                "string" == typeof c && (a[b] = new g.Corner(c))
-            }, "^position.container$": function (a, b, c) {
-                y.rendered && D.appendTo(c)
-            }, "^show.ready$": function () {
-                y.rendered ? y.toggle(b) : y.render(1)
-            }, "^style.classes$": function (a, b, c) {
-                D.attr("class", j + " qtip ui-helper-reset " + c)
-            }, "^style.widget|content.title": I, "^events.(render|show|move|hide|focus|blur)$": function (b, c, d) {
-                D[(a.isFunction(d) ? "" : "un") + "bind"]("tooltip" + c, d)
-            }, "^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)": function () {
-                var a = s.position;
-                D.attr("tracking", a.target === "mouse" && a.adjust.mouse), Q(), P()
-            }}, a.extend(y, {render: function (d) {
-                if (y.rendered)
-                    return y;
-                var e = s.content.text, f = s.content.title.text, h = s.position, i = a.Event("tooltiprender");
-                return a.attr(r[0], "aria-describedby", A), D = F.tooltip = a("<div/>", {id: A, "class": j + " qtip ui-helper-reset " + n + " " + s.style.classes + " " + j + "-pos-" + s.position.my.abbrev(), width: s.style.width || "", height: s.style.height || "", tracking: h.target === "mouse" && h.adjust.mouse, role: "alert", "aria-live": "polite", "aria-atomic": c, "aria-describedby": A + "-content", "aria-hidden": b}).toggleClass(l, G.disabled).data("qtip", y).appendTo(s.position.container).append(F.content = a("<div />", {"class": j + "-content", id: A + "-content", "aria-atomic": b})), y.rendered = -1, C = 1, B = 1, f && (L(), a.isFunction(f) || N(f, c)), a.isFunction(e) || O(e, c), y.rendered = b, I(), a.each(s.events, function (b, c) {
-                    a.isFunction(c) && D.bind(b === "toggle" ? "tooltipshow tooltiphide" : "tooltip" + b, c)
-                }), a.each(g, function () {
-                    this.initialize === "render" && this(y)
-                }), P(), D.queue("fx", function (a) {
-                    i.originalEvent = G.event, D.trigger(i, [y]), C = 0, B = 0, y.redraw(), (s.show.ready || d) && y.toggle(b, G.event, c), a()
-                }), y
-            }, get: function (a) {
-                var b, c;
-                switch (a.toLowerCase()) {
-                    case"dimensions":
-                        b = {height: D.outerHeight(), width: D.outerWidth()};
-                        break;
-                    case"offset":
-                        b = g.offset(D, s.position.container);
-                        break;
-                    default:
-                        c = H(a.toLowerCase()), b = c[0][c[1]], b = b.precedance ? b.string() : b
-                }
-                return b
-            }, set: function (e, f) {
-                function m(a, b) {
-                    var c, d, e;
-                    for (c in k)
-                        for (d in k[c])
-                            if (e = (new RegExp(d, "i")).exec(a))
-                                b.push(e), k[c][d].apply(y, b)
-                }
-                var g = /^position\.(my|at|adjust|target|container)|style|content|show\.ready/i, h = /^content\.(title|attr)|style/i, i = c, j = c, k = y.checks, l;
-                return"string" == typeof e ? (l = e, e = {}, e[l] = f) : e = a.extend(b, {}, e), a.each(e, function (b, c) {
-                    var d = H(b.toLowerCase()), f;
-                    f = d[0][d[1]], d[0][d[1]] = "object" == typeof c && c.nodeType ? a(c) : c, e[b] = [d[0], d[1], c, f], i = g.test(b) || i, j = h.test(b) || j
-                }), w(s), B = C = 1, a.each(e, m), B = C = 0, y.rendered && D[0].offsetWidth > 0 && (i && y.reposition(s.position.target === "mouse" ? d : G.event), j && y.redraw()), y
-            }, toggle: function (e, f) {
-                function t() {
-                    e ? (a.browser.msie && D[0].style.removeAttribute("filter"), D.css("overflow", ""), "string" == typeof i.autofocus && a(i.autofocus, D).focus(), i.target.trigger("qtip-" + v + "-inactive")) : D.css({display: "", visibility: "", opacity: "", left: "", top: ""}), r = a.Event("tooltip" + (e ? "visible" : "hidden")), r.originalEvent = f ? G.event : d, D.trigger(r, [y])
-                }
-                if (!y.rendered)
-                    return e ? y.render(1) : y;
-                var g = e ? "show" : "hide", i = s[g], j = s[e ? "hide" : "show"], k = s.position, l = s.content, n = D[0].offsetWidth > 0, o = e || i.target.length === 1, p = !f || i.target.length < 2 || G.target[0] === f.target, q, r;
-                (typeof e).search("boolean|number") && (e = !n);
-                if (!D.is(":animated") && n === e && p)
-                    return y;
-                if (f) {
-                    if (/over|enter/.test(f.type) && /out|leave/.test(G.event.type) && s.show.target.add(f.target).length === s.show.target.length && D.has(f.relatedTarget).length)
-                        return y;
-                    G.event = a.extend({}, f)
-                }
-                return r = a.Event("tooltip" + g), r.originalEvent = f ? G.event : d, D.trigger(r, [y, 90]), r.isDefaultPrevented() ? y : (a.attr(D[0], "aria-hidden", !e), e ? (G.origin = a.extend({}, h), y.focus(f), a.isFunction(l.text) && O(l.text, c), a.isFunction(l.title.text) && N(l.title.text, c), !u && k.target === "mouse" && k.adjust.mouse && (a(document).bind("mousemove.qtip", function (a) {
-                    h = {pageX: a.pageX, pageY: a.pageY, type: "mousemove"}
-                }), u = b), y.reposition(f, arguments[2]), (r.solo = !!i.solo) && a(m, i.solo).not(D).qtip("hide", r)) : (clearTimeout(y.timers.show), delete G.origin, u && !a(m + '[tracking="true"]:visible', i.solo).not(D).length && (a(document).unbind("mousemove.qtip"), u = c), y.blur(f)), i.effect === c || o === c ? (D[g](), t.call(D)) : a.isFunction(i.effect) ? (D.stop(1, 1), i.effect.call(D, y), D.queue("fx", function (a) {
-                    t(), a()
-                })) : D.fadeTo(90, e ? 1 : 0, t), e && i.target.trigger("qtip-" + v + "-inactive"), y)
-            }, show: function (a) {
-                return y.toggle(b, a)
-            }, hide: function (a) {
-                return y.toggle(c, a)
-            }, focus: function (b) {
-                if (!y.rendered)
-                    return y;
-                var c = a(m), d = parseInt(D[0].style.zIndex, 10), e = f.zindex + c.length, g = a.extend({}, b), h, i;
-                return D.hasClass(o) || (i = a.Event("tooltipfocus"), i.originalEvent = g, D.trigger(i, [y, e]), i.isDefaultPrevented() || (d !== e && (c.each(function () {
-                    this.style.zIndex > d && (this.style.zIndex = this.style.zIndex - 1)
-                }), c.filter("." + o).qtip("blur", g)), D.addClass(o)[0].style.zIndex = e)), y
-            }, blur: function (b) {
-                var c = a.extend({}, b), d;
-                return D.removeClass(o), d = a.Event("tooltipblur"), d.originalEvent = c, D.trigger(d, [y]), y
-            }, reposition: function (b, d) {
-                if (!y.rendered || B)
-                    return y;
-                B = 1;
-                var e = s.position.target, f = s.position, i = f.my, k = f.at, l = f.adjust, m = l.method.split(" "), n = D.outerWidth(), o = D.outerHeight(), p = 0, q = 0, r = a.Event("tooltipmove"), t = D.css("position") === "fixed", u = f.viewport, v = {left: 0, top: 0}, w = f.container, x = c, A = y.plugins.tip, C = D[0].offsetWidth > 0, E = {horizontal: m[0], vertical: m[1] = m[1] || m[0], enabled: u.jquery && e[0] !== window && e[0] !== z && l.method !== "none", left: function (a) {
-                        var b = E.horizontal === "shift", c = l.x * (E.horizontal.substr(-6) === "invert" ? 2 : 0), d = -w.offset.left + u.offset.left + u.scrollLeft, e = i.x === "left" ? n : i.x === "right" ? -n : -n / 2, f = k.x === "left" ? p : k.x === "right" ? -p : -p / 2, g = A && A.size ? A.size.width || 0 : 0, h = A && A.corner && A.corner.precedance === "x" && !b ? g : 0, j = d - a + h, m = a + n - u.width - d + h, o = e - (i.precedance === "x" || i.x === i.y ? f : 0) - (k.x === "center" ? p / 2 : 0), q = i.x === "center";
-                        return b ? (h = A && A.corner && A.corner.precedance === "y" ? g : 0, o = (i.x === "left" ? 1 : -1) * e - h, v.left += j > 0 ? j : m > 0 ? -m : 0, v.left = Math.max(-w.offset.left + u.offset.left + (h && A.corner.x === "center" ? A.offset : 0), a - o, Math.min(Math.max(-w.offset.left + u.offset.left + u.width, a + o), v.left))) : (j > 0 && (i.x !== "left" || m > 0) ? v.left -= o + c : m > 0 && (i.x !== "right" || j > 0) && (v.left -= (q ? -o : o) + c), v.left < d && -v.left > m && (v.left = a)), v.left - a
-                    }, top: function (a) {
-                        var b = E.vertical === "shift", c = l.y * (E.vertical.substr(-6) === "invert" ? 2 : 0), d = -w.offset.top + u.offset.top + u.scrollTop, e = i.y === "top" ? o : i.y === "bottom" ? -o : -o / 2, f = k.y === "top" ? q : k.y === "bottom" ? -q : -q / 2, g = A && A.size ? A.size.height || 0 : 0, h = A && A.corner && A.corner.precedance === "y" && !b ? g : 0, j = d - a + h, m = a + o - u.height - d + h, n = e - (i.precedance === "y" || i.x === i.y ? f : 0) - (k.y === "center" ? q / 2 : 0), p = i.y === "center";
-                        return b ? (h = A && A.corner && A.corner.precedance === "x" ? g : 0, n = (i.y === "top" ? 1 : -1) * e - h, v.top += j > 0 ? j : m > 0 ? -m : 0, v.top = Math.max(-w.offset.top + u.offset.top + (h && A.corner.x === "center" ? A.offset : 0), a - n, Math.min(Math.max(-w.offset.top + u.offset.top + u.height, a + n), v.top))) : (j > 0 && (i.y !== "top" || m > 0) ? v.top -= n + c : m > 0 && (i.y !== "bottom" || j > 0) && (v.top -= (p ? -n : n) + c), v.top < 0 && -v.top > m && (v.top = a)), v.top - a
-                    }}, H;
-                if (a.isArray(e) && e.length === 2)
-                    k = {x: "left", y: "top"}, v = {left: e[0], top: e[1]};
-                else if (e === "mouse" && (b && b.pageX || G.event.pageX))
-                    k = {x: "left", y: "top"}, b = (!b || b.type !== "resize" && b.type !== "scroll" ? b && b.pageX && b.type === "mousemove" ? b : h && h.pageX && (l.mouse || !b || !b.pageX) ? {pageX: h.pageX, pageY: h.pageY} : !l.mouse && G.origin && G.origin.pageX && s.show.distance ? G.origin : b : G.event) || b || G.event || h || {}, v = {top: b.pageY, left: b.pageX};
-                else {
-                    e === "event" ? b && b.target && b.type !== "scroll" && b.type !== "resize" ? e = G.target = a(b.target) : e = G.target : e = G.target = a(e.jquery ? e : F.target), e = a(e).eq(0);
-                    if (e.length === 0)
-                        return y;
-                    e[0] === document || e[0] === window ? (p = g.iOS ? window.innerWidth : e.width(), q = g.iOS ? window.innerHeight : e.height(), e[0] === window && (v = {top: (u || e).scrollTop(), left: (u || e).scrollLeft()})) : e.is("area") && g.imagemap ? v = g.imagemap(e, k, E.enabled ? m : c) : e[0].namespaceURI === "http://www.w3.org/2000/svg" && g.svg ? v = g.svg(e, k) : (p = e.outerWidth(), q = e.outerHeight(), v = g.offset(e, w)), v.offset && (p = v.width, q = v.height, x = v.flipoffset, v = v.offset);
-                    if (g.iOS < 4.1 && g.iOS > 3.1 || g.iOS == 4.3 || !g.iOS && t)
-                        H = a(window), v.left -= H.scrollLeft(), v.top -= H.scrollTop();
-                    v.left += k.x === "right" ? p : k.x === "center" ? p / 2 : 0, v.top += k.y === "bottom" ? q : k.y === "center" ? q / 2 : 0
-                }
-                return v.left += l.x + (i.x === "right" ? -n : i.x === "center" ? -n / 2 : 0), v.top += l.y + (i.y === "bottom" ? -o : i.y === "center" ? -o / 2 : 0), E.enabled ? (u = {elem: u, height: u[(u[0] === window ? "h" : "outerH") + "eight"](), width: u[(u[0] === window ? "w" : "outerW") + "idth"](), scrollLeft: t ? 0 : u.scrollLeft(), scrollTop: t ? 0 : u.scrollTop(), offset: u.offset() || {left: 0, top: 0}}, w = {elem: w, scrollLeft: w.scrollLeft(), scrollTop: w.scrollTop(), offset: w.offset() || {left: 0, top: 0}}, v.adjusted = {left: E.horizontal !== "none" ? E.left(v.left) : 0, top: E.vertical !== "none" ? E.top(v.top) : 0}, v.adjusted.left + v.adjusted.top && D.attr("class", D[0].className.replace(/ui-tooltip-pos-\w+/i, j + "-pos-" + i.abbrev())), x && v.adjusted.left && (v.left += x.left), x && v.adjusted.top && (v.top += x.top)) : v.adjusted = {left: 0, top: 0}, r.originalEvent = a.extend({}, b), D.trigger(r, [y, v, u.elem || u]), r.isDefaultPrevented() ? y : (delete
  v.adjusted, d === c || !C || isNaN(v.left) || isNaN(v.top) || e === "mouse" || !a.isFunction(f.effect) ? D.css(v) : a.isFunction(f.effect) && (f.effect.call(D, y, a.extend({}, v)), D.queue(function (b) {
-                    a(this).css({opacity: "", height: ""}), a.browser.msie && this.style.removeAttribute("filter"), b()
-                })), B = 0, y)
-            }, redraw: function () {
-                if (y.rendered < 1 || C)
-                    return y;
-                var a = s.position.container, b, c, d, e;
-                return C = 1, s.style.height && D.css("height", s.style.height), s.style.width ? D.css("width", s.style.width) : (D.css("width", "").addClass(q), c = D.width() + 1, d = D.css("max-width") || "", e = D.css("min-width") || "", b = (d + e).indexOf("%") > -1 ? a.width() / 100 : 0, d = (d.indexOf("%") > -1 ? b : 1) * parseInt(d, 10) || c, e = (e.indexOf("%") > -1 ? b : 1) * parseInt(e, 10) || 0, c = d + e ? Math.min(Math.max(c, e), d) : c, D.css("width", Math.round(c)).removeClass(q)), C = 0, y
-            }, disable: function (b) {
-                return"boolean" != typeof b && (b = !D.hasClass(l) && !G.disabled), y.rendered ? (D.toggleClass(l, b), a.attr(D[0], "aria-disabled", b)) : G.disabled = !!b, y
-            }, enable: function () {
-                return y.disable(c)
-            }, destroy: function () {
-                var c = r[0], d = a.attr(c, t), e = r.data("qtip");
-                y.destroyed = b, y.rendered && (D.stop(1, 0).remove(), a.each(y.plugins, function () {
-                    this.destroy && this.destroy()
-                })), clearTimeout(y.timers.show), clearTimeout(y.timers.hide), Q();
-                if (!e || y === e)
-                    a.removeData(c, "qtip"), s.suppress && d && (a.attr(c, "title", d), r.removeAttr(t)), r.removeAttr("aria-describedby");
-                return r.unbind(".qtip-" + v), delete i[y.id], r
-            }})
-    }
-    function y(e, h) {
-        var i, j, k, l, m, n = a(this), o = a(document.body), p = this === document ? o : n, q = n.metadata ? n.metadata(h.metadata) : d, r = h.metadata.type === "html5" && q ? q[h.metadata.name] : d, s = n.data(h.metadata.name || "qtipopts");
-        try {
-            s = typeof s == "string" ? (new Function("return " + s))() : s
-        } catch (u) {
-            v("Unable to parse HTML5 attribute data: " + s)
-        }
-        l = a.extend(b, {}, f.defaults, h, typeof s == "object" ? w(s) : d, w(r || q)), j = l.position, l.id = e;
-        if ("boolean" == typeof l.content.text) {
-            k = n.attr(l.content.attr);
-            if (l.content.attr === c || !k)
-                return v("Unable to locate content for tooltip! Aborting render of tooltip on element: ", n), c;
-            l.content.text = k
-        }
-        j.container.length || (j.container = o), j.target === c && (j.target = p), l.show.target === c && (l.show.target = p), l.show.solo === b && (l.show.solo = j.container.closest("body")), l.hide.target === c && (l.hide.target = p), l.position.viewport === b && (l.position.viewport = j.container), j.container = j.container.eq(0), j.at = new g.Corner(j.at), j.my = new g.Corner(j.my);
-        if (a.data(this, "qtip"))
-            if (l.overwrite)
-                n.qtip("destroy");
-            else if (l.overwrite === c)
-                return c;
-        return l.suppress && (m = a.attr(this, "title")) && a(this).removeAttr("title").attr(t, m), i = new x(n, l, e, !!k), a.data(this, "qtip", i), n.bind("remove.qtip-" + e + " removeqtip.qtip-" + e, function () {
-            i.destroy()
-        }), i
-    }
-    function z(d) {
-        var e = this, g = d.elements.tooltip, h = d.options.content.ajax, i = f.defaults.content.ajax, j = ".qtip-ajax", k = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, l = b, m = c, n;
-        d.checks.ajax = {"^content.ajax": function (a, b, c) {
-                b === "ajax" && (h = c), b === "once" ? e.init() : h && h.url ? e.load() : g.unbind(j)
-            }}, a.extend(e, {init: function () {
-                return h && h.url && g.unbind(j)[h.once ? "one" : "bind"]("tooltipshow" + j, e.load), e
-            }, load: function (f) {
-                function r() {
-                    var e;
-                    if (d.destroyed)
-                        return;
-                    l = c, p && (m = b, d.show(f.originalEvent)), (e = i.complete || h.complete) && a.isFunction(e) && e.apply(h.context || d, arguments)
-                }
-                function s(b, c, e) {
-                    var f;
-                    if (d.destroyed)
-                        return;
-                    o && (b = a("<div/>").append(b.replace(k, "")).find(o)), (f = i.success || h.success) && a.isFunction(f) ? f.call(h.context || d, b, c, e) : d.set("content.text", b)
-                }
-                function t(a, b, c) {
-                    if (d.destroyed || a.status === 0)
-                        return;
-                    d.set("content.text", b + ": " + c)
-                }
-                if (m) {
-                    m = c;
-                    return
-                }
-                var g = h.url.indexOf(" "), j = h.url, o, p = !h.loading && l;
-                if (p)
-                    try {
-                        f.preventDefault()
-                    } catch (q) {
-                    }
-                else if (f && f.isDefaultPrevented())
-                    return e;
-                n && n.abort && n.abort(), g > -1 && (o = j.substr(g), j = j.substr(0, g)), n = a.ajax(a.extend({error: i.error || t, context: d}, h, {url: j, success: s, complete: r}))
-            }, destroy: function () {
-                n && n.abort && n.abort(), d.destroyed = b
-            }}), e.init()
-    }
-    function A(b) {
-        var c = this, d = b.elements, e = d.tooltip, f = ".bgiframe-" + b.id;
-        a.extend(c, {init: function () {
-                d.bgiframe = a('<iframe class="ui-tooltip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';"  style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>'), d.bgiframe.appendTo(e), e.bind("tooltipmove" + f, c.adjust)
-            }, adjust: function () {
-                var a = b.get("dimensions"), c = b.plugins.tip, f = d.tip, g, h;
-                h = parseInt(e.css("border-left-width"), 10) || 0, h = {left: -h, top: -h}, c && f && (g = c.corner.precedance === "x" ? ["width", "left"] : ["height", "top"], h[g[1]] -= f[g[0]]()), d.bgiframe.css(h).css(a)
-            }, destroy: function () {
-                d.bgiframe.remove(), e.unbind(f)
-            }}), c.init()
-    }
-    function B(d) {
-        var e = this, f = d.options.show.modal, h = d.elements, i = h.tooltip, j = "#qtip-overlay", k = ".qtipmodal", l = k + d.id, n = "is-modal-qtip", p = a(document.body), q;
-        d.checks.modal = {"^show.modal.(on|blur)$": function () {
-                e.init(), h.overlay.toggle(i.is(":visible"))
-            }}, a.extend(e, {init: function () {
-                return f.on ? (q = e.create(), i.attr(n, b).css("z-index", g.modal.zindex + a(m + "[" + n + "]").length).unbind(k).unbind(l).bind("tooltipshow" + k + " tooltiphide" + k, function (b, c, d) {
-                    var f = b.originalEvent;
-                    if (b.target === i[0])
-                        if (f && b.type === "tooltiphide" && /mouse(leave|enter)/.test(f.type) && a(f.relatedTarget).closest(q[0]).length)
-                            try {
-                                b.preventDefault()
-                            } catch (g) {
-                            }
-                        else
-                            (!f || f && !f.solo) && e[b.type.replace("tooltip", "")](b, d)
-                }).bind("tooltipfocus" + k, function (b) {
-                    if (b.isDefaultPrevented() || b.target !== i[0])
-                        return;
-                    var c = a(m).filter("[" + n + "]"), d = g.modal.zindex + c.length, e = parseInt(i[0].style.zIndex, 10);
-                    q[0].style.zIndex = d - 1, c.each(function () {
-                        this.style.zIndex > e && (this.style.zIndex -= 1)
-                    }), c.end().filter("." + o).qtip("blur", b.originalEvent), i.addClass(o)[0].style.zIndex = d;
-                    try {
-                        b.preventDefault()
-                    } catch (f) {
-                    }
-                }).bind("tooltiphide" + k, function (b) {
-                    b.target === i[0] && a("[" + n + "]").filter(":visible").not(i).last().qtip("focus", b)
-                }), f.escape && a(window).unbind(l).bind("keydown" + l, function (a) {
-                    a.keyCode === 27 && i.hasClass(o) && d.hide(a)
-                }), f.blur && h.overlay.unbind(l).bind("click" + l, function (a) {
-                    i.hasClass(o) && d.hide(a)
-                }), e) : e
-            }, create: function () {
-                function d() {
-                    q.css({height: a(window).height(), width: a(window).width()})
-                }
-                var b = a(j);
-                return b.length ? h.overlay = b.insertAfter(a(m).last()) : (q = h.overlay = a("<div />", {id: j.substr(1), html: "<div></div>", mousedown: function () {
-                        return c
-                    }}).insertAfter(a(m).last()), a(window).unbind(k).bind("resize" + k, d), d(), q)
-            }, toggle: function (d, g, h) {
-                if (d && d.isDefaultPrevented())
-                    return e;
-                var j = f.effect, k = g ? "show" : "hide", o = q.is(":visible"), r = a("[" + n + "]").filter(":visible").not(i), s;
-                return q || (q = e.create()), q.is(":animated") && o === g || !g && r.length ? e : (g ? (q.css({left: 0, top: 0}), q.toggleClass("blurs", f.blur), p.bind("focusin" + l, function (b) {
-                    var d = a(b.target), e = d.closest(".qtip"), f = e.length < 1 ? c : parseInt(e[0].style.zIndex, 10) > parseInt(i[0].style.zIndex, 10);
-                    !f && a(b.target).closest(m)[0] !== i[0] && i.find("input:visible").filter(":first").focus()
-                })) : p.undelegate("*", "focusin" + l), q.stop(b, c), a.isFunction(j) ? j.call(q, g) : j === c ? q[k]() : q.fadeTo(parseInt(h, 10) || 90, g ? 1 : 0, function () {
-                    g || a(this).hide()
-                }), g || q.queue(function (a) {
-                    q.css({left: "", top: ""}), a()
-                }), e)
-            }, show: function (a, c) {
-                return e.toggle(a, b, c)
-            }, hide: function (a, b) {
-                return e.toggle(a, c, b)
-            }, destroy: function () {
-                var b = q;
-                return b && (b = a("[" + n + "]").not(i).length < 1, b ? (h.overlay.remove(), a(window).unbind(k)) : h.overlay.unbind(k + d.id), p.undelegate("*", "focusin" + l)), i.removeAttr(n).unbind(k)
-            }}), e.init()
-    }
-    function C(a, b, c) {
-        var d = Math.ceil(b / 2), e = Math.ceil(c / 2), f = {bottomright: [[0, 0], [b, c], [b, 0]], bottomleft: [[0, 0], [b, 0], [0, c]], topright: [[0, c], [b, 0], [b, c]], topleft: [[0, 0], [0, c], [b, c]], topcenter: [[0, c], [d, 0], [b, c]], bottomcenter: [[0, 0], [b, 0], [d, c]], rightcenter: [[0, 0], [b, e], [0, c]], leftcenter: [[b, 0], [b, c], [0, e]]};
-        return f.lefttop = f.bottomright, f.righttop = f.bottomleft, f.leftbottom = f.topright, f.rightbottom = f.topleft, f[a.string()]
-    }
-    function D(f, h) {
-        function t() {
-            var a = n.width;
-            n.width = n.height, n.height = a
-        }
-        function u() {
-            n.width = j.width, n.height = j.height
-        }
-        function v(a, d, g, h) {
-            if (!k.tip)
-                return;
-            var l = i.corner.clone(), n = g.adjusted, o = f.options.position.adjust.method.split(" "), p = o[0], q = o[1] || o[0], r = {left: c, top: c, x: 0, y: 0}, s, t = {}, u;
-            i.corner.fixed !== b && (p === "shift" && l.precedance === "x" && n.left && l.y !== "center" ? l.precedance = l.precedance === "x" ? "y" : "x" : p !== "shift" && n.left && (l.x = l.x === "center" ? n.left > 0 ? "left" : "right" : l.x === "left" ? "right" : "left"), q === "shift" && l.precedance === "y" && n.top && l.x !== "center" ? l.precedance = l.precedance === "y" ? "x" : "y" : q !== "shift" && n.top && (l.y = l.y === "center" ? n.top > 0 ? "top" : "bottom" : l.y === "top" ? "bottom" : "top"), l.string() !== m.corner.string() && (m.top !== n.top || m.left !== n.left) && i.update(l, c)), s = i.position(l, n), s.right !== e && (s.left = -s.right), s.bottom !== e && (s.top = -s.bottom), s.user = Math.max(0, j.offset);
-            if (r.left = p === "shift" && !!n.left)
-                l.x === "center" ? t["margin-left"] = r.x = s["margin-left"] - n.left : (u = s.right !== e ? [n.left, -s.left] : [-n.left, s.left], (r.x = Math.max(u[0], u[1])) > u[0] && (g.left -= n.left, r.left = c), t[s.right !== e ? "right" : "left"] = r.x);
-            if (r.top = q === "shift" && !!n.top)
-                l.y === "center" ? t["margin-top"] = r.y = s["margin-top"] - n.top : (u = s.bottom !== e ? [n.top, -s.top] : [-n.top, s.top], (r.y = Math.max(u[0], u[1])) > u[0] && (g.top -= n.top, r.top = c), t[s.bottom !== e ? "bottom" : "top"] = r.y);
-            k.tip.css(t).toggle(!(r.x && r.y || l.x === "center" && r.y || l.y === "center" && r.x)), g.left -= s.left.charAt ? s.user : p !== "shift" || r.top || !r.left && !r.top ? s.left : 0, g.top -= s.top.charAt ? s.user : q !== "shift" || r.left || !r.left && !r.top ? s.top : 0, m.left = n.left, m.top = n.top, m.corner = l.clone()
-        }
-        function w(a, b, c) {
-            b = b ? b : a[a.precedance];
-            var d = l.hasClass(q), e = k.titlebar && a.y === "top", f = e ? k.titlebar : k.content, g = "border-" + b + "-width", h;
-            return l.addClass(q), h = parseInt(f.css(g), 10), h = (c ? h || parseInt(l.css(g), 10) : h) || 0, l.toggleClass(q, d), h
-        }
-        function x(b) {
-            var c = k.titlebar && b.y === "top", d = c ? k.titlebar : k.content, e = a.browser.mozilla, f = e ? "-moz-" : a.browser.webkit ? "-webkit-" : "", g = b.y + (e ? "" : "-") + b.x, h = f + (e ? "border-radius-" + g : "border-" + g + "-radius");
-            return parseInt(d.css(h), 10) || parseInt(l.css(h), 10) || 0
-        }
-        function y(a) {
-            var b = a.precedance === "y", c = n[b ? "width" : "height"], d = n[b ? "height" : "width"], e = a.string().indexOf("center") > -1, f = c * (e ? .5 : 1), g = Math.pow, h = Math.round, i, j, k, l = Math.sqrt(g(f, 2) + g(d, 2)), m = [p / f * l, p / d * l];
-            return m[2] = Math.sqrt(g(m[0], 2) - g(p, 2)), m[3] = Math.sqrt(g(m[1], 2) - g(p, 2)), i = l + m[2] + m[3] + (e ? 0 : m[0]), j = i / l, k = [h(j * d), h(j * c)], {height: k[b ? 0 : 1], width: k[b ? 1 : 0]}
-        }
-        var i = this, j = f.options.style.tip, k = f.elements, l = k.tooltip, m = {top: 0, left: 0}, n = {width: j.width, height: j.height}, o = {}, p = j.border || 0, r = ".qtip-tip", s = !!(a("<canvas />")[0] || {}).getContext;
-        i.corner = d, i.mimic = d, i.border = p, i.offset = j.offset, i.size = n, f.checks.tip = {"^position.my|style.tip.(corner|mimic|border)$": function () {
-                i.init() || i.destroy(), f.reposition()
-            }, "^style.tip.(height|width)$": function () {
-                n = {width: j.width, height: j.height}, i.create(), i.update(), f.reposition()
-            }, "^content.title.text|style.(classes|widget)$": function () {
-                k.tip && k.tip.length && i.update()
-            }}, a.extend(i, {init: function () {
-                var b = i.detectCorner() && (s || a.browser.msie);
-                return b && (i.create(), i.update(), l.unbind(r).bind("tooltipmove" + r, v)), b
-            }, detectCorner: function () {
-                var a = j.corner, d = f.options.position, e = d.at, h = d.my.string ? d.my.string() : d.my;
-                return a === c || h === c && e === c ? c : (a === b ? i.corner = new g.Corner(h) : a.string || (i.corner = new g.Corner(a), i.corner.fixed = b), m.corner = new g.Corner(i.corner.string()), i.corner.string() !== "centercenter")
-            }, detectColours: function (b) {
-                var c, d, e, g = k.tip.css("cssText", ""), h = b || i.corner, m = h[h.precedance], p = "border-" + m + "-color", r = "border" + m.charAt(0) + m.substr(1) + "Color", s = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i, t = "background-color", u = "transparent", v = " !important", w = a(document.body).css("color"), x = f.elements.content.css("color"), y = k.titlebar && (h.y === "top" || h.y === "center" && g.position().top + n.height / 2 + j.offset < k.titlebar.outerHeight(1)), z = y ? k.titlebar : k.content;
-                l.addClass(q), o.fill = d = g.css(t), o.border = e = g[0].style[r] || g.css(p) || l.css(p);
-                if (!d || s.test(d))
-                    o.fill = z.css(t) || u, s.test(o.fill) && (o.fill = l.css(t) || d);
-                if (!e || s.test(e) || e === w)
-                    o.border = z.css(p) || u, s.test(o.border) && (o.border = e);
-                a("*", g).add(g).css("cssText", t + ":" + u + v + ";border:0" + v + ";"), l.removeClass(q)
-            }, create: function () {
-                var b = n.width, c = n.height, d;
-                k.tip && k.tip.remove(), k.tip = a("<div />", {"class": "ui-tooltip-tip"}).css({width: b, height: c}).prependTo(l), s ? a("<canvas />").appendTo(k.tip)[0].getContext("2d").save() : (d = '<vml:shape coordorigin="0,0" style="display:inline-block; position:absolute; behavior:url(#default#VML);"></vml:shape>', k.tip.html(d + d), a("*", k.tip).bind("click mousedown", function (a) {
-                    a.stopPropagation()
-                }))
-            }, update: function (e, f) {
-                var h = k.tip, l = h.children(), q = n.width, r = n.height, v = "px solid ", x = "px dashed transparent", z = j.mimic, A = Math.round, B, D, E, F, G;
-                e || (e = m.corner || i.corner), z === c ? z = e : (z = new g.Corner(z), z.precedance = e.precedance, z.x === "inherit" ? z.x = e.x : z.y === "inherit" ? z.y = e.y : z.x === z.y && (z[e.precedance] = e[e.precedance])), B = z.precedance, e.precedance === "x" ? t() : u(), k.tip.css({width: q = n.width, height: r = n.height}), i.detectColours(e), o.border !== "transparent" && o.border !== "#123456" ? (p = w(e, d, b), j.border === 0 && p > 0 && (o.fill = o.border), i.border = p = j.border !== b ? j.border : p) : i.border = p = 0, E = C(z, q, r), i.size = G = y(e), h.css(G), e.precedance === "y" ? F = [A(z.x === "left" ? p : z.x === "right" ? G.width - q - p : (G.width - q) / 2), A(z.y === "top" ? G.height - r : 0)] : F = [A(z.x === "left" ? G.width - q : 0), A(z.y === "top" ? p : z.y === "bottom" ? G.height - r - p : (G.height - r) / 2)], s ? (l.attr(G), D = l[0].getContext("2d"), D.restore(), D.save(), D.clearRect(0, 0, 3e3, 3e3), D.translate(F[0], F[1]), D.beginPath(),
  D.moveTo(E[0][0], E[0][1]), D.lineTo(E[1][0], E[1][1]), D.lineTo(E[2][0], E[2][1]), D.closePath(), D.fillStyle = o.fill, D.strokeStyle = o.border, D.lineWidth = p * 2, D.lineJoin = "miter", D.miterLimit = 100, p && D.stroke(), D.fill()) : (E = "m" + E[0][0] + "," + E[0][1] + " l" + E[1][0] + "," + E[1][1] + " " + E[2][0] + "," + E[2][1] + " xe", F[2] = p && /^(r|b)/i.test(e.string()) ? parseFloat(a.browser.version, 10) === 8 ? 2 : 1 : 0, l.css({antialias: "" + (z.string().indexOf("center") > -1), left: F[0] - F[2] * Number(B === "x"), top: F[1] - F[2] * Number(B === "y"), width: q + p, height: r + p}).each(function (b) {
-                    var c = a(this);
-                    c[c.prop ? "prop" : "attr"]({coordsize: q + p + " " + (r + p), path: E, fillcolor: o.fill, filled: !!b, stroked: !b}).css({display: p || b ? "block" : "none"}), !b && c.html() === "" && c.html('<vml:stroke weight="' + p * 2 + 'px" color="' + o.border + '" miterlimit="1000" joinstyle="miter" ' + ' style="behavior:url(#default#VML); display:inline-block;" />')
-                })), f !== c && i.position(e)
-            }, position: function (d) {
-                var e = k.tip, f = {}, g = Math.max(0, j.offset), h, l, m;
-                return j.corner === c || !e ? c : (d = d || i.corner, h = d.precedance, l = y(d), m = [d.x, d.y], h === "x" && m.reverse(), a.each(m, function (a, c) {
-                    var e, i;
-                    c === "center" ? (e = h === "y" ? "left" : "top", f[e] = "50%", f["margin-" + e] = -Math.round(l[h === "y" ? "width" : "height"] / 2) + g) : (e = w(d, c, b), i = x(d), f[c] = a ? p ? w(d, c) : 0 : g + (i > e ? i : 0))
-                }), f[d[h]] -= l[h === "x" ? "width" : "height"], e.css({top: "", bottom: "", left: "", right: "", margin: ""}).css(f), f)
-            }, destroy: function () {
-                k.tip && k.tip.remove(), k.tip = !1, l.unbind(r)
-            }}), i.init()
-    }
-    var b = !0, c = !1, d = null, e, f, g, h, i = {}, j = "ui-tooltip", k = "ui-widget", l = "ui-state-disabled", m = "div.qtip." + j, n = j + "-default", o = j + "-focus", p = j + "-hover", q = j + "-fluid", r = "-31000px", s = "_replacedByqTip", t = "oldtitle", u;
-    f = a.fn.qtip = function (g, h, i) {
-        var j = ("" + g).toLowerCase(), k = d, l = a.makeArray(arguments).slice(1), m = l[l.length - 1], n = this[0] ? a.data(this[0], "qtip") : d;
-        if (!arguments.length && n || j === "api")
-            return n;
-        if ("string" == typeof g)
-            return this.each(function () {
-                var d = a.data(this, "qtip");
-                if (!d)
-                    return b;
-                m && m.timeStamp && (d.cache.event = m);
-                if (j !== "option" && j !== "options" || !h)
-                    d[j] && d[j].apply(d[j], l);
-                else {
-                    if (!a.isPlainObject(h) && i === e)
-                        return k = d.get(h), c;
-                    d.set(h, i)
-                }
-            }), k !== d ? k : this;
-        if ("object" == typeof g || !arguments.length)
-            return n = w(a.extend(b, {}, g)), f.bind.call(this, n, m)
-    }, f.bind = function (d, j) {
-        return this.each(function (k) {
-            function r(b) {
-                function d() {
-                    p.render(typeof b == "object" || l.show.ready), m.show.add(m.hide).unbind(o)
-                }
-                if (p.cache.disabled)
-                    return c;
-                p.cache.event = a.extend({}, b), p.cache.target = b ? a(b.target) : [e], l.show.delay > 0 ? (clearTimeout(p.timers.show), p.timers.show = setTimeout(d, l.show.delay), n.show !== n.hide && m.hide.bind(n.hide, function () {
-                    clearTimeout(p.timers.show)
-                })) : d()
-            }
-            var l, m, n, o, p, q;
-            q = a.isArray(d.id) ? d.id[k] : d.id, q = !q || q === c || q.length < 1 || i[q] ? f.nextid++ : i[q] = q, o = ".qtip-" + q + "-create", p = y.call(this, q, d);
-            if (p === c)
-                return b;
-            l = p.options, a.each(g, function () {
-                this.initialize === "initialize" && this(p)
-            }), m = {show: l.show.target, hide: l.hide.target}, n = {show: a.trim("" + l.show.event).replace(/ /g, o + " ") + o, hide: a.trim("" + l.hide.event).replace(/ /g, o + " ") + o}, /mouse(over|enter)/i.test(n.show) && !/mouse(out|leave)/i.test(n.hide) && (n.hide += " mouseleave" + o), m.show.bind("mousemove" + o, function (a) {
-                h = {pageX: a.pageX, pageY: a.pageY, type: "mousemove"}, p.cache.onTarget = b
-            }), m.show.bind(n.show, r), (l.show.ready || l.prerender) && r(j)
-        })
-    }, g = f.plugins = {Corner: function (a) {
-            a = ("" + a).replace(/([A-Z])/, " $1").replace(/middle/gi, "center").toLowerCase(), this.x = (a.match(/left|right/i) || a.match(/center/) || ["inherit"])[0].toLowerCase(), this.y = (a.match(/top|bottom|center/i) || ["inherit"])[0].toLowerCase();
-            var b = a.charAt(0);
-            this.precedance = b === "t" || b === "b" ? "y" : "x", this.string = function () {
-                return this.precedance === "y" ? this.y + this.x : this.x + this.y
-            }, this.abbrev = function () {
-                var a = this.x.substr(0, 1), b = this.y.substr(0, 1);
-                return a === b ? a : a === "c" || a !== "c" && b !== "c" ? b + a : a + b
-            }, this.clone = function () {
-                return{x: this.x, y: this.y, precedance: this.precedance, string: this.string, abbrev: this.abbrev, clone: this.clone}
-            }
-        }, offset: function (b, c) {
-            function j(a, b) {
-                d.left += b * a.scrollLeft(), d.top += b * a.scrollTop()
-            }
-            var d = b.offset(), e = b.closest("body")[0], f = c, g, h, i;
-            if (f) {
-                do
-                    f.css("position") !== "static" && (h = f.position(), d.left -= h.left + (parseInt(f.css("borderLeftWidth"), 10) || 0) + (parseInt(f.css("marginLeft"), 10) || 0), d.top -= h.top + (parseInt(f.css("borderTopWidth"), 10) || 0) + (parseInt(f.css("marginTop"), 10) || 0), !g && (i = f.css("overflow")) !== "hidden" && i !== "visible" && (g = f));
-                while ((f = a(f[0].offsetParent)).length);
-                g && g[0] !== e && j(g, 1)
-            }
-            return d
-        }, iOS: parseFloat(("" + (/CPU.*OS ([0-9_]{1,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ""])[1]).replace("undefined", "3_2").replace("_", ".")) || c, fn: {attr: function (b, c) {
-                if (this.length) {
-                    var d = this[0], e = "title", f = a.data(d, "qtip");
-                    if (b === e && f && "object" == typeof f && f.options.suppress)
-                        return arguments.length < 2 ? a.attr(d, t) : (f && f.options.content.attr === e && f.cache.attr && f.set("content.text", c), this.attr(t, c))
-                }
-                return a.fn["attr" + s].apply(this, arguments)
-            }, clone: function (b) {
-                var c = a([]), d = "title", e = a.fn["clone" + s].apply(this, arguments);
-                return b || e.filter("[" + t + "]").attr("title", function () {
-                    return a.attr(this, t)
-                }).removeAttr(t), e
-            }}}, a.each(g.fn, function (c, d) {
-        if (!d || a.fn[c + s])
-            return b;
-        var e = a.fn[c + s] = a.fn[c];
-        a.fn[c] = function () {
-            return d.apply(this, arguments) || e.apply(this, arguments)
-        }
-    }), a.ui || (a["cleanData" + s] = a.cleanData, a.cleanData = function (b) {
-        for (var c = 0, d; (d = b[c]) !== e; c++)
-            try {
-                a(d).triggerHandler("removeqtip")
-            } catch (f) {
-            }
-        a["cleanData" + s](b)
-    }), f.version = "2.0.0pre", f.nextid = 0, f.inactiveEvents = "click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "), f.zindex = 15e3, f.defaults = {prerender: c, id: c, overwrite: b, suppress: b, content: {text: b, attr: "title", title: {text: c, button: c}}, position: {my: "top left", at: "bottom right", target: c, container: c, viewport: c, adjust: {x: 0, y: 0, mouse: b, resize: b, method: "flip flip"}, effect: function (b, d, e) {
-                a(this).animate(d, {duration: 200, queue: c})
-            }}, show: {target: c, event: "mouseenter", effect: b, delay: 90, solo: c, ready: c, autofocus: c}, hide: {target: c, event: "mouseleave", effect: b, delay: 0, fixed: c, inactive: c, leave: "window", distance: c}, style: {classes: "", widget: c, width: c, height: c, def: b}, events: {render: d, move: d, show: d, hide: d, toggle: d, visible: d, hidden: d, focus: d, blur: d}}, g.ajax = function (a) {
-        var b = a.plugins.ajax;
-        return"object" == typeof b ? b : a.plugins.ajax = new z(a)
-    }, g.ajax.initialize = "render", g.ajax.sanitize = function (a) {
-        var b = a.content, c;
-        b && "ajax"in b && (c = b.ajax, typeof c != "object" && (c = a.content.ajax = {url: c}), "boolean" != typeof c.once && c.once && (c.once = !!c.once))
-    }, a.extend(b, f.defaults, {content: {ajax: {loading: b, once: b}}}), g.bgiframe = function (b) {
-        var d = a.browser, e = b.plugins.bgiframe;
-        return a("select, object").length < 1 || !d.msie || ("" + d.version).charAt(0) !== "6" ? c : "object" == typeof e ? e : b.plugins.bgiframe = new A(b)
-    }, g.bgiframe.initialize = "render", g.imagemap = function (b, c, d) {
-        function n(a, b, c) {
-            var d = 0, e = 1, f = 1, g = 0, h = 0, i = a.width, j = a.height;
-            while (i > 0 && j > 0 && e > 0 && f > 0) {
-                i = Math.floor(i / 2), j = Math.floor(j / 2), c.x === "left" ? e = i : c.x === "right" ? e = a.width - i : e += Math.floor(i / 2), c.y === "top" ? f = j : c.y === "bottom" ? f = a.height - j : f += Math.floor(j / 2), d = b.length;
-                while (d--) {
-                    if (b.length < 2)
-                        break;
-                    g = b[d][0] - a.offset.left, h = b[d][1] - a.offset.top, (c.x === "left" && g >= e || c.x === "right" && g <= e || c.x === "center" && (g < e || g > a.width - e) || c.y === "top" && h >= f || c.y === "bottom" && h <= f || c.y === "center" && (h < f || h > a.height - f)) && b.splice(d, 1)
-                }
-            }
-            return{left: b[0][0], top: b[0][1]}
-        }
-        b.jquery || (b = a(b));
-        var e = (b[0].shape || b.attr("shape")).toLowerCase(), f = (b[0].coords || b.attr("coords")).split(","), g = [], h = a('img[usemap="#' + b.parent("map").attr("name") + '"]'), i = h.offset(), j = {width: 0, height: 0, offset: {top: 1e10, right: 0, bottom: 0, left: 1e10}}, k = 0, l = 0, m;
-        i.left += Math.ceil((h.outerWidth() - h.width()) / 2), i.top += Math.ceil((h.outerHeight() - h.height()) / 2);
-        if (e === "poly") {
-            k = f.length;
-            while (k--)
-                l = [parseInt(f[--k], 10), parseInt(f[k + 1], 10)], l[0] > j.offset.right && (j.offset.right = l[0]), l[0] < j.offset.left && (j.offset.left = l[0]), l[1] > j.offset.bottom && (j.offset.bottom = l[1]), l[1] < j.offset.top && (j.offset.top = l[1]), g.push(l)
-        } else
-            g = a.map(f, function (a) {
-                return parseInt(a, 10)
-            });
-        switch (e) {
-            case"rect":
-                j = {width: Math.abs(g[2] - g[0]), height: Math.abs(g[3] - g[1]), offset: {left: Math.min(g[0], g[2]), top: Math.min(g[1], g[3])}};
-                break;
-            case"circle":
-                j = {width: g[2] + 2, height: g[2] + 2, offset: {left: g[0], top: g[1]}};
-                break;
-            case"poly":
-                a.extend(j, {width: Math.abs(j.offset.right - j.offset.left), height: Math.abs(j.offset.bottom - j.offset.top)}), c.string() === "centercenter" ? j.offset = {left: j.offset.left + j.width / 2, top: j.offset.top + j.height / 2} : (j.offset = n(j, g.slice(), c), d && (d[0] === "flip" || d[1] === "flip") && (j.flipoffset = n(j, g.slice(), {x: c.x === "left" ? "right" : c.x === "right" ? "left" : "center", y: c.y === "top" ? "bottom" : c.y === "bottom" ? "top" : "center"}), j.flipoffset.left -= j.offset.left, j.flipoffset.top -= j.offset.top)), j.width = j.height = 0
-        }
-        return j.offset.left += i.left, j.offset.top += i.top, j
-    }, g.modal = function (a) {
-        var b = a.plugins.modal;
-        return"object" == typeof b ? b : a.plugins.modal = new B(a)
-    }, g.modal.initialize = "render", g.modal.sanitize = function (a) {
-        a.show && (typeof a.show.modal != "object" ? a.show.modal = {on: !!a.show.modal} : typeof a.show.modal.on == "undefined" && (a.show.modal.on = b))
-    }, g.modal.zindex = f.zindex + 1e3, a.extend(b, f.defaults, {show: {modal: {on: c, effect: b, blur: b, escape: b}}}), g.svg = function (b, c) {
-        var d = a(document), e = b[0], f = {width: 0, height: 0, offset: {top: 1e10, left: 1e10}}, g, h, i, j, k;
-        if (e.getBBox && e.parentNode) {
-            g = e.getBBox(), h = e.getScreenCTM(), i = e.farthestViewportElement || e;
-            if (!i.createSVGPoint)
-                return f;
-            j = i.createSVGPoint(), j.x = g.x, j.y = g.y, k = j.matrixTransform(h), f.offset.left = k.x, f.offset.top = k.y, j.x += g.width, j.y += g.height, k = j.matrixTransform(h), f.width = k.x - f.offset.left, f.height = k.y - f.offset.top, f.offset.left += d.scrollLeft(), f.offset.top += d.scrollTop()
-        }
-        return f
-    }, g.tip = function (a) {
-        var b = a.plugins.tip;
-        return"object" == typeof b ? b : a.plugins.tip = new D(a)
-    }, g.tip.initialize = "render", g.tip.sanitize = function (a) {
-        var c = a.style, d;
-        c && "tip"in c && (d = a.style.tip, typeof d != "object" && (a.style.tip = {corner: d}), /string|boolean/i.test(typeof d.corner) || (d.corner = b), typeof d.width != "number" && delete d.width, typeof d.height != "number" && delete d.height, typeof d.border != "number" && d.border !== b && delete d.border, typeof d.offset != "number" && delete d.offset)
-    }, a.extend(b, f.defaults, {style: {tip: {corner: b, mimic: c, width: 6, height: 6, border: b, offset: 0}}})
-});
\ No newline at end of file
+/* qTip2 v2.2.1 | Plugins: tips modal viewport svg imagemap ie6 | Styles: core basic css3 | qtip2.com | Licensed MIT | Sat Sep 06 2014 23:12:07 */
+
+!function(a,b,c){!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)}(function(d){"use strict";function e(a,b,c,e){this.id=c,this.target=a,this.tooltip=F,this.elements={target:a},this._id=S+"-"+c,this.timers={img:{}},this.options=b,this.plugins={},this.cache={event:{},target:d(),disabled:E,attr:e,onTooltip:E,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=E}function f(a){return a===F||"object"!==d.type(a)}function g(a){return!(d.isFunction(a)||a&&a.attr||a.length||"object"===d.type(a)&&(a.jquery||a.then))}function h(a){var b,c,e,h;return f(a)?E:(f(a.metadata)&&(a.metadata={type:a.metadata}),"content"in a&&(b=a.content,f(b)||b.jquery||b.done?b=a.content={text:c=g(b)?E:b}:c=b.text,"ajax"in b&&(e=b.ajax,h=e&&e.once!==E,delete b.ajax,b.text=function(a,b){var f=c||d(this).attr(b.options.content.attr)||"Loading...",g=d.ajax(d.extend({},e,{context
 :b})).then(e.success,F,e.error).then(function(a){return a&&h&&b.set("content.text",a),a},function(a,c,d){b.destroyed||0===a.status||b.set("content.text",c+": "+d)});return h?f:(b.set("content.text",f),g)}),"title"in b&&(d.isPlainObject(b.title)&&(b.button=b.title.button,b.title=b.title.text),g(b.title||E)&&(b.title=E))),"position"in a&&f(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&f(a.show)&&(a.show=a.show.jquery?{target:a.show}:a.show===D?{ready:D}:{event:a.show}),"hide"in a&&f(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&f(a.style)&&(a.style={classes:a.style}),d.each(R,function(){this.sanitize&&this.sanitize(a)}),a)}function i(a,b){for(var c,d=0,e=a,f=b.split(".");e=e[f[d++]];)d<f.length&&(c=e);return[c||a,f.pop()]}function j(a,b){var c,d,e;for(c in this.checks)for(d in this.checks[c])(e=new RegExp(d,"i").exec(a))&&(b.push(e),("builtin"===c||this.plugins[c])&&this.checks[c][d].apply(this.plugins[c]||this,b))}function k(a){retu
 rn V.concat("").join(a?"-"+a+" ":" ")}function l(a,b){return b>0?setTimeout(d.proxy(a,this),b):void a.call(this)}function m(a){this.tooltip.hasClass(ab)||(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=l.call(this,function(){this.toggle(D,a)},this.options.show.delay))}function n(a){if(!this.tooltip.hasClass(ab)&&!this.destroyed){var b=d(a.relatedTarget),c=b.closest(W)[0]===this.tooltip[0],e=b[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==b[0]&&"mouse"===this.options.position.target&&c||this.options.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(c||e))try{a.preventDefault(),a.stopImmediatePropagation()}catch(f){}else this.timers.hide=l.call(this,function(){this.toggle(E,a)},this.options.hide.delay,this)}}function o(a){!this.tooltip.hasClass(ab)&&this.options.hide.inactive&&(clearTimeout(this.timers.inactive),this.timers.inactive=l.call(this,function(){this.hide(a)},this.options.hide.inactiv
 e))}function p(a){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(a)}function q(a,c,e){d(b.body).delegate(a,(c.split?c:c.join("."+S+" "))+"."+S,function(){var a=y.api[d.attr(this,U)];a&&!a.disabled&&e.apply(a,arguments)})}function r(a,c,f){var g,i,j,k,l,m=d(b.body),n=a[0]===b?m:a,o=a.metadata?a.metadata(f.metadata):F,p="html5"===f.metadata.type&&o?o[f.metadata.name]:F,q=a.data(f.metadata.name||"qtipopts");try{q="string"==typeof q?d.parseJSON(q):q}catch(r){}if(k=d.extend(D,{},y.defaults,f,"object"==typeof q?h(q):F,h(p||o)),i=k.position,k.id=c,"boolean"==typeof k.content.text){if(j=a.attr(k.content.attr),k.content.attr===E||!j)return E;k.content.text=j}if(i.container.length||(i.container=m),i.target===E&&(i.target=n),k.show.target===E&&(k.show.target=n),k.show.solo===D&&(k.show.solo=i.container.closest("body")),k.hide.target===E&&(k.hide.target=n),k.position.viewport===D&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new A(i.at,D),i.my=new A(i.my),
 a.data(S))if(k.overwrite)a.qtip("destroy",!0);else if(k.overwrite===E)return E;return a.attr(T,c),k.suppress&&(l=a.attr("title"))&&a.removeAttr("title").attr(cb,l).attr("title",""),g=new e(a,k,c,!!j),a.data(S,g),g}function s(a){return a.charAt(0).toUpperCase()+a.slice(1)}function t(a,b){var d,e,f=b.charAt(0).toUpperCase()+b.slice(1),g=(b+" "+rb.join(f+" ")+f).split(" "),h=0;if(qb[b])return a.css(qb[b]);for(;d=g[h++];)if((e=a.css(d))!==c)return qb[b]=d,e}function u(a,b){return Math.ceil(parseFloat(t(a,b)))}function v(a,b){this._ns="tip",this.options=b,this.offset=b.offset,this.size=[b.width,b.height],this.init(this.qtip=a)}function w(a,b){this.options=b,this._ns="-modal",this.init(this.qtip=a)}function x(a){this._ns="ie6",this.init(this.qtip=a)}var y,z,A,B,C,D=!0,E=!1,F=null,G="x",H="y",I="width",J="height",K="top",L="left",M="bottom",N="right",O="center",P="flipinvert",Q="shift",R={},S="qtip",T="data-hasqtip",U="data-qtip-id",V=["ui-widget","ui-tooltip"],W="."+S,X="click dblclick mo
 usedown mouseup mousemove mouseleave mouseenter".split(" "),Y=S+"-fixed",Z=S+"-default",$=S+"-focus",_=S+"-hover",ab=S+"-disabled",bb="_replacedByqTip",cb="oldtitle",db={ie:function(){for(var a=4,c=b.createElement("div");(c.innerHTML="<!--[if gt IE "+a+"]><i></i><![endif]-->")&&c.getElementsByTagName("i")[0];a+=1);return a>4?a:0/0}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||E};z=e.prototype,z._when=function(a){return d.when.apply(d,a)},z.render=function(a){if(this.rendered||this.destroyed)return this;var b,c=this,e=this.options,f=this.cache,g=this.elements,h=e.content.text,i=e.content.title,j=e.content.button,k=e.position,l=("."+this._id+" ",[]);return d.attr(this.target[0],"aria-describedby",this._id),f.posClass=this._createPosClass((this.position={my:k.my,at:k.at}).my),this.tooltip=g.tooltip=b=d("<div/>",{id:this._id,"class":[S,Z,e.style.classes,
 f.posClass].join(" "),width:e.style.width||"",height:e.style.height||"",tracking:"mouse"===k.target&&k.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":E,"aria-describedby":this._id+"-content","aria-hidden":D}).toggleClass(ab,this.disabled).attr(U,this.id).data(S,this).appendTo(k.container).append(g.content=d("<div />",{"class":S+"-content",id:this._id+"-content","aria-atomic":D})),this.rendered=-1,this.positioning=D,i&&(this._createTitle(),d.isFunction(i)||l.push(this._updateTitle(i,E))),j&&this._createButton(),d.isFunction(h)||l.push(this._updateContent(h,E)),this.rendered=D,this._setWidget(),d.each(R,function(a){var b;"render"===this.initialize&&(b=this(c))&&(c.plugins[a]=b)}),this._unassignEvents(),this._assignEvents(),this._when(l).then(function(){c._trigger("render"),c.positioning=E,c.hiddenDuringWait||!e.show.ready&&!a||c.toggle(D,f.event,E),c.hiddenDuringWait=E}),y.api[this.id]=this,this},z.destroy=function(a){function b(){if(!this.destroyed){this.destroyed=D;var
  a,b=this.target,c=b.attr(cb);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),d.each(this.plugins,function(){this.destroy&&this.destroy()});for(a in this.timers)clearTimeout(this.timers[a]);b.removeData(S).removeAttr(U).removeAttr(T).removeAttr("aria-describedby"),this.options.suppress&&c&&b.attr("title",c).removeAttr(cb),this._unassignEvents(),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=F,delete y.api[this.id]}}return this.destroyed?this.target:(a===D&&"hide"!==this.triggering||!this.rendered?b.call(this):(this.tooltip.one("tooltiphidden",d.proxy(b,this)),!this.triggering&&this.hide()),this.target)},B=z.checks={builtin:{"^id$":function(a,b,c,e){var f=c===D?y.nextid:c,g=S+"-"+f;f!==E&&f.length>0&&!d("#"+g).length?(this._id=g,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):a[b]=e},"^prerender":function(a,b,c){c&&!this.rendered&&this.render(th
 is.options.show.ready)},"^content.text$":function(a,b,c){this._updateContent(c)},"^content.attr$":function(a,b,c,d){this.options.content.text===this.target.attr(d)&&this._updateContent(this.target.attr(c))},"^content.title$":function(a,b,c){return c?(c&&!this.elements.title&&this._createTitle(),void this._updateTitle(c)):this._removeTitle()},"^content.button$":function(a,b,c){this._updateButton(c)},"^content.title.(text|button)$":function(a,b,c){this.set("content."+b,c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(this.position[b]=a[b]=new A(c,"at"===b))},"^position.container$":function(a,b,c){this.rendered&&this.tooltip.appendTo(c)},"^show.ready$":function(a,b,c){c&&(!this.rendered&&this.render(D)||this.toggle(D))},"^style.classes$":function(a,b,c,d){this.rendered&&this.tooltip.removeClass(d).addClass(c)},"^style.(width|height)":function(a,b,c){this.rendered&&this.tooltip.css(b,c)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def"
 :function(a,b,c){this.rendered&&this.tooltip.toggleClass(Z,!!c)},"^events.(render|show|move|hide|focus|blur)$":function(a,b,c){this.rendered&&this.tooltip[(d.isFunction(c)?"":"un")+"bind"]("tooltip"+b,c)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var a=this.options.position;this.tooltip.attr("tracking","mouse"===a.target&&a.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},z.get=function(a){if(this.destroyed)return this;var b=i(this.options,a.toLowerCase()),c=b[0][b[1]];return c.precedance?c.string():c};var eb=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,fb=/^prerender|show\.ready/i;z.set=function(a,b){if(this.destroyed)return this;{var c,e=this.rendered,f=E,g=this.options;this.checks}return"string"==typeof a?(c=a,a={},a[c]=b):a=d.extend({},a),d.each(a,function(b,c){if(e&&fb.test(b))return void delete a[b];var h,j=i(g,b.toLowerCase());h=j[0][j[1]],j[0][j[1]]=c&&c.n
 odeType?d(c):c,f=eb.test(b)||f,a[b]=[j[0],j[1],c,h]}),h(g),this.positioning=D,d.each(a,d.proxy(j,this)),this.positioning=E,this.rendered&&this.tooltip[0].offsetWidth>0&&f&&this.reposition("mouse"===g.position.target?F:this.cache.event),this},z._update=function(a,b){var c=this,e=this.cache;return this.rendered&&a?(d.isFunction(a)&&(a=a.call(this.elements.target,e.event,this)||""),d.isFunction(a.then)?(e.waiting=D,a.then(function(a){return e.waiting=E,c._update(a,b)},F,function(a){return c._update(a,b)})):a===E||!a&&""!==a?E:(a.jquery&&a.length>0?b.empty().append(a.css({display:"block",visibility:"visible"})):b.html(a),this._waitForContent(b).then(function(a){c.rendered&&c.tooltip[0].offsetWidth>0&&c.reposition(e.event,!a.length)}))):E},z._waitForContent=function(a){var b=this.cache;return b.waiting=D,(d.fn.imagesLoaded?a.imagesLoaded():d.Deferred().resolve([])).done(function(){b.waiting=E}).promise()},z._updateContent=function(a,b){this._update(a,this.elements.content,b)},z._updateTi
 tle=function(a,b){this._update(a,this.elements.title,b)===E&&this._removeTitle(E)},z._createTitle=function(){var a=this.elements,b=this._id+"-title";a.titlebar&&this._removeTitle(),a.titlebar=d("<div />",{"class":S+"-titlebar "+(this.options.style.widget?k("header"):"")}).append(a.title=d("<div />",{id:b,"class":S+"-title","aria-atomic":D})).insertBefore(a.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(a){d(this).toggleClass("ui-state-active ui-state-focus","down"===a.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(a){d(this).toggleClass("ui-state-hover","mouseover"===a.type)}),this.options.content.button&&this._createButton()},z._removeTitle=function(a){var b=this.elements;b.title&&(b.titlebar.remove(),b.titlebar=b.title=b.button=F,a!==E&&this.reposition())},z._createPosClass=function(a){return S+"-pos-"+(a||this.options.position.my).abbrev()},z.reposition=function(c,e){if(!this.rendered||this.positioning||this.destroyed)
 return this;this.positioning=D;var f,g,h,i,j=this.cache,k=this.tooltip,l=this.options.position,m=l.target,n=l.my,o=l.at,p=l.viewport,q=l.container,r=l.adjust,s=r.method.split(" "),t=k.outerWidth(E),u=k.outerHeight(E),v=0,w=0,x=k.css("position"),y={left:0,top:0},z=k[0].offsetWidth>0,A=c&&"scroll"===c.type,B=d(a),C=q[0].ownerDocument,F=this.mouse;if(d.isArray(m)&&2===m.length)o={x:L,y:K},y={left:m[0],top:m[1]};else if("mouse"===m)o={x:L,y:K},(!r.mouse||this.options.hide.distance)&&j.origin&&j.origin.pageX?c=j.origin:!c||c&&("resize"===c.type||"scroll"===c.type)?c=j.event:F&&F.pageX&&(c=F),"static"!==x&&(y=q.offset()),C.body.offsetWidth!==(a.innerWidth||C.documentElement.clientWidth)&&(g=d(b.body).offset()),y={left:c.pageX-y.left+(g&&g.left||0),top:c.pageY-y.top+(g&&g.top||0)},r.mouse&&A&&F&&(y.left-=(F.scrollX||0)-B.scrollLeft(),y.top-=(F.scrollY||0)-B.scrollTop());else{if("event"===m?c&&c.target&&"scroll"!==c.type&&"resize"!==c.type?j.target=d(c.target):c.target||(j.target=this.eleme
 nts.target):"event"!==m&&(j.target=d(m.jquery?m:this.elements.target)),m=j.target,m=d(m).eq(0),0===m.length)return this;m[0]===b||m[0]===a?(v=db.iOS?a.innerWidth:m.width(),w=db.iOS?a.innerHeight:m.height(),m[0]===a&&(y={top:(p||m).scrollTop(),left:(p||m).scrollLeft()})):R.imagemap&&m.is("area")?f=R.imagemap(this,m,o,R.viewport?s:E):R.svg&&m&&m[0].ownerSVGElement?f=R.svg(this,m,o,R.viewport?s:E):(v=m.outerWidth(E),w=m.outerHeight(E),y=m.offset()),f&&(v=f.width,w=f.height,g=f.offset,y=f.position),y=this.reposition.offset(m,y,q),(db.iOS>3.1&&db.iOS<4.1||db.iOS>=4.3&&db.iOS<4.33||!db.iOS&&"fixed"===x)&&(y.left-=B.scrollLeft(),y.top-=B.scrollTop()),(!f||f&&f.adjustable!==E)&&(y.left+=o.x===N?v:o.x===O?v/2:0,y.top+=o.y===M?w:o.y===O?w/2:0)}return y.left+=r.x+(n.x===N?-t:n.x===O?-t/2:0),y.top+=r.y+(n.y===M?-u:n.y===O?-u/2:0),R.viewport?(h=y.adjusted=R.viewport(this,y,l,v,w,t,u),g&&h.left&&(y.left+=g.left),g&&h.top&&(y.top+=g.top),h.my&&(this.position.my=h.my)):y.adjusted={left:0,top:0},j.p
 osClass!==(i=this._createPosClass(this.position.my))&&k.removeClass(j.posClass).addClass(j.posClass=i),this._trigger("move",[y,p.elem||p],c)?(delete y.adjusted,e===E||!z||isNaN(y.left)||isNaN(y.top)||"mouse"===m||!d.isFunction(l.effect)?k.css(y):d.isFunction(l.effect)&&(l.effect.call(k,this,d.extend({},y)),k.queue(function(a){d(this).css({opacity:"",height:""}),db.ie&&this.style.removeAttribute("filter"),a()})),this.positioning=E,this):this},z.reposition.offset=function(a,c,e){function f(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}if(!e[0])return c;var g,h,i,j,k=d(a[0].ownerDocument),l=!!db.ie&&"CSS1Compat"!==b.compatMode,m=e[0];do"static"!==(h=d.css(m,"position"))&&("fixed"===h?(i=m.getBoundingClientRect(),f(k,-1)):(i=d(m).position(),i.left+=parseFloat(d.css(m,"borderLeftWidth"))||0,i.top+=parseFloat(d.css(m,"borderTopWidth"))||0),c.left-=i.left+(parseFloat(d.css(m,"marginLeft"))||0),c.top-=i.top+(parseFloat(d.css(m,"marginTop"))||0),g||"hidden"===(j=d.css(m,"overflow"))||
 "visible"===j||(g=d(m)));while(m=m.offsetParent);return g&&(g[0]!==k[0]||l)&&f(g,1),c};var gb=(A=z.reposition.Corner=function(a,b){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,O).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!b;var c=a.charAt(0);this.precedance="t"===c||"b"===c?H:G}).prototype;gb.invert=function(a,b){this[a]=this[a]===L?N:this[a]===N?L:b||this[a]},gb.string=function(a){var b=this.x,c=this.y,d=b!==c?"center"===b||"center"!==c&&(this.precedance===H||this.forceY)?[c,b]:[b,c]:[b];return a!==!1?d.join(" "):d},gb.abbrev=function(){var a=this.string(!1);return a[0].charAt(0)+(a[1]&&a[1].charAt(0)||"")},gb.clone=function(){return new A(this.string(),this.forceY)},z.toggle=function(a,c){var e=this.cache,f=this.options,g=this.tooltip;if(c){if(/over|enter/.test(c.type)&&e.event&&/out|leave/.test(e.event.type)&&f.show.target.add(c.target).le
 ngth===f.show.target.length&&g.has(c.relatedTarget).length)return this;e.event=d.event.fix(c)}if(this.waiting&&!a&&(this.hiddenDuringWait=D),!this.rendered)return a?this.render(1):this;if(this.destroyed||this.disabled)return this;var h,i,j,k=a?"show":"hide",l=this.options[k],m=(this.options[a?"hide":"show"],this.options.position),n=this.options.content,o=this.tooltip.css("width"),p=this.tooltip.is(":visible"),q=a||1===l.target.length,r=!c||l.target.length<2||e.target[0]===c.target;return(typeof a).search("boolean|number")&&(a=!p),h=!g.is(":animated")&&p===a&&r,i=h?F:!!this._trigger(k,[90]),this.destroyed?this:(i!==E&&a&&this.focus(c),!i||h?this:(d.attr(g[0],"aria-hidden",!a),a?(this.mouse&&(e.origin=d.event.fix(this.mouse)),d.isFunction(n.text)&&this._updateContent(n.text,E),d.isFunction(n.title)&&this._updateTitle(n.title,E),!C&&"mouse"===m.target&&m.adjust.mouse&&(d(b).bind("mousemove."+S,this._storeMouse),C=D),o||g.css("width",g.outerWidth(E)),this.reposition(c,arguments[2]),o||g
 .css("width",""),l.solo&&("string"==typeof l.solo?d(l.solo):d(W,l.solo)).not(g).not(l.target).qtip("hide",d.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete e.origin,C&&!d(W+'[tracking="true"]:visible',l.solo).not(g).length&&(d(b).unbind("mousemove."+S),C=E),this.blur(c)),j=d.proxy(function(){a?(db.ie&&g[0].style.removeAttribute("filter"),g.css("overflow",""),"string"==typeof l.autofocus&&d(this.options.show.autofocus,g).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):g.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(a?"visible":"hidden")},this),l.effect===E||q===E?(g[k](),j()):d.isFunction(l.effect)?(g.stop(1,1),l.effect.call(g,this),g.queue("fx",function(a){j(),a()})):g.fadeTo(90,a?1:0,j),a&&l.target.trigger("qtip-"+this.id+"-inactive"),this))},z.show=function(a){return this.toggle(D,a)},z.hide=function(a){return this.toggle(E,a)},z.focus=function(a){if(!this.rendered||this.destroyed)return this;var b=d(W),c=this.tooltip,
 e=parseInt(c[0].style.zIndex,10),f=y.zindex+b.length;return c.hasClass($)||this._trigger("focus",[f],a)&&(e!==f&&(b.each(function(){this.style.zIndex>e&&(this.style.zIndex=this.style.zIndex-1)}),b.filter("."+$).qtip("blur",a)),c.addClass($)[0].style.zIndex=f),this},z.blur=function(a){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass($),this._trigger("blur",[this.tooltip.css("zIndex")],a),this)},z.disable=function(a){return this.destroyed?this:("toggle"===a?a=!(this.rendered?this.tooltip.hasClass(ab):this.disabled):"boolean"!=typeof a&&(a=D),this.rendered&&this.tooltip.toggleClass(ab,a).attr("aria-disabled",a),this.disabled=!!a,this)},z.enable=function(){return this.disable(E)},z._createButton=function(){var a=this,b=this.elements,c=b.tooltip,e=this.options.content.button,f="string"==typeof e,g=f?e:"Close tooltip";b.button&&b.button.remove(),b.button=e.jquery?e:d("<a />",{"class":"qtip-close "+(this.options.style.widget?"":S+"-icon"),title:g,"aria-label":g}).prepend
 (d("<span />",{"class":"ui-icon ui-icon-close",html:"&times;"})),b.button.appendTo(b.titlebar||c).attr("role","button").click(function(b){return c.hasClass(ab)||a.hide(b),E})},z._updateButton=function(a){if(!this.rendered)return E;var b=this.elements.button;a?this._createButton():b.remove()},z._setWidget=function(){var a=this.options.style.widget,b=this.elements,c=b.tooltip,d=c.hasClass(ab);c.removeClass(ab),ab=a?"ui-state-disabled":"qtip-disabled",c.toggleClass(ab,d),c.toggleClass("ui-helper-reset "+k(),a).toggleClass(Z,this.options.style.def&&!a),b.content&&b.content.toggleClass(k("content"),a),b.titlebar&&b.titlebar.toggleClass(k("header"),a),b.button&&b.button.toggleClass(S+"-icon",!a)},z._storeMouse=function(a){return(this.mouse=d.event.fix(a)).type="mousemove",this},z._bind=function(a,b,c,e,f){if(a&&c&&b.length){var g="."+this._id+(e?"-"+e:"");return d(a).bind((b.split?b:b.join(g+" "))+g,d.proxy(c,f||this)),this}},z._unbind=function(a,b){return a&&d(a).unbind("."+this._id+(b?"
 -"+b:"")),this},z._trigger=function(a,b,c){var e=d.Event("tooltip"+a);return e.originalEvent=c&&d.extend({},c)||this.cache.event||F,this.triggering=a,this.tooltip.trigger(e,[this].concat(b||[])),this.triggering=E,!e.isDefaultPrevented()},z._bindEvents=function(a,b,c,e,f,g){var h=c.filter(e).add(e.filter(c)),i=[];h.length&&(d.each(b,function(b,c){var e=d.inArray(c,a);e>-1&&i.push(a.splice(e,1)[0])}),i.length&&(this._bind(h,i,function(a){var b=this.rendered?this.tooltip[0].offsetWidth>0:!1;(b?g:f).call(this,a)}),c=c.not(h),e=e.not(h))),this._bind(c,a,f),this._bind(e,b,g)},z._assignInitialEvents=function(a){function b(a){return this.disabled||this.destroyed?E:(this.cache.event=a&&d.event.fix(a),this.cache.target=a&&d(a.target),clearTimeout(this.timers.show),void(this.timers.show=l.call(this,function(){this.render("object"==typeof a||c.show.ready)},c.prerender?0:c.show.delay)))}var c=this.options,e=c.show.target,f=c.hide.target,g=c.show.event?d.trim(""+c.show.event).split(" "):[],h=c.hi
 de.event?d.trim(""+c.hide.event).split(" "):[];this._bind(this.elements.target,["remove","removeqtip"],function(){this.destroy(!0)},"destroy"),/mouse(over|enter)/i.test(c.show.event)&&!/mouse(out|leave)/i.test(c.hide.event)&&h.push("mouseleave"),this._bind(e,"mousemove",function(a){this._storeMouse(a),this.cache.onTarget=D}),this._bindEvents(g,h,e,f,b,function(){return this.timers?void clearTimeout(this.timers.show):E}),(c.show.ready||c.prerender)&&b.call(this,a)},z._assignEvents=function(){var c=this,e=this.options,f=e.position,g=this.tooltip,h=e.show.target,i=e.hide.target,j=f.container,k=f.viewport,l=d(b),q=(d(b.body),d(a)),r=e.show.event?d.trim(""+e.show.event).split(" "):[],s=e.hide.event?d.trim(""+e.hide.event).split(" "):[];d.each(e.events,function(a,b){c._bind(g,"toggle"===a?["tooltipshow","tooltiphide"]:["tooltip"+a],b,null,g)}),/mouse(out|leave)/i.test(e.hide.event)&&"window"===e.hide.leave&&this._bind(l,["mouseout","blur"],function(a){/select|option/.test(a.target.nodeNam
 e)||a.relatedTarget||this.hide(a)}),e.hide.fixed?i=i.add(g.addClass(Y)):/mouse(over|enter)/i.test(e.show.event)&&this._bind(i,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+e.hide.event).indexOf("unfocus")>-1&&this._bind(j.closest("html"),["mousedown","touchstart"],function(a){var b=d(a.target),c=this.rendered&&!this.tooltip.hasClass(ab)&&this.tooltip[0].offsetWidth>0,e=b.parents(W).filter(this.tooltip[0]).length>0;b[0]===this.target[0]||b[0]===this.tooltip[0]||e||this.target.has(b[0]).length||!c||this.hide(a)}),"number"==typeof e.hide.inactive&&(this._bind(h,"qtip-"+this.id+"-inactive",o,"inactive"),this._bind(i.add(g),y.inactiveEvents,o)),this._bindEvents(r,s,h,i,m,n),this._bind(h.add(g),"mousemove",function(a){if("number"==typeof e.hide.distance){var b=this.cache.origin||{},c=this.options.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&this.hide(a)}this._storeMouse(a)}),"mouse"===f.target&&f.adjust.mouse&&(e.hide.event&&this._bind(h,["mousee
 nter","mouseleave"],function(a){return this.cache?void(this.cache.onTarget="mouseenter"===a.type):E}),this._bind(l,"mousemove",function(a){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(ab)&&this.tooltip[0].offsetWidth>0&&this.reposition(a)})),(f.adjust.resize||k.length)&&this._bind(d.event.special.resize?k:q,"resize",p),f.adjust.scroll&&this._bind(q.add(f.container),"scroll",p)},z._unassignEvents=function(){var c=this.options,e=c.show.target,f=c.hide.target,g=d.grep([this.elements.target[0],this.rendered&&this.tooltip[0],c.position.container[0],c.position.viewport[0],c.position.container.closest("html")[0],a,b],function(a){return"object"==typeof a});e&&e.toArray&&(g=g.concat(e.toArray())),f&&f.toArray&&(g=g.concat(f.toArray())),this._unbind(g)._unbind(g,"destroy")._unbind(g,"inactive")},d(function(){q(W,["mouseenter","mouseleave"],function(a){var b="mouseenter"===a.type,c=d(a.currentTarget),e=d(a.relatedTarget||a.target),f=this.options;b?(this.focus(a),c.hasClass(Y)&&!c
 .hasClass(ab)&&clearTimeout(this.timers.hide)):"mouse"===f.position.target&&f.position.adjust.mouse&&f.hide.event&&f.show.target&&!e.closest(f.show.target[0]).length&&this.hide(a),c.toggleClass(_,b)}),q("["+U+"]",X,o)}),y=d.fn.qtip=function(a,b,e){var f=(""+a).toLowerCase(),g=F,i=d.makeArray(arguments).slice(1),j=i[i.length-1],k=this[0]?d.data(this[0],S):F;return!arguments.length&&k||"api"===f?k:"string"==typeof a?(this.each(function(){var a=d.data(this,S);if(!a)return D;if(j&&j.timeStamp&&(a.cache.event=j),!b||"option"!==f&&"options"!==f)a[f]&&a[f].apply(a,i);else{if(e===c&&!d.isPlainObject(b))return g=a.get(b),E;a.set(b,e)}}),g!==F?g:this):"object"!=typeof a&&arguments.length?void 0:(k=h(d.extend(D,{},a)),this.each(function(a){var b,c;return c=d.isArray(k.id)?k.id[a]:k.id,c=!c||c===E||c.length<1||y.api[c]?y.nextid++:c,b=r(d(this),c,k),b===E?D:(y.api[c]=b,d.each(R,function(){"initialize"===this.initialize&&this(b)}),void b._assignInitialEvents(j))}))},d.qtip=e,y.api={},d.each({attr
 :function(a,b){if(this.length){var c=this[0],e="title",f=d.data(c,"qtip");if(a===e&&f&&"object"==typeof f&&f.options.suppress)return arguments.length<2?d.attr(c,cb):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",b),this.attr(cb,b))}return d.fn["attr"+bb].apply(this,arguments)},clone:function(a){var b=(d([]),d.fn["clone"+bb].apply(this,arguments));return a||b.filter("["+cb+"]").attr("title",function(){return d.attr(this,cb)}).removeAttr(cb),b}},function(a,b){if(!b||d.fn[a+bb])return D;var c=d.fn[a+bb]=d.fn[a];d.fn[a]=function(){return b.apply(this,arguments)||c.apply(this,arguments)}}),d.ui||(d["cleanData"+bb]=d.cleanData,d.cleanData=function(a){for(var b,c=0;(b=d(a[c])).length;c++)if(b.attr(T))try{b.triggerHandler("removeqtip")}catch(e){}d["cleanData"+bb].apply(this,arguments)}),y.version="2.2.1",y.nextid=0,y.inactiveEvents=X,y.zindex=15e3,y.defaults={prerender:E,id:E,overwrite:D,suppress:D,content:{text:D,attr:"title",title:E,button:E},position:{my:"top left",at
 :"bottom right",target:E,container:E,viewport:E,adjust:{x:0,y:0,mouse:D,scroll:D,resize:D,method:"flipinvert flipinvert"},effect:function(a,b){d(this).animate(b,{duration:200,queue:E})}},show:{target:E,event:"mouseenter",effect:D,delay:90,solo:E,ready:E,autofocus:E},hide:{target:E,event:"mouseleave",effect:D,delay:0,fixed:E,inactive:E,leave:"window",distance:E},style:{classes:"",widget:E,width:E,height:E,def:D},events:{render:F,move:F,show:F,hide:F,toggle:F,visible:F,hidden:F,focus:F,blur:F}};var hb,ib="margin",jb="border",kb="color",lb="background-color",mb="transparent",nb=" !important",ob=!!b.createElement("canvas").getContext,pb=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,qb={},rb=["Webkit","O","Moz","ms"];if(ob)var sb=a.devicePixelRatio||1,tb=function(){var a=b.createElement("canvas").getContext("2d");return a.backingStorePixelRatio||a.webkitBackingStorePixelRatio||a.mozBackingStorePixelRatio||a.msBackingStorePixelRatio||a.oBackingStorePixelRatio||1}(),ub=sb/tb;else var vb=fu
 nction(a,b,c){return"<qtipvml:"+a+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(b||"")+' style="behavior: url(#default#VML); '+(c||"")+'" />'};d.extend(v.prototype,{init:function(a){var b,c;c=this.element=a.elements.tip=d("<div />",{"class":S+"-tip"}).prependTo(a.tooltip),ob?(b=d("<canvas />").appendTo(this.element)[0].getContext("2d"),b.lineJoin="miter",b.miterLimit=1e5,b.save()):(b=vb("shape",'coordorigin="0,0"',"position:absolute;"),this.element.html(b+b),a._bind(d("*",c).add(c),["click","mousedown"],function(a){a.stopPropagation()},this._ns)),a._bind(a.tooltip,"tooltipmove",this.reposition,this._ns,this),this.create()},_swapDimensions:function(){this.size[0]=this.options.height,this.size[1]=this.options.width},_resetDimensions:function(){this.size[0]=this.options.width,this.size[1]=this.options.height},_useTitle:function(a){var b=this.qtip.elements.titlebar;return b&&(a.y===K||a.y===O&&this.element.position().top+this.size[1]/2+this.options.offset<b.outerHeight(D))
 },_parseCorner:function(a){var b=this.qtip.options.position.my;return a===E||b===E?a=E:a===D?a=new A(b.string()):a.string||(a=new A(a),a.fixed=D),a},_parseWidth:function(a,b,c){var d=this.qtip.elements,e=jb+s(b)+"Width";return(c?u(c,e):u(d.content,e)||u(this._useTitle(a)&&d.titlebar||d.content,e)||u(d.tooltip,e))||0},_parseRadius:function(a){var b=this.qtip.elements,c=jb+s(a.y)+s(a.x)+"Radius";return db.ie<9?0:u(this._useTitle(a)&&b.titlebar||b.content,c)||u(b.tooltip,c)||0},_invalidColour:function(a,b,c){var d=a.css(b);return!d||c&&d===a.css(c)||pb.test(d)?E:d},_parseColours:function(a){var b=this.qtip.elements,c=this.element.css("cssText",""),e=jb+s(a[a.precedance])+s(kb),f=this._useTitle(a)&&b.titlebar||b.content,g=this._invalidColour,h=[];return h[0]=g(c,lb)||g(f,lb)||g(b.content,lb)||g(b.tooltip,lb)||c.css(lb),h[1]=g(c,e,kb)||g(f,e,kb)||g(b.content,e,kb)||g(b.tooltip,e,kb)||b.tooltip.css(e),d("*",c).add(c).css("cssText",lb+":"+mb+nb+";"+jb+":0"+nb+";"),h},_calculateSize:functio
 n(a){var b,c,d,e=a.precedance===H,f=this.options.width,g=this.options.height,h="c"===a.abbrev(),i=(e?f:g)*(h?.5:1),j=Math.pow,k=Math.round,l=Math.sqrt(j(i,2)+j(g,2)),m=[this.border/i*l,this.border/g*l];return m[2]=Math.sqrt(j(m[0],2)-j(this.border,2)),m[3]=Math.sqrt(j(m[1],2)-j(this.border,2)),b=l+m[2]+m[3]+(h?0:m[0]),c=b/l,d=[k(c*f),k(c*g)],e?d:d.reverse()},_calculateTip:function(a,b,c){c=c||1,b=b||this.size;var d=b[0]*c,e=b[1]*c,f=Math.ceil(d/2),g=Math.ceil(e/2),h={br:[0,0,d,e,d,0],bl:[0,0,d,0,0,e],tr:[0,e,d,0,d,e],tl:[0,0,0,e,d,e],tc:[0,e,f,0,d,e],bc:[0,0,d,0,f,e],rc:[0,0,d,g,0,e],lc:[d,0,d,e,0,g]};return h.lt=h.br,h.rt=h.bl,h.lb=h.tr,h.rb=h.tl,h[a.abbrev()]},_drawCoords:function(a,b){a.beginPath(),a.moveTo(b[0],b[1]),a.lineTo(b[2],b[3]),a.lineTo(b

<TRUNCATED>

[08/28] incubator-nifi git commit: Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/incubator-nifi into develop

Posted by mc...@apache.org.
Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/incubator-nifi into develop


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/5ebf3b51
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/5ebf3b51
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/5ebf3b51

Branch: refs/heads/nifi-27
Commit: 5ebf3b51cd7a51ed52ac38c37797b5268129d633
Parents: cb63c66 2735c6c
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 11:08:10 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 11:08:10 2014 -0500

----------------------------------------------------------------------
 .../resources/src/main/resources/bin/nifi.sh    | 16 +++-
 .../web/controller/StandardSearchContext.java   | 18 +---
 .../accesscontrol/DfmAccessControlTest.java     | 26 +++++-
 .../src/main/webapp/js/nf/canvas/nf-canvas.js   | 95 ++++++++++----------
 .../main/webapp/js/nf/canvas/nf-connectable.js  |  8 +-
 .../main/webapp/js/nf/canvas/nf-draggable.js    | 49 ++++++----
 .../js/nf/canvas/nf-processor-property-table.js | 10 +--
 .../main/webapp/js/nf/canvas/nf-selectable.js   |  6 +-
 .../main/webapp/js/nf/nf-processor-details.js   | 16 ++--
 9 files changed, 142 insertions(+), 102 deletions(-)
----------------------------------------------------------------------



[18/28] incubator-nifi git commit: NIFI-27: - Latest version of qtip2.

Posted by mc...@apache.org.
NIFI-27:
- Latest version of qtip2.


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/57b4178f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/57b4178f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/57b4178f

Branch: refs/heads/nifi-27
Commit: 57b4178f19960bb4359d79f462c6e790e3e8f1a1
Parents: f60a97b
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Dec 10 08:35:31 2014 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Wed Dec 10 12:19:26 2014 -0500

----------------------------------------------------------------------
 .../webapp/WEB-INF/pages/bulletin-board.jsp     |   2 +-
 .../src/main/webapp/WEB-INF/pages/canvas.jsp    |   2 +-
 .../src/main/webapp/WEB-INF/pages/cluster.jsp   |   2 +-
 .../src/main/webapp/WEB-INF/pages/counters.jsp  |   2 +-
 .../src/main/webapp/WEB-INF/pages/history.jsp   |   2 +-
 .../main/webapp/WEB-INF/pages/provenance.jsp    |   2 +-
 .../src/main/webapp/WEB-INF/pages/summary.jsp   |   2 +-
 .../src/main/webapp/WEB-INF/pages/templates.jsp |   2 +-
 .../src/main/webapp/WEB-INF/pages/users.jsp     |   2 +-
 .../main/webapp/js/jquery/qtip2/jquery.qtip.css | 557 ---------------
 .../webapp/js/jquery/qtip2/jquery.qtip.min.css  |   3 +
 .../webapp/js/jquery/qtip2/jquery.qtip.min.js   | 711 +------------------
 12 files changed, 17 insertions(+), 1272 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/bulletin-board.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/bulletin-board.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/bulletin-board.jsp
index 8669f6c..083862d 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/bulletin-board.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/bulletin-board.jsp
@@ -24,7 +24,7 @@
         ${nf.bulletin.board.style.tags}
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <script type="text/javascript" src="js/jquery/jquery-1.7.min.js"></script>
         <script type="text/javascript" src="js/jquery/jquery.center.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
index acdd147..c8f2ff7 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
@@ -28,7 +28,7 @@
         <link rel="stylesheet" href="js/jquery/tabbs/jquery.tabbs.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/minicolors/jquery.minicolors.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
index 33fdbb0..e3e7b86 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
@@ -24,7 +24,7 @@
         ${nf.cluster.style.tags}
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
index 5b90113..21ee508 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
@@ -24,7 +24,7 @@
         ${nf.counters.style.tags}
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
index 47eb9ec..61be727 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
@@ -24,7 +24,7 @@
         ${nf.history.style.tags}
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
index 742dd32..2f51918 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
@@ -25,7 +25,7 @@
         <link rel="stylesheet" href="js/jquery/tabbs/jquery.tabbs.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
index 983fac9..b34f0e6 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
@@ -25,7 +25,7 @@
         <link rel="stylesheet" href="js/jquery/tabbs/jquery.tabbs.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
index d4c41ab..c7c0293 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
@@ -24,7 +24,7 @@
         ${nf.templates.style.tags}
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
index a1b511f..770dad5 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
@@ -25,7 +25,7 @@
         <link rel="stylesheet" href="js/jquery/tabbs/jquery.tabbs.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
         <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
-        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
         <link rel="stylesheet" href="js/jquery/css/smoothness/jquery-ui-1.8.10.custom.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
         <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.css
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.css b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.css
deleted file mode 100755
index 4655d9c..0000000
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.css
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
-* qTip2 - Pretty powerful tooltips
-* http://craigsworks.com/projects/qtip2/
-*
-* Version: 2.0.0pre
-* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com
-*
-* Dual licensed under MIT or GPLv2 licenses
-*   http://en.wikipedia.org/wiki/MIT_License
-*   http://en.wikipedia.org/wiki/GNU_General_Public_License
-*
-* Date: Thu Apr 26 20:40:09 2012 +0100
-*/
-
-/* Core qTip styles */
-.ui-tooltip, .qtip{
-    position: absolute;
-    left: -28000px;
-    top: -28000px;
-    display: none;
-
-    max-width: 600px;
-    min-width: 50px;
-
-    font-size: 10.5px;
-    line-height: 12px;
-}
-
-/* Fluid class for determining actual width in IE */
-.ui-tooltip-fluid{
-    display: block;
-    visibility: hidden;
-    position: static !important;
-    float: left !important;
-}
-
-.ui-tooltip-content{
-    position: relative;
-    padding: 5px 9px;
-    overflow: hidden;
-
-    border: 1px solid #000001;
-
-    text-align: left;
-    word-wrap: break-word;
-    overflow: hidden;
-}
-
-.ui-tooltip-titlebar{
-    position: relative;
-    min-height: 14px;
-    padding: 5px 35px 5px 10px;
-    overflow: hidden;
-
-    border: 1px solid #000001;
-    border-width: 1px 1px 0;
-
-    font-weight: bold;
-}
-
-.ui-tooltip-titlebar + .ui-tooltip-content{ border-top-width: 0px !important; }
-
-/*! Default close button class */
-.ui-tooltip-titlebar .ui-state-default{
-    position: absolute;
-    right: 4px;
-    top: 50%;
-    margin-top: -9px;
-
-    cursor: pointer;
-    outline: medium none;
-
-    border-width: 1px;
-    border-style: solid;
-}
-
-* html .ui-tooltip-titlebar .ui-state-default{ top: 16px; } /* IE fix */
-
-.ui-tooltip-titlebar .ui-icon,
-.ui-tooltip-icon .ui-icon{
-    display: block;
-    text-indent: -1000em;
-}
-
-.ui-tooltip-icon, .ui-tooltip-icon .ui-icon{
-    -moz-border-radius: 3px;
-    -webkit-border-radius: 3px;
-    border-radius: 3px;
-}
-
-.ui-tooltip-icon .ui-icon{
-    width: 18px;
-    height: 14px;
-
-    text-align: center;
-    text-indent: 0;
-    font: normal bold 10px/13px Tahoma,sans-serif;
-
-    color: inherit;
-    background: transparent none no-repeat -100em -100em;
-}
-
-
-/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
-.ui-tooltip-focus{
-
-}
-
-/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
-.ui-tooltip-hover{
-
-}
-
-
-/*! Default tooltip style */
-.ui-tooltip-default .ui-tooltip-titlebar,
-.ui-tooltip-default .ui-tooltip-content{
-    border-color: #F1D031;
-    background-color: #FFFFA3;
-    color: #555;
-}
-
-.ui-tooltip-default .ui-tooltip-titlebar{
-    background-color: #FFEF93;
-}
-
-.ui-tooltip-default .ui-tooltip-icon{
-    border-color: #CCC;
-    background: #F1F1F1;
-    color: #777;
-}
-
-.ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{
-    border-color: #AAA;
-    color: #111;
-}
-
-/* Modal plugin */
-#qtip-overlay{
-    position: fixed;
-    left: -10000em;
-    top: -10000em;
-}
-
-/* Applied to modals with show.modal.blur set to true */
-#qtip-overlay.blurs{ cursor: pointer; }
-
-/* Change opacity of overlay here */
-#qtip-overlay div{
-    position: absolute;
-    left: 0; top: 0;
-    width: 100%; height: 100%;
-
-    background-color: black;
-
-    opacity: 0.7;
-    filter:alpha(opacity=70);
-    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
-}
-
-/* Tips plugin */
-.ui-tooltip .ui-tooltip-tip{
-    margin: 0 auto;
-    overflow: hidden;
-    z-index: 10;
-}
-
-.ui-tooltip .ui-tooltip-tip,
-.ui-tooltip .ui-tooltip-tip *{
-    position: absolute;
-
-    line-height: 0.1px !important;
-    font-size: 0.1px !important;
-    color: #123456;
-
-    background: transparent;
-    border: 0px dashed transparent;
-}
-
-.ui-tooltip .ui-tooltip-tip canvas{ top: 0; left: 0; }
-
-
-/*! Light tooltip style */
-.ui-tooltip-light .ui-tooltip-titlebar,
-.ui-tooltip-light .ui-tooltip-content{
-    border-color: #E2E2E2;
-    color: #454545;
-}
-
-.ui-tooltip-light .ui-tooltip-content{
-    background-color: white;
-}
-
-.ui-tooltip-light .ui-tooltip-titlebar{
-    background-color: #f1f1f1;
-}
-
-
-/*! Dark tooltip style */
-.ui-tooltip-dark .ui-tooltip-titlebar,
-.ui-tooltip-dark .ui-tooltip-content{
-    border-color: #303030;
-    color: #f3f3f3;
-}
-
-.ui-tooltip-dark .ui-tooltip-content{
-    background-color: #505050;
-}
-
-.ui-tooltip-dark .ui-tooltip-titlebar{
-    background-color: #404040;
-}
-
-.ui-tooltip-dark .ui-tooltip-icon{
-    border-color: #444;
-}
-
-.ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{
-    border-color: #303030;
-}
-
-
-/*! Cream tooltip style */
-.ui-tooltip-cream .ui-tooltip-titlebar,
-.ui-tooltip-cream .ui-tooltip-content{
-    border-color: #F9E98E;
-    color: #A27D35;
-}
-
-.ui-tooltip-cream .ui-tooltip-content{
-    background-color: #FBF7AA;
-}
-
-.ui-tooltip-cream .ui-tooltip-titlebar{
-    background-color: #F0DE7D;
-}
-
-.ui-tooltip-cream .ui-state-default .ui-tooltip-icon{
-    background-position: -82px 0;
-}
-
-
-/*! Red tooltip style */
-.ui-tooltip-red .ui-tooltip-titlebar,
-.ui-tooltip-red .ui-tooltip-content{
-    border-color: #D95252;
-    color: #912323;
-}
-
-.ui-tooltip-red .ui-tooltip-content{
-    background-color: #F78B83;
-}
-
-.ui-tooltip-red .ui-tooltip-titlebar{
-    background-color: #F06D65;
-}
-
-.ui-tooltip-red .ui-state-default .ui-tooltip-icon{
-    background-position: -102px 0;
-}
-
-.ui-tooltip-red .ui-tooltip-icon{
-    border-color: #D95252;
-}
-
-.ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{
-    border-color: #D95252;
-}
-
-
-/*! Green tooltip style */
-.ui-tooltip-green .ui-tooltip-titlebar,
-.ui-tooltip-green .ui-tooltip-content{
-    border-color: #90D93F;
-    color: #3F6219;
-}
-
-.ui-tooltip-green .ui-tooltip-content{
-    background-color: #CAED9E;
-}
-
-.ui-tooltip-green .ui-tooltip-titlebar{
-    background-color: #B0DE78;
-}
-
-.ui-tooltip-green .ui-state-default .ui-tooltip-icon{
-    background-position: -42px 0;
-}
-
-
-/*! Blue tooltip style */
-.ui-tooltip-blue .ui-tooltip-titlebar,
-.ui-tooltip-blue .ui-tooltip-content{
-    border-color: #ADD9ED;
-    color: #5E99BD;
-}
-
-.ui-tooltip-blue .ui-tooltip-content{
-    background-color: #E5F6FE;
-}
-
-.ui-tooltip-blue .ui-tooltip-titlebar{
-    background-color: #D0E9F5;
-}
-
-.ui-tooltip-blue .ui-state-default .ui-tooltip-icon{
-    background-position: -2px 0;
-}
-
-/*! Add shadows to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE6+, Safari 2+ */
-.ui-tooltip-shadow{
-    -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
-    -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
-    box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
-}
-
-.ui-tooltip-shadow .ui-tooltip-titlebar,
-.ui-tooltip-shadow .ui-tooltip-content{
-    filter: progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3);
-    -ms-filter:"progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3)";
-
-    _margin-bottom: -3px; /* IE6 */
-    .margin-bottom: -3px; /* IE7 */
-}
-
-
-/*! Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */
-.ui-tooltip-rounded,
-.ui-tooltip-rounded .ui-tooltip-content,
-.ui-tooltip-tipsy,
-.ui-tooltip-tipsy .ui-tooltip-content,
-.ui-tooltip-youtube,
-.ui-tooltip-youtube .ui-tooltip-content{
-    -moz-border-radius: 4px;
-    -webkit-border-radius: 4px;
-    border-radius: 4px;
-}
-
-.ui-tooltip-rounded .ui-tooltip-titlebar,
-.ui-tooltip-tipsy .ui-tooltip-titlebar,
-.ui-tooltip-youtube .ui-tooltip-titlebar{
-    -moz-border-radius: 5px 5px 0 0;
-    -webkit-border-radius: 5px 5px 0 0;
-    border-radius: 5px 5px 0 0;
-}
-
-.ui-tooltip-rounded .ui-tooltip-titlebar + .ui-tooltip-content,
-.ui-tooltip-tipsy .ui-tooltip-titlebar + .ui-tooltip-content,
-.ui-tooltip-youtube .ui-tooltip-titlebar + .ui-tooltip-content{
-    -moz-border-radius: 0 0 5px 5px;
-    -webkit-border-radius: 0 0 5px 5px;
-    border-radius: 0 0 5px 5px;
-}
-
-
-/*! Youtube tooltip style */
-.ui-tooltip-youtube{
-    -webkit-box-shadow: 0 0 3px #333;
-    -moz-box-shadow: 0 0 3px #333;
-    box-shadow: 0 0 3px #333;
-}
-
-.ui-tooltip-youtube .ui-tooltip-titlebar,
-.ui-tooltip-youtube .ui-tooltip-content{
-    _margin-bottom: 0; /* IE6 */
-    .margin-bottom: 0; /* IE7 */
-
-    background: transparent;
-    background: rgba(0, 0, 0, 0.85);
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);
-    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";
-
-    color: white;
-    border-color: #CCCCCC;
-}
-
-.ui-tooltip-youtube .ui-tooltip-icon{
-    border-color: #222;
-}
-
-.ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{
-    border-color: #303030;
-}
-
-
-/* jQuery TOOLS Tooltip style */
-.ui-tooltip-jtools{
-    background: #232323;
-    background: rgba(0, 0, 0, 0.7);
-    background-image: -moz-linear-gradient(top, #717171, #232323);
-    background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323));
-
-    border: 2px solid #ddd;
-    border: 2px solid rgba(241,241,241,1);
-
-    -moz-border-radius: 2px;
-    -webkit-border-radius: 2px;
-    border-radius: 2px;
-
-    -webkit-box-shadow: 0 0 12px #333;
-    -moz-box-shadow: 0 0 12px #333;
-    box-shadow: 0 0 12px #333;
-}
-
-/* IE Specific */
-.ui-tooltip-jtools .ui-tooltip-titlebar{
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A);
-    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)";
-}
-.ui-tooltip-jtools .ui-tooltip-content{
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323);
-    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)";
-}
-
-.ui-tooltip-jtools .ui-tooltip-titlebar,
-.ui-tooltip-jtools .ui-tooltip-content{
-    background: transparent;
-    color: white;
-    border: 0 dashed transparent;
-}
-
-.ui-tooltip-jtools .ui-tooltip-icon{
-    border-color: #555;
-}
-
-.ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{
-    border-color: #333;
-}
-
-
-/* Cluetip style */
-.ui-tooltip-cluetip{
-    -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
-    -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
-    box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
-}
-
-.ui-tooltip-cluetip .ui-tooltip-titlebar{
-    background-color: #87876A;
-    color: white;
-    border: 0 dashed transparent;
-}
-
-.ui-tooltip-cluetip .ui-tooltip-content{
-    background-color: #D9D9C2;
-    color: #111;
-    border: 0 dashed transparent;
-}
-
-.ui-tooltip-cluetip .ui-tooltip-icon{
-    border-color: #808064;
-}
-
-.ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{
-    border-color: #696952;
-    color: #696952;
-}
-
-
-/* Tipsy style */
-.ui-tooltip-tipsy{
-    border: 0;
-}
-
-.ui-tooltip-tipsy .ui-tooltip-titlebar,
-.ui-tooltip-tipsy .ui-tooltip-content{
-    _margin-bottom: 0; /* IE6 */
-    .margin-bottom: 0; /* IE7 */
-
-    background: transparent;
-    background: rgba(0, 0, 0, .87);
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);
-    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";
-
-    color: white;
-    border: 0px transparent;
-
-    font-size: 11px;
-    font-family: 'Lucida Grande', sans-serif;
-    font-weight: bold;
-    line-height: 16px;
-    text-shadow: 0 1px black;
-}
-
-.ui-tooltip-tipsy .ui-tooltip-titlebar{
-    padding: 6px 35px 0 10;
-}
-
-.ui-tooltip-tipsy .ui-tooltip-content{
-    padding: 6px 10;
-}
-
-.ui-tooltip-tipsy .ui-tooltip-icon{
-    border-color: #222;
-    text-shadow: none;
-}
-
-.ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{
-    border-color: #303030;
-}
-
-
-/* Tipped style */
-.ui-tooltip-tipped{
-
-}
-
-.ui-tooltip-tipped .ui-tooltip-titlebar,
-.ui-tooltip-tipped .ui-tooltip-content{
-    border: 3px solid #959FA9;
-
-    filter: none; -ms-filter: none;
-}
-
-.ui-tooltip-tipped .ui-tooltip-titlebar{
-    background: #3A79B8;
-    background-image: -moz-linear-gradient(top, #3A79B8, #2E629D);
-    background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D));
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D);
-    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)";
-
-    color: white;
-    font-weight: normal;
-    font-family: serif;
-
-    border-bottom-width: 0;
-    -moz-border-radius: 3px 3px 0 0;
-    -webkit-border-radius: 3px 3px 0 0;
-    border-radius: 3px 3px 0 0;
-}
-
-.ui-tooltip-tipped .ui-tooltip-content{
-    background-color: #F9F9F9;
-    color: #454545;
-
-    -moz-border-radius: 0 0 3px 3px;
-    -webkit-border-radius: 0 0 3px 3px;
-    border-radius: 0 0 3px 3px;
-}
-
-.ui-tooltip-tipped .ui-tooltip-icon{
-    border: 2px solid #285589;
-    background: #285589;
-}
-
-.ui-tooltip-tipped .ui-tooltip-icon .ui-icon{
-    background-color: #FBFBFB;
-    color: #555;
-}
-
-/* IE9 fix - removes all filters */
-.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content,
-.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{
-    filter: none;
-    -ms-filter: none;
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/57b4178f/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.css
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.css b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.css
new file mode 100644
index 0000000..27b9729
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/qtip2/jquery.qtip.min.css
@@ -0,0 +1,3 @@
+/* qTip2 v2.2.1 | Plugins: tips modal viewport svg imagemap ie6 | Styles: core basic css3 | qtip2.com | Licensed MIT | Sat Sep 06 2014 23:12:07 */
+
+.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr;box-shadow:none;padding:0}.qtip-content{position:relative;padding:5px 9px;overflow:hidden;text-align:left;word-wrap:break-word}.qtip-titlebar{position:relative;padding:5px 35px 5px 10px;overflow:hidden;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;z-index:11;cursor:pointer;outline:0;border:1px solid transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-icon .ui-icon,.qtip-titlebar .ui-icon{display:block;text-indent:-1000em;direction:ltr}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;line-height:14px;text-align:center;text-indent:0;font:400 bold 10px/13px Tahoma,sans
 -serif;color:inherit;background:-100em -100em no-repeat}.qtip-default{border:1px solid #F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111}.qtip-light{background-color:#fff;border-color:#E2E2E2;color:#454545}.qtip-light .qtip-titlebar{background-color:#f1f1f1}.qtip-dark{background-color:#505050;border-color:#303030;color:#f3f3f3}.qtip-dark .qtip-titlebar{background-color:#404040}.qtip-dark .qtip-icon{border-color:#444}.qtip-dark .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-cream{background-color:#FBF7AA;border-color:#F9E98E;color:#A27D35}.qtip-cream .qtip-titlebar{background-color:#F0DE7D}.qtip-cream .qtip-close .qtip-icon{background-position:-82px 0}.qtip-red{background-color:#F78B83;border-color:#D95252;color:#912323}.qtip-red .qtip-titlebar{background-color:#F06D65}.qtip-red .qtip-
 close .qtip-icon{background-position:-102px 0}.qtip-red .qtip-icon,.qtip-red .qtip-titlebar .ui-state-hover{border-color:#D95252}.qtip-green{background-color:#CAED9E;border-color:#90D93F;color:#3F6219}.qtip-green .qtip-titlebar{background-color:#B0DE78}.qtip-green .qtip-close .qtip-icon{background-position:-42px 0}.qtip-blue{background-color:#E5F6FE;border-color:#ADD9ED;color:#5E99BD}.qtip-blue .qtip-titlebar{background-color:#D0E9F5}.qtip-blue .qtip-close .qtip-icon{background-position:-2px 0}.qtip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)}.qtip-bootstrap,.qtip-rounded,.qtip-tipsy{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.qtip-rounded .qtip-titlebar{-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.qtip-youtube{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 3px #333;-
 moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;color:#fff;border:0 solid transparent;background:#4A4A4A;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,#000));background-image:-webkit-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-moz-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-ms-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-o-linear-gradient(top,#4A4A4A 0,#000 100%)}.qtip-youtube .qtip-titlebar{background-color:transparent}.qtip-youtube .qtip-content{padding:.75em;font:12px arial,sans-serif;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);-ms-filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);"}.qtip-youtube .qtip-icon{border-color:#222}.qtip-youtube .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-jtools{background:#232323;background:rgba(0,0,0,.7);background
 -image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-linear-gradient(top,#717171,#232323);background-image:-ms-linear-gradient(top,#717171,#232323);background-image:-o-linear-gradient(top,#717171,#232323);border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333}.qtip-jtools .qtip-titlebar{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"}.qtip-jtools .qtip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"}.qtip-jtools .qtip-content,
 .qtip-jtools .qtip-titlebar{background:0 0;color:#fff;border:0 dashed transparent}.qtip-jtools .qtip-icon{border-color:#555}.qtip-jtools .qtip-titlebar .ui-state-hover{border-color:#333}.qtip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,.4);box-shadow:4px 4px 5px rgba(0,0,0,.4);background-color:#D9D9C2;color:#111;border:0 dashed transparent}.qtip-cluetip .qtip-titlebar{background-color:#87876A;color:#fff;border:0 dashed transparent}.qtip-cluetip .qtip-icon{border-color:#808064}.qtip-cluetip .qtip-titlebar .ui-state-hover{border-color:#696952;color:#696952}.qtip-tipsy{background:#000;background:rgba(0,0,0,.87);color:#fff;border:0 solid transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:700;line-height:16px;text-shadow:0 1px #000}.qtip-tipsy .qtip-titlebar{padding:6px 35px 0 10px;background-color:transparent}.qtip-tipsy .qtip-content{padding:6px 10px}.qtip-tipsy .qtip-icon{border-color:#222;text-shadow:none}.qt
 ip-tipsy .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-tipped{border:3px solid #959FA9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#F9F9F9;color:#454545;font-weight:400;font-family:serif}.qtip-tipped .qtip-titlebar{border-bottom-width:0;color:#fff;background:#3A79B8;background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D);background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-ms-linear-gradient(top,#3A79B8,#2E629D);background-image:-o-linear-gradient(top,#3A79B8,#2E629D);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"}.qtip-tipped .qtip-icon{border:2px solid #285589;background:#285589}.qtip-tipped .qtip-icon .ui-icon{background-color:#FBFBFB;color:#555}.qtip-bootstrap{font-si
 ze:14px;line-height:20px;color:#333;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.qtip-bootstrap .qtip-titlebar{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.qtip-bootstrap .qtip-titlebar .qtip-close{right:11px;top:45%;border-style:none}.qtip-bootstrap .qtip-content{padding:9px 14px}.qtip-bootstrap .qtip-icon{background:0 0}.qtip-bootstrap .qtip-icon .ui-icon{width:auto;height:auto;float:right;font-size:20px;font-weight:700;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;f
 ilter:alpha(opacity=20)}.qtip-bootstrap .qtip-icon .ui-icon:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.qtip:not(.ie9haxors) div.qtip-content,.qtip:not(.ie9haxors) div.qtip-titlebar{filter:none;-ms-filter:none}.qtip .qtip-tip{margin:0 auto;overflow:hidden;z-index:10}.qtip .qtip-tip,x:-o-prefocus{visibility:hidden}.qtip .qtip-tip,.qtip .qtip-tip .qtip-vml,.qtip .qtip-tip canvas{position:absolute;color:#123456;background:0 0;border:0 dashed transparent}.qtip .qtip-tip canvas{top:0;left:0}.qtip .qtip-tip .qtip-vml{behavior:url(#default#VML);display:inline-block;visibility:visible}#qtip-overlay{position:fixed;left:0;top:0;width:100%;height:100%}#qtip-overlay.blurs{cursor:pointer}#qtip-overlay div{position:absolute;left:0;top:0;width:100%;height:100%;background-color:#000;opacity:.7;filter:alpha(opacity=70);-ms-filter:"alpha(Opacity=70)"}.qtipmodal-ie6fix{position:absolute!important}
\ No newline at end of file


[25/28] incubator-nifi git commit: NIFI-27: - Latest version of codemirror.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.css
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.css b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.css
old mode 100755
new mode 100644
index 4de1393..e2d4ec2
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.css
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.css
@@ -1,67 +1,97 @@
 /* BASICS */
 
 .CodeMirror {
-    /* Set height, width, borders, and global font properties here */
-    font-family: monospace;
-    height: 300px;
+  /* Set height, width, borders, and global font properties here */
+  font-family: monospace;
+  height: 300px;
 }
 .CodeMirror-scroll {
-    /* Set scrolling behaviour here */
-    overflow: auto;
+  /* Set scrolling behaviour here */
+  overflow: auto;
 }
 
 /* PADDING */
 
 .CodeMirror-lines {
-    padding: 4px 0; /* Vertical padding around content */
+  padding: 4px 0; /* Vertical padding around content */
 }
 .CodeMirror pre {
-    padding: 0 4px; /* Horizontal padding of content */
+  padding: 0 4px; /* Horizontal padding of content */
 }
 
 .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
-    background-color: white; /* The little square between H and V scrollbars */
+  background-color: white; /* The little square between H and V scrollbars */
 }
 
 /* GUTTER */
 
 .CodeMirror-gutters {
-    border-right: 1px solid #ddd;
-    background-color: #f7f7f7;
-    white-space: nowrap;
+  border-right: 1px solid #ddd;
+  background-color: #f7f7f7;
+  white-space: nowrap;
 }
 .CodeMirror-linenumbers {}
 .CodeMirror-linenumber {
-    padding: 0 3px 0 5px;
-    min-width: 20px;
-    text-align: right;
-    color: #999;
-    -moz-box-sizing: content-box;
-    box-sizing: content-box;
+  padding: 0 3px 0 5px;
+  min-width: 20px;
+  text-align: right;
+  color: #999;
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
 }
 
+.CodeMirror-guttermarker { color: black; }
+.CodeMirror-guttermarker-subtle { color: #999; }
+
 /* CURSOR */
 
 .CodeMirror div.CodeMirror-cursor {
-    border-left: 1px solid black;
+  border-left: 1px solid black;
 }
 /* Shown when moving in bi-directional text */
 .CodeMirror div.CodeMirror-secondarycursor {
-    border-left: 1px solid silver;
+  border-left: 1px solid silver;
+}
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
+  width: auto;
+  border: 0;
+  background: #7e7;
+}
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
+  z-index: 1;
+}
+
+.cm-animate-fat-cursor {
+  width: auto;
+  border: 0;
+  -webkit-animation: blink 1.06s steps(1) infinite;
+  -moz-animation: blink 1.06s steps(1) infinite;
+  animation: blink 1.06s steps(1) infinite;
+}
+@-moz-keyframes blink {
+  0% { background: #7e7; }
+  50% { background: none; }
+  100% { background: #7e7; }
+}
+@-webkit-keyframes blink {
+  0% { background: #7e7; }
+  50% { background: none; }
+  100% { background: #7e7; }
 }
-.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
-    width: auto;
-    border: 0;
-    background: #7e7;
+@keyframes blink {
+  0% { background: #7e7; }
+  50% { background: none; }
+  100% { background: #7e7; }
 }
+
 /* Can style cursor different in overwrite (non-insert) mode */
 div.CodeMirror-overwrite div.CodeMirror-cursor {}
 
-.cm-tab { display: inline-block; }
+.cm-tab { display: inline-block; text-decoration: inherit; }
 
 .CodeMirror-ruler {
-    border-left: 1px solid #ccc;
-    position: absolute;
+  border-left: 1px solid #ccc;
+  position: absolute;
 }
 
 /* DEFAULT THEME */
@@ -70,11 +100,12 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
 .cm-s-default .cm-atom {color: #219;}
 .cm-s-default .cm-number {color: #164;}
 .cm-s-default .cm-def {color: #00f;}
-.cm-s-default .cm-variable {color: black;}
+.cm-s-default .cm-variable,
+.cm-s-default .cm-punctuation,
+.cm-s-default .cm-property,
+.cm-s-default .cm-operator {}
 .cm-s-default .cm-variable-2 {color: #05a;}
 .cm-s-default .cm-variable-3 {color: #085;}
-.cm-s-default .cm-property {color: black;}
-.cm-s-default .cm-operator {color: black;}
 .cm-s-default .cm-comment {color: #a50;}
 .cm-s-default .cm-string {color: #a11;}
 .cm-s-default .cm-string-2 {color: #f50;}
@@ -94,12 +125,16 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
 .cm-header, .cm-strong {font-weight: bold;}
 .cm-em {font-style: italic;}
 .cm-link {text-decoration: underline;}
+.cm-strikethrough {text-decoration: line-through;}
 
 .cm-s-default .cm-error {color: #f00;}
 .cm-invalidchar {color: #f00;}
 
+/* Default styles for common addons */
+
 div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
 div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
 .CodeMirror-activeline-background {background: #e8f2ff;}
 
 /* STOP */
@@ -108,152 +143,159 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
    the editor. You probably shouldn't touch them. */
 
 .CodeMirror {
-    line-height: 1;
-    position: relative;
-    overflow: hidden;
-    background: white;
-    color: black;
+  line-height: 1;
+  position: relative;
+  overflow: hidden;
+  background: white;
+  color: black;
 }
 
 .CodeMirror-scroll {
-    /* 30px is the magic margin used to hide the element's real scrollbars */
-    /* See overflow: hidden in .CodeMirror */
-    margin-bottom: -30px; margin-right: -30px;
-    padding-bottom: 30px;
-    height: 100%;
-    outline: none; /* Prevent dragging from highlighting the element */
-    position: relative;
-    -moz-box-sizing: content-box;
-    box-sizing: content-box;
+  /* 30px is the magic margin used to hide the element's real scrollbars */
+  /* See overflow: hidden in .CodeMirror */
+  margin-bottom: -30px; margin-right: -30px;
+  padding-bottom: 30px;
+  height: 100%;
+  outline: none; /* Prevent dragging from highlighting the element */
+  position: relative;
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
 }
 .CodeMirror-sizer {
-    position: relative;
-    border-right: 30px solid transparent;
-    -moz-box-sizing: content-box;
-    box-sizing: content-box;
+  position: relative;
+  border-right: 30px solid transparent;
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
 }
 
 /* The fake, visible scrollbars. Used to force redraw during scrolling
    before actuall scrolling happens, thus preventing shaking and
    flickering artifacts. */
 .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
-    position: absolute;
-    z-index: 6;
-    display: none;
+  position: absolute;
+  z-index: 6;
+  display: none;
 }
 .CodeMirror-vscrollbar {
-    right: 0; top: 0;
-    overflow-x: hidden;
-    overflow-y: scroll;
+  right: 0; top: 0;
+  overflow-x: hidden;
+  overflow-y: scroll;
 }
 .CodeMirror-hscrollbar {
-    bottom: 0; left: 0;
-    overflow-y: hidden;
-    overflow-x: scroll;
+  bottom: 0; left: 0;
+  overflow-y: hidden;
+  overflow-x: scroll;
 }
 .CodeMirror-scrollbar-filler {
-    right: 0; bottom: 0;
+  right: 0; bottom: 0;
 }
 .CodeMirror-gutter-filler {
-    left: 0; bottom: 0;
+  left: 0; bottom: 0;
 }
 
 .CodeMirror-gutters {
-    position: absolute; left: 0; top: 0;
-    padding-bottom: 30px;
-    z-index: 3;
+  position: absolute; left: 0; top: 0;
+  padding-bottom: 30px;
+  z-index: 3;
 }
 .CodeMirror-gutter {
-    white-space: normal;
-    height: 100%;
-    -moz-box-sizing: content-box;
-    box-sizing: content-box;
-    padding-bottom: 30px;
-    margin-bottom: -32px;
-    display: inline-block;
-    /* Hack to make IE7 behave */
-    *zoom:1;
-    *display:inline;
+  white-space: normal;
+  height: 100%;
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
+  padding-bottom: 30px;
+  margin-bottom: -32px;
+  display: inline-block;
+  /* Hack to make IE7 behave */
+  *zoom:1;
+  *display:inline;
+}
+.CodeMirror-gutter-wrapper {
+  position: absolute;
+  z-index: 4;
+  height: 100%;
 }
 .CodeMirror-gutter-elt {
-    position: absolute;
-    cursor: default;
-    z-index: 4;
+  position: absolute;
+  cursor: default;
+  z-index: 4;
 }
 
 .CodeMirror-lines {
-    cursor: text;
+  cursor: text;
+  min-height: 1px; /* prevents collapsing before first draw */
 }
 .CodeMirror pre {
-    /* Reset some styles that the rest of the page might have set */
-    -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
-    border-width: 0;
-    background: transparent;
-    font-family: inherit;
-    font-size: inherit;
-    margin: 0;
-    white-space: pre;
-    word-wrap: normal;
-    line-height: inherit;
-    color: inherit;
-    z-index: 2;
-    position: relative;
-    overflow: visible;
+  /* Reset some styles that the rest of the page might have set */
+  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
+  border-width: 0;
+  background: transparent;
+  font-family: inherit;
+  font-size: inherit;
+  margin: 0;
+  white-space: pre;
+  word-wrap: normal;
+  line-height: inherit;
+  color: inherit;
+  z-index: 2;
+  position: relative;
+  overflow: visible;
 }
 .CodeMirror-wrap pre {
-    word-wrap: break-word;
-    white-space: pre-wrap;
-    word-break: normal;
+  word-wrap: break-word;
+  white-space: pre-wrap;
+  word-break: normal;
 }
 
 .CodeMirror-linebackground {
-    position: absolute;
-    left: 0; right: 0; top: 0; bottom: 0;
-    z-index: 0;
+  position: absolute;
+  left: 0; right: 0; top: 0; bottom: 0;
+  z-index: 0;
 }
 
 .CodeMirror-linewidget {
-    position: relative;
-    z-index: 2;
-    overflow: auto;
+  position: relative;
+  z-index: 2;
+  overflow: auto;
 }
 
 .CodeMirror-widget {}
 
 .CodeMirror-wrap .CodeMirror-scroll {
-    overflow-x: hidden;
+  overflow-x: hidden;
 }
 
 .CodeMirror-measure {
-    position: absolute;
-    width: 100%;
-    height: 0;
-    overflow: hidden;
-    visibility: hidden;
+  position: absolute;
+  width: 100%;
+  height: 0;
+  overflow: hidden;
+  visibility: hidden;
 }
 .CodeMirror-measure pre { position: static; }
 
 .CodeMirror div.CodeMirror-cursor {
-    position: absolute;
-    border-right: none;
-    width: 0;
+  position: absolute;
+  border-right: none;
+  width: 0;
 }
 
 div.CodeMirror-cursors {
-    visibility: hidden;
-    position: relative;
-    z-index: 1;
+  visibility: hidden;
+  position: relative;
+  z-index: 3;
 }
 .CodeMirror-focused div.CodeMirror-cursors {
-    visibility: visible;
+  visibility: visible;
 }
 
 .CodeMirror-selected { background: #d9d9d9; }
 .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+.CodeMirror-crosshair { cursor: crosshair; }
 
 .cm-searching {
-    background: #ffa;
-    background: rgba(255, 255, 0, .4);
+  background: #ffa;
+  background: rgba(255, 255, 0, .4);
 }
 
 /* IE7 hack to prevent it from returning funny offsetTops on the spans */
@@ -263,8 +305,14 @@ div.CodeMirror-cursors {
 .cm-force-border { padding-right: .1px; }
 
 @media print {
-    /* Hide the cursor when printing */
-    .CodeMirror div.CodeMirror-cursors {
-        visibility: hidden;
-    }
+  /* Hide the cursor when printing */
+  .CodeMirror div.CodeMirror-cursors {
+    visibility: hidden;
+  }
 }
+
+/* See issue #2901 */
+.cm-tab-wrap-hack:after { content: ''; }
+
+/* Help users use markselection to safely style text background */
+span.CodeMirror-selectedtext { background: none; }


[10/28] incubator-nifi git commit: NIFI-52: Created new implementation of PreparedQuery so that we can still prepare a query even if the expression is invalid

Posted by mc...@apache.org.
NIFI-52: Created new implementation of PreparedQuery so that we can still prepare a query even if the expression is invalid


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/8254b754
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/8254b754
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/8254b754

Branch: refs/heads/nifi-27
Commit: 8254b75437a5b5a168259c7e46460ee3a7bc52f0
Parents: cce3633
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 11:47:00 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 11:47:00 2014 -0500

----------------------------------------------------------------------
 .../language/InvalidPreparedQuery.java          | 71 ++++++++++++++++++++
 .../attribute/expression/language/Query.java    | 44 ++++++------
 .../exception/IllegalAttributeException.java    |  1 +
 3 files changed, 96 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/8254b754/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/InvalidPreparedQuery.java
----------------------------------------------------------------------
diff --git a/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/InvalidPreparedQuery.java b/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/InvalidPreparedQuery.java
new file mode 100644
index 0000000..e23bcc0
--- /dev/null
+++ b/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/InvalidPreparedQuery.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.attribute.expression.language;
+
+import java.util.Map;
+
+import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException;
+import org.apache.nifi.expression.AttributeValueDecorator;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.exception.ProcessException;
+
+
+/**
+ * An implementation of PreparedQuery that throws an {@link AttributeExpressionLanguageException} when attempting
+ * to evaluate the query. This allows a PreparedQuery to be created, even though it can't
+ * be evaluated.
+ */
+public class InvalidPreparedQuery implements PreparedQuery {
+    private final String query;
+    private final String explanation;
+    
+    public InvalidPreparedQuery(final String query, final String explanation) {
+        this.query = query;
+        this.explanation = explanation;
+    }
+    
+    @Override
+    public String evaluateExpressions(final FlowFile flowFile, final AttributeValueDecorator decorator) throws ProcessException {
+        throw new AttributeExpressionLanguageException("Invalid Expression: " + query + " due to " + explanation);
+    }
+
+    @Override
+    public String evaluateExpressions() throws ProcessException {
+        throw new AttributeExpressionLanguageException("Invalid Expression: " + query + " due to " + explanation);
+    }
+
+    @Override
+    public String evaluateExpressions(final AttributeValueDecorator decorator) throws ProcessException {
+        throw new AttributeExpressionLanguageException("Invalid Expression: " + query + " due to " + explanation);
+    }
+
+    @Override
+    public String evaluateExpressions(final FlowFile flowFile) throws ProcessException {
+        throw new AttributeExpressionLanguageException("Invalid Expression: " + query + " due to " + explanation);
+    }
+
+    @Override
+    public String evaluateExpressions(final Map<String, String> attributes) throws ProcessException {
+        throw new AttributeExpressionLanguageException("Invalid Expression: " + query + " due to " + explanation);
+    }
+
+    @Override
+    public String evaluateExpressions(final Map<String, String> attributes, final AttributeValueDecorator decorator) throws ProcessException {
+        throw new AttributeExpressionLanguageException("Invalid Expression: " + query + " due to " + explanation);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/8254b754/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java
----------------------------------------------------------------------
diff --git a/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java b/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java
index 6d9cc91..f4c1c0d 100644
--- a/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java
+++ b/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java
@@ -569,29 +569,33 @@ public class Query {
             return new EmptyPreparedQuery(query.replace("$$", "$"));
         }
 
-        final List<String> substrings = new ArrayList<>();
-        final Map<String, Tree> trees = new HashMap<>();
-
-        int lastIndex = 0;
-        for (final Range range : ranges) {
-            if (range.getStart() > lastIndex) {
-                substrings.add(query.substring(lastIndex, range.getStart()).replace("$$", "$"));
+        try {
+            final List<String> substrings = new ArrayList<>();
+            final Map<String, Tree> trees = new HashMap<>();
+    
+            int lastIndex = 0;
+            for (final Range range : ranges) {
+                if (range.getStart() > lastIndex) {
+                    substrings.add(query.substring(lastIndex, range.getStart()).replace("$$", "$"));
+                    lastIndex = range.getEnd() + 1;
+                }
+    
+                final String treeText = query.substring(range.getStart(), range.getEnd() + 1).replace("$$", "$");
+                substrings.add(treeText);
+                trees.put(treeText, Query.compileTree(treeText));
                 lastIndex = range.getEnd() + 1;
             }
-
-            final String treeText = query.substring(range.getStart(), range.getEnd() + 1).replace("$$", "$");
-            substrings.add(treeText);
-            trees.put(treeText, Query.compileTree(treeText));
-            lastIndex = range.getEnd() + 1;
-        }
-
-        final Range lastRange = ranges.get(ranges.size() - 1);
-        if (lastRange.getEnd() + 1 < query.length()) {
-            final String treeText = query.substring(lastRange.getEnd() + 1).replace("$$", "$");
-            substrings.add(treeText);
+    
+            final Range lastRange = ranges.get(ranges.size() - 1);
+            if (lastRange.getEnd() + 1 < query.length()) {
+                final String treeText = query.substring(lastRange.getEnd() + 1).replace("$$", "$");
+                substrings.add(treeText);
+            }
+    
+            return new StandardPreparedQuery(substrings, trees);
+        } catch (final AttributeExpressionLanguageParsingException e) {
+            return new InvalidPreparedQuery(query, e.getMessage());
         }
-
-        return new StandardPreparedQuery(substrings, trees);
     }
 
     public static Query compile(final String query) throws AttributeExpressionLanguageParsingException {

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/8254b754/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/exception/IllegalAttributeException.java
----------------------------------------------------------------------
diff --git a/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/exception/IllegalAttributeException.java b/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/exception/IllegalAttributeException.java
index 4a9a9c5..f6f32ca 100644
--- a/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/exception/IllegalAttributeException.java
+++ b/commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/exception/IllegalAttributeException.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.attribute.expression.language.exception;
 
 public class IllegalAttributeException extends RuntimeException {
+    private static final long serialVersionUID = 12348721897342L;
 
     public IllegalAttributeException() {
         super();


[22/28] incubator-nifi git commit: NIFI-27: - Latest version of slickgrid.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.core.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.core.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.core.js
index aea3567..2f097b1 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.core.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.core.js
@@ -5,419 +5,463 @@
  */
 
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "Event": Event,
-            "EventData": EventData,
-            "EventHandler": EventHandler,
-            "Range": Range,
-            "NonDataRow": NonDataItem,
-            "Group": Group,
-            "GroupTotals": GroupTotals,
-            "EditorLock": EditorLock,
-            /***
-             * A global singleton editor lock.
-             * @class GlobalEditorLock
-             * @static
-             * @constructor
-             */
-            "GlobalEditorLock": new EditorLock()
-        }
-    });
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "Event": Event,
+      "EventData": EventData,
+      "EventHandler": EventHandler,
+      "Range": Range,
+      "NonDataRow": NonDataItem,
+      "Group": Group,
+      "GroupTotals": GroupTotals,
+      "EditorLock": EditorLock,
+
+      /***
+       * A global singleton editor lock.
+       * @class GlobalEditorLock
+       * @static
+       * @constructor
+       */
+      "GlobalEditorLock": new EditorLock()
+    }
+  });
+
+  /***
+   * An event object for passing data to event handlers and letting them control propagation.
+   * <p>This is pretty much identical to how W3C and jQuery implement events.</p>
+   * @class EventData
+   * @constructor
+   */
+  function EventData() {
+    var isPropagationStopped = false;
+    var isImmediatePropagationStopped = false;
 
     /***
-     * An event object for passing data to event handlers and letting them control propagation.
-     * <p>This is pretty much identical to how W3C and jQuery implement events.</p>
-     * @class EventData
-     * @constructor
+     * Stops event from propagating up the DOM tree.
+     * @method stopPropagation
      */
-    function EventData() {
-        var isPropagationStopped = false;
-        var isImmediatePropagationStopped = false;
-
-        /***
-         * Stops event from propagating up the DOM tree.
-         * @method stopPropagation
-         */
-        this.stopPropagation = function () {
-            isPropagationStopped = true;
-        };
-
-        /***
-         * Returns whether stopPropagation was called on this event object.
-         * @method isPropagationStopped
-         * @return {Boolean}
-         */
-        this.isPropagationStopped = function () {
-            return isPropagationStopped;
-        };
-
-        /***
-         * Prevents the rest of the handlers from being executed.
-         * @method stopImmediatePropagation
-         */
-        this.stopImmediatePropagation = function () {
-            isImmediatePropagationStopped = true;
-        };
-
-        /***
-         * Returns whether stopImmediatePropagation was called on this event object.\
-         * @method isImmediatePropagationStopped
-         * @return {Boolean}
-         */
-        this.isImmediatePropagationStopped = function () {
-            return isImmediatePropagationStopped;
-        }
-    }
+    this.stopPropagation = function () {
+      isPropagationStopped = true;
+    };
 
     /***
-     * A simple publisher-subscriber implementation.
-     * @class Event
-     * @constructor
+     * Returns whether stopPropagation was called on this event object.
+     * @method isPropagationStopped
+     * @return {Boolean}
      */
-    function Event() {
-        var handlers = [];
-
-        /***
-         * Adds an event handler to be called when the event is fired.
-         * <p>Event handler will receive two arguments - an <code>EventData</code> and the <code>data</code>
-         * object the event was fired with.<p>
-         * @method subscribe
-         * @param fn {Function} Event handler.
-         */
-        this.subscribe = function (fn) {
-            handlers.push(fn);
-        };
-
-        /***
-         * Removes an event handler added with <code>subscribe(fn)</code>.
-         * @method unsubscribe
-         * @param fn {Function} Event handler to be removed.
-         */
-        this.unsubscribe = function (fn) {
-            for (var i = handlers.length - 1; i >= 0; i--) {
-                if (handlers[i] === fn) {
-                    handlers.splice(i, 1);
-                }
-            }
-        };
-
-        /***
-         * Fires an event notifying all subscribers.
-         * @method notify
-         * @param args {Object} Additional data object to be passed to all handlers.
-         * @param e {EventData}
-         *      Optional.
-         *      An <code>EventData</code> object to be passed to all handlers.
-         *      For DOM events, an existing W3C/jQuery event object can be passed in.
-         * @param scope {Object}
-         *      Optional.
-         *      The scope ("this") within which the handler will be executed.
-         *      If not specified, the scope will be set to the <code>Event</code> instance.
-         */
-        this.notify = function (args, e, scope) {
-            e = e || new EventData();
-            scope = scope || this;
-
-            var returnValue;
-            for (var i = 0; i < handlers.length && !(e.isPropagationStopped() || e.isImmediatePropagationStopped()); i++) {
-                returnValue = handlers[i].call(scope, e, args);
-            }
-
-            return returnValue;
-        };
-    }
+    this.isPropagationStopped = function () {
+      return isPropagationStopped;
+    };
 
-    function EventHandler() {
-        var handlers = [];
-
-        this.subscribe = function (event, handler) {
-            handlers.push({
-                event: event,
-                handler: handler
-            });
-            event.subscribe(handler);
-        };
-
-        this.unsubscribe = function (event, handler) {
-            var i = handlers.length;
-            while (i--) {
-                if (handlers[i].event === event &&
-                        handlers[i].handler === handler) {
-                    handlers.splice(i, 1);
-                    event.unsubscribe(handler);
-                    return;
-                }
-            }
-        };
-
-        this.unsubscribeAll = function () {
-            var i = handlers.length;
-            while (i--) {
-                handlers[i].event.unsubscribe(handlers[i].handler);
-            }
-            handlers = [];
-        }
+    /***
+     * Prevents the rest of the handlers from being executed.
+     * @method stopImmediatePropagation
+     */
+    this.stopImmediatePropagation = function () {
+      isImmediatePropagationStopped = true;
+    };
+
+    /***
+     * Returns whether stopImmediatePropagation was called on this event object.\
+     * @method isImmediatePropagationStopped
+     * @return {Boolean}
+     */
+    this.isImmediatePropagationStopped = function () {
+      return isImmediatePropagationStopped;
     }
+  }
+
+  /***
+   * A simple publisher-subscriber implementation.
+   * @class Event
+   * @constructor
+   */
+  function Event() {
+    var handlers = [];
+
+    /***
+     * Adds an event handler to be called when the event is fired.
+     * <p>Event handler will receive two arguments - an <code>EventData</code> and the <code>data</code>
+     * object the event was fired with.<p>
+     * @method subscribe
+     * @param fn {Function} Event handler.
+     */
+    this.subscribe = function (fn) {
+      handlers.push(fn);
+    };
 
     /***
-     * A structure containing a range of cells.
-     * @class Range
-     * @constructor
-     * @param fromRow {Integer} Starting row.
-     * @param fromCell {Integer} Starting cell.
-     * @param toRow {Integer} Optional. Ending row. Defaults to <code>fromRow</code>.
-     * @param toCell {Integer} Optional. Ending cell. Defaults to <code>fromCell</code>.
+     * Removes an event handler added with <code>subscribe(fn)</code>.
+     * @method unsubscribe
+     * @param fn {Function} Event handler to be removed.
      */
-    function Range(fromRow, fromCell, toRow, toCell) {
-        if (toRow === undefined && toCell === undefined) {
-            toRow = fromRow;
-            toCell = fromCell;
+    this.unsubscribe = function (fn) {
+      for (var i = handlers.length - 1; i >= 0; i--) {
+        if (handlers[i] === fn) {
+          handlers.splice(i, 1);
         }
+      }
+    };
+
+    /***
+     * Fires an event notifying all subscribers.
+     * @method notify
+     * @param args {Object} Additional data object to be passed to all handlers.
+     * @param e {EventData}
+     *      Optional.
+     *      An <code>EventData</code> object to be passed to all handlers.
+     *      For DOM events, an existing W3C/jQuery event object can be passed in.
+     * @param scope {Object}
+     *      Optional.
+     *      The scope ("this") within which the handler will be executed.
+     *      If not specified, the scope will be set to the <code>Event</code> instance.
+     */
+    this.notify = function (args, e, scope) {
+      e = e || new EventData();
+      scope = scope || this;
 
-        /***
-         * @property fromRow
-         * @type {Integer}
-         */
-        this.fromRow = Math.min(fromRow, toRow);
-
-        /***
-         * @property fromCell
-         * @type {Integer}
-         */
-        this.fromCell = Math.min(fromCell, toCell);
-
-        /***
-         * @property toRow
-         * @type {Integer}
-         */
-        this.toRow = Math.max(fromRow, toRow);
-
-        /***
-         * @property toCell
-         * @type {Integer}
-         */
-        this.toCell = Math.max(fromCell, toCell);
-
-        /***
-         * Returns whether a range represents a single row.
-         * @method isSingleRow
-         * @return {Boolean}
-         */
-        this.isSingleRow = function () {
-            return this.fromRow == this.toRow;
-        };
-
-        /***
-         * Returns whether a range represents a single cell.
-         * @method isSingleCell
-         * @return {Boolean}
-         */
-        this.isSingleCell = function () {
-            return this.fromRow == this.toRow && this.fromCell == this.toCell;
-        };
-
-        /***
-         * Returns whether a range contains a given cell.
-         * @method contains
-         * @param row {Integer}
-         * @param cell {Integer}
-         * @return {Boolean}
-         */
-        this.contains = function (row, cell) {
-            return row >= this.fromRow && row <= this.toRow &&
-                    cell >= this.fromCell && cell <= this.toCell;
-        };
-
-        /***
-         * Returns a readable representation of a range.
-         * @method toString
-         * @return {String}
-         */
-        this.toString = function () {
-            if (this.isSingleCell()) {
-                return "(" + this.fromRow + ":" + this.fromCell + ")";
-            }
-            else {
-                return "(" + this.fromRow + ":" + this.fromCell + " - " + this.toRow + ":" + this.toCell + ")";
-            }
+      var returnValue;
+      for (var i = 0; i < handlers.length && !(e.isPropagationStopped() || e.isImmediatePropagationStopped()); i++) {
+        returnValue = handlers[i].call(scope, e, args);
+      }
+
+      return returnValue;
+    };
+  }
+
+  function EventHandler() {
+    var handlers = [];
+
+    this.subscribe = function (event, handler) {
+      handlers.push({
+        event: event,
+        handler: handler
+      });
+      event.subscribe(handler);
+
+      return this;  // allow chaining
+    };
+
+    this.unsubscribe = function (event, handler) {
+      var i = handlers.length;
+      while (i--) {
+        if (handlers[i].event === event &&
+            handlers[i].handler === handler) {
+          handlers.splice(i, 1);
+          event.unsubscribe(handler);
+          return;
         }
+      }
+
+      return this;  // allow chaining
+    };
+
+    this.unsubscribeAll = function () {
+      var i = handlers.length;
+      while (i--) {
+        handlers[i].event.unsubscribe(handlers[i].handler);
+      }
+      handlers = [];
+
+      return this;  // allow chaining
+    }
+  }
+
+  /***
+   * A structure containing a range of cells.
+   * @class Range
+   * @constructor
+   * @param fromRow {Integer} Starting row.
+   * @param fromCell {Integer} Starting cell.
+   * @param toRow {Integer} Optional. Ending row. Defaults to <code>fromRow</code>.
+   * @param toCell {Integer} Optional. Ending cell. Defaults to <code>fromCell</code>.
+   */
+  function Range(fromRow, fromCell, toRow, toCell) {
+    if (toRow === undefined && toCell === undefined) {
+      toRow = fromRow;
+      toCell = fromCell;
     }
 
+    /***
+     * @property fromRow
+     * @type {Integer}
+     */
+    this.fromRow = Math.min(fromRow, toRow);
 
     /***
-     * A base class that all special / non-data rows (like Group and GroupTotals) derive from.
-     * @class NonDataItem
-     * @constructor
+     * @property fromCell
+     * @type {Integer}
      */
-    function NonDataItem() {
-        this.__nonDataRow = true;
-    }
+    this.fromCell = Math.min(fromCell, toCell);
 
+    /***
+     * @property toRow
+     * @type {Integer}
+     */
+    this.toRow = Math.max(fromRow, toRow);
 
     /***
-     * Information about a group of rows.
-     * @class Group
-     * @extends Slick.NonDataItem
-     * @constructor
+     * @property toCell
+     * @type {Integer}
      */
-    function Group() {
-        this.__group = true;
-        this.__updated = false;
-
-        /***
-         * Number of rows in the group.
-         * @property count
-         * @type {Integer}
-         */
-        this.count = 0;
-
-        /***
-         * Grouping value.
-         * @property value
-         * @type {Object}
-         */
-        this.value = null;
-
-        /***
-         * Formatted display value of the group.
-         * @property title
-         * @type {String}
-         */
-        this.title = null;
-
-        /***
-         * Whether a group is collapsed.
-         * @property collapsed
-         * @type {Boolean}
-         */
-        this.collapsed = false;
-
-        /***
-         * GroupTotals, if any.
-         * @property totals
-         * @type {GroupTotals}
-         */
-        this.totals = null;
-    }
+    this.toCell = Math.max(fromCell, toCell);
+
+    /***
+     * Returns whether a range represents a single row.
+     * @method isSingleRow
+     * @return {Boolean}
+     */
+    this.isSingleRow = function () {
+      return this.fromRow == this.toRow;
+    };
 
-    Group.prototype = new NonDataItem();
+    /***
+     * Returns whether a range represents a single cell.
+     * @method isSingleCell
+     * @return {Boolean}
+     */
+    this.isSingleCell = function () {
+      return this.fromRow == this.toRow && this.fromCell == this.toCell;
+    };
 
     /***
-     * Compares two Group instances.
-     * @method equals
+     * Returns whether a range contains a given cell.
+     * @method contains
+     * @param row {Integer}
+     * @param cell {Integer}
      * @return {Boolean}
-     * @param group {Group} Group instance to compare to.
      */
-    Group.prototype.equals = function (group) {
-        return this.value === group.value &&
-                this.count === group.count &&
-                this.collapsed === group.collapsed;
+    this.contains = function (row, cell) {
+      return row >= this.fromRow && row <= this.toRow &&
+          cell >= this.fromCell && cell <= this.toCell;
     };
 
     /***
-     * Information about group totals.
-     * An instance of GroupTotals will be created for each totals row and passed to the aggregators
-     * so that they can store arbitrary data in it.  That data can later be accessed by group totals
-     * formatters during the display.
-     * @class GroupTotals
-     * @extends Slick.NonDataItem
-     * @constructor
+     * Returns a readable representation of a range.
+     * @method toString
+     * @return {String}
      */
-    function GroupTotals() {
-        this.__groupTotals = true;
-
-        /***
-         * Parent Group.
-         * @param group
-         * @type {Group}
-         */
-        this.group = null;
+    this.toString = function () {
+      if (this.isSingleCell()) {
+        return "(" + this.fromRow + ":" + this.fromCell + ")";
+      }
+      else {
+        return "(" + this.fromRow + ":" + this.fromCell + " - " + this.toRow + ":" + this.toCell + ")";
+      }
     }
+  }
+
+
+  /***
+   * A base class that all special / non-data rows (like Group and GroupTotals) derive from.
+   * @class NonDataItem
+   * @constructor
+   */
+  function NonDataItem() {
+    this.__nonDataRow = true;
+  }
+
+
+  /***
+   * Information about a group of rows.
+   * @class Group
+   * @extends Slick.NonDataItem
+   * @constructor
+   */
+  function Group() {
+    this.__group = true;
+
+    /**
+     * Grouping level, starting with 0.
+     * @property level
+     * @type {Number}
+     */
+    this.level = 0;
 
-    GroupTotals.prototype = new NonDataItem();
+    /***
+     * Number of rows in the group.
+     * @property count
+     * @type {Integer}
+     */
+    this.count = 0;
 
     /***
-     * A locking helper to track the active edit controller and ensure that only a single controller
-     * can be active at a time.  This prevents a whole class of state and validation synchronization
-     * issues.  An edit controller (such as SlickGrid) can query if an active edit is in progress
-     * and attempt a commit or cancel before proceeding.
-     * @class EditorLock
-     * @constructor
+     * Grouping value.
+     * @property value
+     * @type {Object}
      */
-    function EditorLock() {
-        var activeEditController = null;
-
-        /***
-         * Returns true if a specified edit controller is active (has the edit lock).
-         * If the parameter is not specified, returns true if any edit controller is active.
-         * @method isActive
-         * @param editController {EditController}
-         * @return {Boolean}
-         */
-        this.isActive = function (editController) {
-            return (editController ? activeEditController === editController : activeEditController !== null);
-        };
-
-        /***
-         * Sets the specified edit controller as the active edit controller (acquire edit lock).
-         * If another edit controller is already active, and exception will be thrown.
-         * @method activate
-         * @param editController {EditController} edit controller acquiring the lock
-         */
-        this.activate = function (editController) {
-            if (editController === activeEditController) { // already activated?
-                return;
-            }
-            if (activeEditController !== null) {
-                throw "SlickGrid.EditorLock.activate: an editController is still active, can't activate another editController";
-            }
-            if (!editController.commitCurrentEdit) {
-                throw "SlickGrid.EditorLock.activate: editController must implement .commitCurrentEdit()";
-            }
-            if (!editController.cancelCurrentEdit) {
-                throw "SlickGrid.EditorLock.activate: editController must implement .cancelCurrentEdit()";
-            }
-            activeEditController = editController;
-        };
-
-        /***
-         * Unsets the specified edit controller as the active edit controller (release edit lock).
-         * If the specified edit controller is not the active one, an exception will be thrown.
-         * @method deactivate
-         * @param editController {EditController} edit controller releasing the lock
-         */
-        this.deactivate = function (editController) {
-            if (activeEditController !== editController) {
-                throw "SlickGrid.EditorLock.deactivate: specified editController is not the currently active one";
-            }
-            activeEditController = null;
-        };
-
-        /***
-         * Attempts to commit the current edit by calling "commitCurrentEdit" method on the active edit
-         * controller and returns whether the commit attempt was successful (commit may fail due to validation
-         * errors, etc.).  Edit controller's "commitCurrentEdit" must return true if the commit has succeeded
-         * and false otherwise.  If no edit controller is active, returns true.
-         * @method commitCurrentEdit
-         * @return {Boolean}
-         */
-        this.commitCurrentEdit = function () {
-            return (activeEditController ? activeEditController.commitCurrentEdit() : true);
-        };
-
-        /***
-         * Attempts to cancel the current edit by calling "cancelCurrentEdit" method on the active edit
-         * controller and returns whether the edit was successfully cancelled.  If no edit controller is
-         * active, returns true.
-         * @method cancelCurrentEdit
-         * @return {Boolean}
-         */
-        this.cancelCurrentEdit = function cancelCurrentEdit() {
-            return (activeEditController ? activeEditController.cancelCurrentEdit() : true);
-        };
-    }
+    this.value = null;
+
+    /***
+     * Formatted display value of the group.
+     * @property title
+     * @type {String}
+     */
+    this.title = null;
+
+    /***
+     * Whether a group is collapsed.
+     * @property collapsed
+     * @type {Boolean}
+     */
+    this.collapsed = false;
+
+    /***
+     * GroupTotals, if any.
+     * @property totals
+     * @type {GroupTotals}
+     */
+    this.totals = null;
+
+    /**
+     * Rows that are part of the group.
+     * @property rows
+     * @type {Array}
+     */
+    this.rows = [];
+
+    /**
+     * Sub-groups that are part of the group.
+     * @property groups
+     * @type {Array}
+     */
+    this.groups = null;
+
+    /**
+     * A unique key used to identify the group.  This key can be used in calls to DataView
+     * collapseGroup() or expandGroup().
+     * @property groupingKey
+     * @type {Object}
+     */
+    this.groupingKey = null;
+  }
+
+  Group.prototype = new NonDataItem();
+
+  /***
+   * Compares two Group instances.
+   * @method equals
+   * @return {Boolean}
+   * @param group {Group} Group instance to compare to.
+   */
+  Group.prototype.equals = function (group) {
+    return this.value === group.value &&
+        this.count === group.count &&
+        this.collapsed === group.collapsed &&
+        this.title === group.title;
+  };
+
+  /***
+   * Information about group totals.
+   * An instance of GroupTotals will be created for each totals row and passed to the aggregators
+   * so that they can store arbitrary data in it.  That data can later be accessed by group totals
+   * formatters during the display.
+   * @class GroupTotals
+   * @extends Slick.NonDataItem
+   * @constructor
+   */
+  function GroupTotals() {
+    this.__groupTotals = true;
+
+    /***
+     * Parent Group.
+     * @param group
+     * @type {Group}
+     */
+    this.group = null;
+
+    /***
+     * Whether the totals have been fully initialized / calculated.
+     * Will be set to false for lazy-calculated group totals.
+     * @param initialized
+     * @type {Boolean}
+     */
+    this.initialized = false;
+  }
+
+  GroupTotals.prototype = new NonDataItem();
+
+  /***
+   * A locking helper to track the active edit controller and ensure that only a single controller
+   * can be active at a time.  This prevents a whole class of state and validation synchronization
+   * issues.  An edit controller (such as SlickGrid) can query if an active edit is in progress
+   * and attempt a commit or cancel before proceeding.
+   * @class EditorLock
+   * @constructor
+   */
+  function EditorLock() {
+    var activeEditController = null;
+
+    /***
+     * Returns true if a specified edit controller is active (has the edit lock).
+     * If the parameter is not specified, returns true if any edit controller is active.
+     * @method isActive
+     * @param editController {EditController}
+     * @return {Boolean}
+     */
+    this.isActive = function (editController) {
+      return (editController ? activeEditController === editController : activeEditController !== null);
+    };
+
+    /***
+     * Sets the specified edit controller as the active edit controller (acquire edit lock).
+     * If another edit controller is already active, and exception will be thrown.
+     * @method activate
+     * @param editController {EditController} edit controller acquiring the lock
+     */
+    this.activate = function (editController) {
+      if (editController === activeEditController) { // already activated?
+        return;
+      }
+      if (activeEditController !== null) {
+        throw "SlickGrid.EditorLock.activate: an editController is still active, can't activate another editController";
+      }
+      if (!editController.commitCurrentEdit) {
+        throw "SlickGrid.EditorLock.activate: editController must implement .commitCurrentEdit()";
+      }
+      if (!editController.cancelCurrentEdit) {
+        throw "SlickGrid.EditorLock.activate: editController must implement .cancelCurrentEdit()";
+      }
+      activeEditController = editController;
+    };
+
+    /***
+     * Unsets the specified edit controller as the active edit controller (release edit lock).
+     * If the specified edit controller is not the active one, an exception will be thrown.
+     * @method deactivate
+     * @param editController {EditController} edit controller releasing the lock
+     */
+    this.deactivate = function (editController) {
+      if (activeEditController !== editController) {
+        throw "SlickGrid.EditorLock.deactivate: specified editController is not the currently active one";
+      }
+      activeEditController = null;
+    };
+
+    /***
+     * Attempts to commit the current edit by calling "commitCurrentEdit" method on the active edit
+     * controller and returns whether the commit attempt was successful (commit may fail due to validation
+     * errors, etc.).  Edit controller's "commitCurrentEdit" must return true if the commit has succeeded
+     * and false otherwise.  If no edit controller is active, returns true.
+     * @method commitCurrentEdit
+     * @return {Boolean}
+     */
+    this.commitCurrentEdit = function () {
+      return (activeEditController ? activeEditController.commitCurrentEdit() : true);
+    };
+
+    /***
+     * Attempts to cancel the current edit by calling "cancelCurrentEdit" method on the active edit
+     * controller and returns whether the edit was successfully cancelled.  If no edit controller is
+     * active, returns true.
+     * @method cancelCurrentEdit
+     * @return {Boolean}
+     */
+    this.cancelCurrentEdit = function cancelCurrentEdit() {
+      return (activeEditController ? activeEditController.cancelCurrentEdit() : true);
+    };
+  }
 })(jQuery);
 
 


[15/28] incubator-nifi git commit: NIFI-27: - Latest version of D3.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b61a1def/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/d3.min.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/d3.min.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/d3.min.js
old mode 100755
new mode 100644
index 862fcb2..ddaf546
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/d3.min.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/d3.min.js
@@ -1,5385 +1,5 @@
-d3 = function () {
-    function n(n) {
-        return null != n && !isNaN(n)
-    }
-    function t(n) {
-        return n.length
-    }
-    function e(n) {
-        for (var t = 1; n * t % 1; )
-            t *= 10;
-        return t
-    }
-    function r(n, t) {
-        try {
-            for (var e in t)
-                Object.defineProperty(n.prototype, e, {value: t[e], enumerable: !1})
-        } catch (r) {
-            n.prototype = t
-        }
-    }
-    function u() {
-    }
-    function i() {
-    }
-    function o(n, t, e) {
-        return function () {
-            var r = e.apply(t, arguments);
-            return r === t ? n : r
-        }
-    }
-    function a(n, t) {
-        if (t in n)
-            return t;
-        t = t.charAt(0).toUpperCase() + t.substring(1);
-        for (var e = 0, r = Co.length; r > e; ++e) {
-            var u = Co[e] + t;
-            if (u in n)
-                return u
-        }
-    }
-    function c() {
-    }
-    function l() {
-    }
-    function s(n) {
-        function t() {
-            for (var t, r = e, u = -1, i = r.length; ++u < i; )
-                (t = r[u].on) && t.apply(this, arguments);
-            return n
-        }
-        var e = [], r = new u;
-        return t.on = function (t, u) {
-            var i, o = r.get(t);
-            return arguments.length < 2 ? o && o.on : (o && (o.on = null, e = e.slice(0, i = e.indexOf(o)).concat(e.slice(i + 1)), r.remove(t)), u && e.push(r.set(t, {on: u})), n)
-        }, t
-    }
-    function f() {
-        vo.event.preventDefault()
-    }
-    function h() {
-        for (var n, t = vo.event; n = t.sourceEvent; )
-            t = n;
-        return t
-    }
-    function g(n) {
-        for (var t = new l, e = 0, r = arguments.length; ++e < r; )
-            t[arguments[e]] = s(t);
-        return t.of = function (e, r) {
-            return function (u) {
-                try {
-                    var i = u.sourceEvent = vo.event;
-                    u.target = n, vo.event = u, t[u.type].apply(e, r)
-                } finally {
-                    vo.event = i
-                }
-            }
-        }, t
-    }
-    function p(n) {
-        return jo(n, Oo), n
-    }
-    function d(n) {
-        return"function" == typeof n ? n : function () {
-            return Lo(n, this)
-        }
-    }
-    function v(n) {
-        return"function" == typeof n ? n : function () {
-            return Ho(n, this)
-        }
-    }
-    function m(n, t) {
-        function e() {
-            this.removeAttribute(n)
-        }
-        function r() {
-            this.removeAttributeNS(n.space, n.local)
-        }
-        function u() {
-            this.setAttribute(n, t)
-        }
-        function i() {
-            this.setAttributeNS(n.space, n.local, t)
-        }
-        function o() {
-            var e = t.apply(this, arguments);
-            null == e ? this.removeAttribute(n) : this.setAttribute(n, e)
-        }
-        function a() {
-            var e = t.apply(this, arguments);
-            null == e ? this.removeAttributeNS(n.space, n.local) : this.setAttributeNS(n.space, n.local, e)
-        }
-        return n = vo.ns.qualify(n), null == t ? n.local ? r : e : "function" == typeof t ? n.local ? a : o : n.local ? i : u
-    }
-    function y(n) {
-        return n.trim().replace(/\s+/g, " ")
-    }
-    function M(n) {
-        return new RegExp("(?:^|\\s+)" + vo.requote(n) + "(?:\\s+|$)", "g")
-    }
-    function x(n, t) {
-        function e() {
-            for (var e = -1; ++e < u; )
-                n[e](this, t)
-        }
-        function r() {
-            for (var e = -1, r = t.apply(this, arguments); ++e < u; )
-                n[e](this, r)
-        }
-        n = n.trim().split(/\s+/).map(b);
-        var u = n.length;
-        return"function" == typeof t ? r : e
-    }
-    function b(n) {
-        var t = M(n);
-        return function (e, r) {
-            if (u = e.classList)
-                return r ? u.add(n) : u.remove(n);
-            var u = e.getAttribute("class") || "";
-            r ? (t.lastIndex = 0, t.test(u) || e.setAttribute("class", y(u + " " + n))) : e.setAttribute("class", y(u.replace(t, " ")))
-        }
-    }
-    function _(n, t, e) {
-        function r() {
-            this.style.removeProperty(n)
-        }
-        function u() {
-            this.style.setProperty(n, t, e)
-        }
-        function i() {
-            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 ? i : u
-    }
-    function w(n, t) {
-        function e() {
-            delete this[n]
-        }
-        function r() {
-            this[n] = t
-        }
-        function u() {
-            var e = t.apply(this, arguments);
-            null == e ? delete this[n] : this[n] = e
-        }
-        return null == t ? e : "function" == typeof t ? u : r
-    }
-    function S(n) {
-        return"function" == typeof n ? n : (n = vo.ns.qualify(n)).local ? function () {
-            return Mo.createElementNS(n.space, n.local)
-        } : function () {
-            return Mo.createElementNS(this.namespaceURI, n)
-        }
-    }
-    function E(n) {
-        return{__data__: n}
-    }
-    function k(n) {
-        return function () {
-            return Po(this, n)
-        }
-    }
-    function A(n) {
-        return arguments.length || (n = vo.ascending), function (t, e) {
-            return t && e ? n(t.__data__, e.__data__) : !t - !e
-        }
-    }
-    function N(n, t) {
-        for (var e = 0, r = n.length; r > e; e++)
-            for (var u, i = n[e], o = 0, a = i.length; a > o; o++)
-                (u = i[o]) && t(u, o, e);
-        return n
-    }
-    function q(n) {
-        return jo(n, Yo), n
-    }
-    function T(n) {
-        var t, e;
-        return function (r, u, i) {
-            var o, a = n[i].update, c = a.length;
-            for (i != e && (e = i, t = 0), u >= t && (t = u + 1); !(o = a[t]) && ++t < c; )
-                ;
-            return o
-        }
-    }
-    function z() {
-        var n = this.__transition__;
-        n && ++n.active
-    }
-    function C(n, t, e) {
-        function r() {
-            var t = this[o];
-            t && (this.removeEventListener(n, t, t.$), delete this[o])
-        }
-        function u() {
-            var u = l(t, yo(arguments));
-            r.call(this), this.addEventListener(n, this[o] = u, u.$ = e), u._ = t
-        }
-        function i() {
-            var t, e = new RegExp("^__on([^.]+)" + vo.requote(n) + "$");
-            for (var r in this)
-                if (t = r.match(e)) {
-                    var u = this[r];
-                    this.removeEventListener(t[1], u, u.$), delete this[r]
-                }
-        }
-        var o = "__on" + n, a = n.indexOf("."), l = D;
-        a > 0 && (n = n.substring(0, a));
-        var s = Uo.get(n);
-        return s && (n = s, l = j), a ? t ? u : r : t ? c : i
-    }
-    function D(n, t) {
-        return function (e) {
-            var r = vo.event;
-            vo.event = e, t[0] = this.__data__;
-            try {
-                n.apply(this, t)
-            } finally {
-                vo.event = r
-            }
-        }
-    }
-    function j(n, t) {
-        var e = D(n, t);
-        return function (n) {
-            var t = this, r = n.relatedTarget;
-            r && (r === t || 8 & r.compareDocumentPosition(t)) || e.call(t, n)
-        }
-    }
-    function L() {
-        var n = ".dragsuppress-" + ++Zo, t = "touchmove" + n, e = "selectstart" + n, r = "dragstart" + n, u = "click" + n, i = vo.select(bo).on(t, f).on(e, f).on(r, f), o = xo.style, a = o[Vo];
-        return o[Vo] = "none", function (t) {
-            function e() {
-                i.on(u, null)
-            }
-            i.on(n, null), o[Vo] = a, t && (i.on(u, function () {
-                f(), e()
-            }, !0), setTimeout(e, 0))
-        }
-    }
-    function H(n, t) {
-        var e = n.ownerSVGElement || n;
-        if (e.createSVGPoint) {
-            var r = e.createSVGPoint();
-            if (0 > Xo && (bo.scrollX || bo.scrollY)) {
-                e = vo.select("body").append("svg").style({position: "absolute", top: 0, left: 0, margin: 0, padding: 0, border: "none"}, "important");
-                var u = e[0][0].getScreenCTM();
-                Xo = !(u.f || u.e), e.remove()
-            }
-            return Xo ? (r.x = t.pageX, r.y = t.pageY) : (r.x = t.clientX, r.y = t.clientY), r = r.matrixTransform(n.getScreenCTM().inverse()), [r.x, r.y]
-        }
-        var i = n.getBoundingClientRect();
-        return[t.clientX - i.left - n.clientLeft, t.clientY - i.top - n.clientTop]
-    }
-    function F(n) {
-        return n > 0 ? 1 : 0 > n ? -1 : 0
-    }
-    function P(n) {
-        return n > 1 ? 0 : -1 > n ? Bo : Math.acos(n)
-    }
-    function O(n) {
-        return n > 1 ? Bo / 2 : -1 > n ? -Bo / 2 : Math.asin(n)
-    }
-    function R(n) {
-        return(Math.exp(n) - Math.exp(-n)) / 2
-    }
-    function Y(n) {
-        return(Math.exp(n) + Math.exp(-n)) / 2
-    }
-    function I(n) {
-        return R(n) / Y(n)
-    }
-    function U(n) {
-        return(n = Math.sin(n / 2)) * n
-    }
-    function V() {
-    }
-    function Z(n, t, e) {
-        return new X(n, t, e)
-    }
-    function X(n, t, e) {
-        this.h = n, this.s = t, this.l = e
-    }
-    function B(n, t, e) {
-        function r(n) {
-            return n > 360 ? n -= 360 : 0 > n && (n += 360), 60 > n ? i + (o - i) * n / 60 : 180 > n ? o : 240 > n ? i + (o - i) * (240 - n) / 60 : i
-        }
-        function u(n) {
-            return Math.round(255 * r(n))
-        }
-        var i, o;
-        return n = isNaN(n) ? 0 : (n %= 360) < 0 ? n + 360 : n, t = isNaN(t) ? 0 : 0 > t ? 0 : t > 1 ? 1 : t, e = 0 > e ? 0 : e > 1 ? 1 : e, o = .5 >= e ? e * (1 + t) : e + t - e * t, i = 2 * e - o, ot(u(n + 120), u(n), u(n - 120))
-    }
-    function $(n, t, e) {
-        return new W(n, t, e)
-    }
-    function W(n, t, e) {
-        this.h = n, this.c = t, this.l = e
-    }
-    function J(n, t, e) {
-        return isNaN(n) && (n = 0), isNaN(t) && (t = 0), G(e, Math.cos(n *= Jo) * t, Math.sin(n) * t)
-    }
-    function G(n, t, e) {
-        return new K(n, t, e)
-    }
-    function K(n, t, e) {
-        this.l = n, this.a = t, this.b = e
-    }
-    function Q(n, t, e) {
-        var r = (n + 16) / 116, u = r + t / 500, i = r - e / 200;
-        return u = tt(u) * aa, r = tt(r) * ca, i = tt(i) * la, ot(rt(3.2404542 * u - 1.5371385 * r - .4985314 * i), rt(-.969266 * u + 1.8760108 * r + .041556 * i), rt(.0556434 * u - .2040259 * r + 1.0572252 * i))
-    }
-    function nt(n, t, e) {
-        return n > 0 ? $(Math.atan2(e, t) * Go, Math.sqrt(t * t + e * e), n) : $(0 / 0, 0 / 0, n)
-    }
-    function tt(n) {
-        return n > .206893034 ? n * n * n : (n - 4 / 29) / 7.787037
-    }
-    function et(n) {
-        return n > .008856 ? Math.pow(n, 1 / 3) : 7.787037 * n + 4 / 29
-    }
-    function rt(n) {
-        return Math.round(255 * (.00304 >= n ? 12.92 * n : 1.055 * Math.pow(n, 1 / 2.4) - .055))
-    }
-    function ut(n) {
-        return ot(n >> 16, 255 & n >> 8, 255 & n)
-    }
-    function it(n) {
-        return ut(n) + ""
-    }
-    function ot(n, t, e) {
-        return new at(n, t, e)
-    }
-    function at(n, t, e) {
-        this.r = n, this.g = t, this.b = e
-    }
-    function ct(n) {
-        return 16 > n ? "0" + Math.max(0, n).toString(16) : Math.min(255, n).toString(16)
-    }
-    function lt(n, t, e) {
-        var r, u, i, o = 0, a = 0, c = 0;
-        if (r = /([a-z]+)\((.*)\)/i.exec(n))
-            switch (u = r[2].split(","), r[1]) {
-                case"hsl":
-                    return e(parseFloat(u[0]), parseFloat(u[1]) / 100, parseFloat(u[2]) / 100);
-                case"rgb":
-                    return t(gt(u[0]), gt(u[1]), gt(u[2]))
-            }
-        return(i = ha.get(n)) ? t(i.r, i.g, i.b) : (null != n && "#" === n.charAt(0) && (4 === n.length ? (o = n.charAt(1), o += o, a = n.charAt(2), a += a, c = n.charAt(3), c += c) : 7 === n.length && (o = n.substring(1, 3), a = n.substring(3, 5), c = n.substring(5, 7)), o = parseInt(o, 16), a = parseInt(a, 16), c = parseInt(c, 16)), t(o, a, c))
-    }
-    function st(n, t, e) {
-        var r, u, i = Math.min(n /= 255, t /= 255, e /= 255), o = Math.max(n, t, e), a = o - i, c = (o + i) / 2;
-        return a ? (u = .5 > c ? a / (o + i) : a / (2 - o - i), r = n == o ? (t - e) / a + (e > t ? 6 : 0) : t == o ? (e - n) / a + 2 : (n - t) / a + 4, r *= 60) : (r = 0 / 0, u = c > 0 && 1 > c ? 0 : r), Z(r, u, c)
-    }
-    function ft(n, t, e) {
-        n = ht(n), t = ht(t), e = ht(e);
-        var r = et((.4124564 * n + .3575761 * t + .1804375 * e) / aa), u = et((.2126729 * n + .7151522 * t + .072175 * e) / ca), i = et((.0193339 * n + .119192 * t + .9503041 * e) / la);
-        return G(116 * u - 16, 500 * (r - u), 200 * (u - i))
-    }
-    function ht(n) {
-        return(n /= 255) <= .04045 ? n / 12.92 : Math.pow((n + .055) / 1.055, 2.4)
-    }
-    function gt(n) {
-        var t = parseFloat(n);
-        return"%" === n.charAt(n.length - 1) ? Math.round(2.55 * t) : t
-    }
-    function pt(n) {
-        return"function" == typeof n ? n : function () {
-            return n
-        }
-    }
-    function dt(n) {
-        return n
-    }
-    function vt(n) {
-        return function (t, e, r) {
-            return 2 === arguments.length && "function" == typeof e && (r = e, e = null), mt(t, e, n, r)
-        }
-    }
-    function mt(n, t, e, r) {
-        function u() {
-            var n, t = c.status;
-            if (!t && c.responseText || t >= 200 && 300 > t || 304 === t) {
-                try {
-                    n = e.call(i, c)
-                } catch (r) {
-                    return o.error.call(i, r), void 0
-                }
-                o.load.call(i, n)
-            } else
-                o.error.call(i, c)
-        }
-        var i = {}, o = vo.dispatch("beforesend", "progress", "load", "error"), a = {}, c = new XMLHttpRequest, l = null;
-        return!bo.XDomainRequest || "withCredentials"in c || !/^(http(s)?:)?\/\//.test(n) || (c = new XDomainRequest), "onload"in c ? c.onload = c.onerror = u : c.onreadystatechange = function () {
-            c.readyState > 3 && u()
-        }, c.onprogress = function (n) {
-            var t = vo.event;
-            vo.event = n;
-            try {
-                o.progress.call(i, c)
-            } finally {
-                vo.event = t
-            }
-        }, i.header = function (n, t) {
-            return n = (n + "").toLowerCase(), arguments.length < 2 ? a[n] : (null == t ? delete a[n] : a[n] = t + "", i)
-        }, i.mimeType = function (n) {
-            return arguments.length ? (t = null == n ? null : n + "", i) : t
-        }, i.responseType = function (n) {
-            return arguments.length ? (l = n, i) : l
-        }, i.response = function (n) {
-            return e = n, i
-        }, ["get", "post"].forEach(function (n) {
-            i[n] = function () {
-                return i.send.apply(i, [n].concat(yo(arguments)))
-            }
-        }), i.send = function (e, r, u) {
-            if (2 === arguments.length && "function" == typeof r && (u = r, r = null), c.open(e, n, !0), null == t || "accept"in a || (a.accept = t + ",*/*"), c.setRequestHeader)
-                for (var s in a)
-                    c.setRequestHeader(s, a[s]);
-            return null != t && c.overrideMimeType && c.overrideMimeType(t), null != l && (c.responseType = l), null != u && i.on("error", u).on("load", function (n) {
-                u(null, n)
-            }), o.beforesend.call(i, c), c.send(null == r ? null : r), i
-        }, i.abort = function () {
-            return c.abort(), i
-        }, vo.rebind(i, o, "on"), null == r ? i : i.get(yt(r))
-    }
-    function yt(n) {
-        return 1 === n.length ? function (t, e) {
-            n(null == t ? e : null)
-        } : n
-    }
-    function Mt() {
-        var n = bt(), t = _t() - n;
-        t > 24 ? (isFinite(t) && (clearTimeout(va), va = setTimeout(Mt, t)), da = 0) : (da = 1, ya(Mt))
-    }
-    function xt(n, t, e) {
-        var r = arguments.length;
-        2 > r && (t = 0), 3 > r && (e = Date.now()), ma.callback = n, ma.time = e + t
-    }
-    function bt() {
-        var n = Date.now();
-        for (ma = ga; ma; )
-            n >= ma.time && (ma.flush = ma.callback(n - ma.time)), ma = ma.next;
-        return n
-    }
-    function _t() {
-        for (var n, t = ga, e = 1 / 0; t; )
-            t.flush ? t = n ? n.next = t.next : ga = t.next : (t.time < e && (e = t.time), t = (n = t).next);
-        return pa = n, e
-    }
-    function wt(n, t) {
-        var e = Math.pow(10, 3 * Math.abs(8 - t));
-        return{scale: t > 8 ? function (n) {
-                return n / e
-            } : function (n) {
-                return n * e
-            }, symbol: n}
-    }
-    function St(n, t) {
-        return t - (n ? Math.ceil(Math.log(n) / Math.LN10) : 1)
-    }
-    function Et(n) {
-        return n + ""
-    }
-    function kt() {
-    }
-    function At(n, t, e) {
-        var r = e.s = n + t, u = r - n, i = r - u;
-        e.t = n - i + (t - u)
-    }
-    function Nt(n, t) {
-        n && Ta.hasOwnProperty(n.type) && Ta[n.type](n, t)
-    }
-    function qt(n, t, e) {
-        var r, u = -1, i = n.length - e;
-        for (t.lineStart(); ++u < i; )
-            r = n[u], t.point(r[0], r[1], r[2]);
-        t.lineEnd()
-    }
-    function Tt(n, t) {
-        var e = -1, r = n.length;
-        for (t.polygonStart(); ++e < r; )
-            qt(n[e], t, 1);
-        t.polygonEnd()
-    }
-    function zt() {
-        function n(n, t) {
-            n *= Jo, t = t * Jo / 2 + Bo / 4;
-            var e = n - r, o = Math.cos(t), a = Math.sin(t), c = i * a, l = u * o + c * Math.cos(e), s = c * Math.sin(e);
-            Ca.add(Math.atan2(s, l)), r = n, u = o, i = a
-        }
-        var t, e, r, u, i;
-        Da.point = function (o, a) {
-            Da.point = n, r = (t = o) * Jo, u = Math.cos(a = (e = a) * Jo / 2 + Bo / 4), i = Math.sin(a)
-        }, Da.lineEnd = function () {
-            n(t, e)
-        }
-    }
-    function Ct(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 Dt(n, t) {
-        return n[0] * t[0] + n[1] * t[1] + n[2] * t[2]
-    }
-    function jt(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 Lt(n, t) {
-        n[0] += t[0], n[1] += t[1], n[2] += t[2]
-    }
-    function Ht(n, t) {
-        return[n[0] * t, n[1] * t, n[2] * t]
-    }
-    function Ft(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 Pt(n) {
-        return[Math.atan2(n[1], n[0]), O(n[2])]
-    }
-    function Ot(n, t) {
-        return Math.abs(n[0] - t[0]) < $o && Math.abs(n[1] - t[1]) < $o
-    }
-    function Rt(n, t) {
-        n *= Jo;
-        var e = Math.cos(t *= Jo);
-        Yt(e * Math.cos(n), e * Math.sin(n), Math.sin(t))
-    }
-    function Yt(n, t, e) {
-        ++ja, Ha += (n - Ha) / ja, Fa += (t - Fa) / ja, Pa += (e - Pa) / ja
-    }
-    function It() {
-        function n(n, u) {
-            n *= Jo;
-            var i = Math.cos(u *= Jo), o = i * Math.cos(n), a = i * Math.sin(n), c = Math.sin(u), l = Math.atan2(Math.sqrt((l = e * c - r * a) * l + (l = r * o - t * c) * l + (l = t * a - e * o) * l), t * o + e * a + r * c);
-            La += l, Oa += l * (t + (t = o)), Ra += l * (e + (e = a)), Ya += l * (r + (r = c)), Yt(t, e, r)
-        }
-        var t, e, r;
-        Za.point = function (u, i) {
-            u *= Jo;
-            var o = Math.cos(i *= Jo);
-            t = o * Math.cos(u), e = o * Math.sin(u), r = Math.sin(i), Za.point = n, Yt(t, e, r)
-        }
-    }
-    function Ut() {
-        Za.point = Rt
-    }
-    function Vt() {
-        function n(n, t) {
-            n *= Jo;
-            var e = Math.cos(t *= Jo), o = e * Math.cos(n), a = e * Math.sin(n), c = Math.sin(t), l = u * c - i * a, s = i * o - r * c, f = r * a - u * o, h = Math.sqrt(l * l + s * s + f * f), g = r * o + u * a + i * c, p = h && -P(g) / h, d = Math.atan2(h, g);
-            Ia += p * l, Ua += p * s, Va += p * f, La += d, Oa += d * (r + (r = o)), Ra += d * (u + (u = a)), Ya += d * (i + (i = c)), Yt(r, u, i)
-        }
-        var t, e, r, u, i;
-        Za.point = function (o, a) {
-            t = o, e = a, Za.point = n, o *= Jo;
-            var c = Math.cos(a *= Jo);
-            r = c * Math.cos(o), u = c * Math.sin(o), i = Math.sin(a), Yt(r, u, i)
-        }, Za.lineEnd = function () {
-            n(t, e), Za.lineEnd = Ut, Za.point = Rt
-        }
-    }
-    function Zt() {
-        return!0
-    }
-    function Xt(n, t, e, r, u) {
-        var i = [], o = [];
-        if (n.forEach(function (n) {
-            if (!((t = n.length - 1) <= 0)) {
-                var t, e = n[0], r = n[t];
-                if (Ot(e, r)) {
-                    u.lineStart();
-                    for (var a = 0; t > a; ++a)
-                        u.point((e = n[a])[0], e[1]);
-                    return u.lineEnd(), void 0
-                }
-                var c = {point: e, points: n, other: null, visited: !1, entry: !0, subject: !0}, l = {point: e, points: [e], other: c, visited: !1, entry: !1, subject: !1};
-                c.other = l, i.push(c), o.push(l), c = {point: r, points: [r], other: null, visited: !1, entry: !1, subject: !0}, l = {point: r, points: [r], other: c, visited: !1, entry: !0, subject: !1}, c.other = l, i.push(c), o.push(l)
-            }
-        }), o.sort(t), Bt(i), Bt(o), i.length) {
-            if (e)
-                for (var a = 1, c = !e(o[0].point), l = o.length; l > a; ++a)
-                    o[a].entry = c = !c;
-            for (var s, f, h, g = i[0]; ; ) {
-                for (s = g; s.visited; )
-                    if ((s = s.next) === g)
-                        return;
-                f = s.points, u.lineStart();
-                do {
-                    if (s.visited = s.other.visited = !0, s.entry) {
-                        if (s.subject)
-                            for (var a = 0; a < f.length; a++)
-                                u.point((h = f[a])[0], h[1]);
-                        else
-                            r(s.point, s.next.point, 1, u);
-                        s = s.next
-                    } else {
-                        if (s.subject) {
-                            f = s.prev.points;
-                            for (var a = f.length; --a >= 0; )
-                                u.point((h = f[a])[0], h[1])
-                        } else
-                            r(s.point, s.prev.point, -1, u);
-                        s = s.prev
-                    }
-                    s = s.other, f = s.points
-                } while (!s.visited);
-                u.lineEnd()
-            }
-        }
-    }
-    function Bt(n) {
-        if (t = n.length) {
-            for (var t, e, r = 0, u = n[0]; ++r < t; )
-                u.next = e = n[r], e.prev = u, u = e;
-            u.next = e = n[0], e.prev = u
-        }
-    }
-    function $t(n, t, e, r) {
-        return function (u) {
-            function i(t, e) {
-                n(t, e) && u.point(t, e)
-            }
-            function o(n, t) {
-                d.point(n, t)
-            }
-            function a() {
-                v.point = o, d.lineStart()
-            }
-            function c() {
-                v.point = i, d.lineEnd()
-            }
-            function l(n, t) {
-                y.point(n, t), p.push([n, t])
-            }
-            function s() {
-                y.lineStart(), p = []
-            }
-            function f() {
-                l(p[0][0], p[0][1]), y.lineEnd();
-                var n, t = y.clean(), e = m.buffer(), r = e.length;
-                if (p.pop(), g.push(p), p = null, r) {
-                    if (1 & t) {
-                        n = e[0];
-                        var i, r = n.length - 1, o = -1;
-                        for (u.lineStart(); ++o < r; )
-                            u.point((i = n[o])[0], i[1]);
-                        return u.lineEnd(), void 0
-                    }
-                    r > 1 && 2 & t && e.push(e.pop().concat(e.shift())), h.push(e.filter(Wt))
-                }
-            }
-            var h, g, p, d = t(u), v = {point: i, lineStart: a, lineEnd: c, polygonStart: function () {
-                    v.point = l, v.lineStart = s, v.lineEnd = f, h = [], g = [], u.polygonStart()
-                }, polygonEnd: function () {
-                    v.point = i, v.lineStart = a, v.lineEnd = c, h = vo.merge(h), h.length ? Xt(h, Gt, null, e, u) : r(g) && (u.lineStart(), e(null, null, 1, u), u.lineEnd()), u.polygonEnd(), h = g = null
-                }, sphere: function () {
-                    u.polygonStart(), u.lineStart(), e(null, null, 1, u), u.lineEnd(), u.polygonEnd()
-                }}, m = Jt(), y = t(m);
-            return v
-        }
-    }
-    function Wt(n) {
-        return n.length > 1
-    }
-    function Jt() {
-        var n, t = [];
-        return{lineStart: function () {
-                t.push(n = [])
-            }, point: function (t, e) {
-                n.push([t, e])
-            }, lineEnd: c, buffer: function () {
-                var e = t;
-                return t = [], n = null, e
-            }, rejoin: function () {
-                t.length > 1 && t.push(t.pop().concat(t.shift()))
-            }}
-    }
-    function Gt(n, t) {
-        return((n = n.point)[0] < 0 ? n[1] - Bo / 2 - $o : Bo / 2 - n[1]) - ((t = t.point)[0] < 0 ? t[1] - Bo / 2 - $o : Bo / 2 - t[1])
-    }
-    function Kt(n, t) {
-        var e = n[0], r = n[1], u = [Math.sin(e), -Math.cos(e), 0], i = 0, o = !1, a = !1, c = 0;
-        Ca.reset();
-        for (var l = 0, s = t.length; s > l; ++l) {
-            var f = t[l], h = f.length;
-            if (h) {
-                for (var g = f[0], p = g[0], d = g[1] / 2 + Bo / 4, v = Math.sin(d), m = Math.cos(d), y = 1; ; ) {
-                    y === h && (y = 0), n = f[y];
-                    var M = n[0], x = n[1] / 2 + Bo / 4, b = Math.sin(x), _ = Math.cos(x), w = M - p, S = Math.abs(w) > Bo, E = v * b;
-                    if (Ca.add(Math.atan2(E * Math.sin(w), m * _ + E * Math.cos(w))), Math.abs(x) < $o && (a = !0), i += S ? w + (w >= 0 ? 2 : -2) * Bo : w, S ^ p >= e ^ M >= e) {
-                        var k = jt(Ct(g), Ct(n));
-                        Ft(k);
-                        var A = jt(u, k);
-                        Ft(A);
-                        var N = (S ^ w >= 0 ? -1 : 1) * O(A[2]);
-                        r > N && (c += S ^ w >= 0 ? 1 : -1)
-                    }
-                    if (!y++)
-                        break;
-                    p = M, v = b, m = _, g = n
-                }
-                Math.abs(i) > $o && (o = !0)
-            }
-        }
-        return(!a && !o && 0 > Ca || -$o > i) ^ 1 & c
-    }
-    function Qt(n) {
-        var t, e = 0 / 0, r = 0 / 0, u = 0 / 0;
-        return{lineStart: function () {
-                n.lineStart(), t = 1
-            }, point: function (i, o) {
-                var a = i > 0 ? Bo : -Bo, c = Math.abs(i - e);
-                Math.abs(c - Bo) < $o ? (n.point(e, r = (r + o) / 2 > 0 ? Bo / 2 : -Bo / 2), n.point(u, r), n.lineEnd(), n.lineStart(), n.point(a, r), n.point(i, r), t = 0) : u !== a && c >= Bo && (Math.abs(e - u) < $o && (e -= u * $o), Math.abs(i - a) < $o && (i -= a * $o), r = ne(e, r, i, o), n.point(u, r), n.lineEnd(), n.lineStart(), n.point(a, r), t = 0), n.point(e = i, r = o), u = a
-            }, lineEnd: function () {
-                n.lineEnd(), e = r = 0 / 0
-            }, clean: function () {
-                return 2 - t
-            }}
-    }
-    function ne(n, t, e, r) {
-        var u, i, o = Math.sin(n - e);
-        return Math.abs(o) > $o ? Math.atan((Math.sin(t) * (i = Math.cos(r)) * Math.sin(e) - Math.sin(r) * (u = Math.cos(t)) * Math.sin(n)) / (u * i * o)) : (t + r) / 2
-    }
-    function te(n, t, e, r) {
-        var u;
-        if (null == n)
-            u = e * Bo / 2, r.point(-Bo, u), r.point(0, u), r.point(Bo, u), r.point(Bo, 0), r.point(Bo, -u), r.point(0, -u), r.point(-Bo, -u), r.point(-Bo, 0), r.point(-Bo, u);
-        else if (Math.abs(n[0] - t[0]) > $o) {
-            var i = (n[0] < t[0] ? 1 : -1) * Bo;
-            u = e * i / 2, r.point(-i, u), r.point(0, u), r.point(i, u)
-        } else
-            r.point(t[0], t[1])
-    }
-    function ee(n) {
-        return Kt(Ba, n)
-    }
-    function re(n) {
-        function t(n, t) {
-            return Math.cos(n) * Math.cos(t) > o
-        }
-        function e(n) {
-            var e, i, o, c, s;
-            return{lineStart: function () {
-                    c = o = !1, s = 1
-                }, point: function (f, h) {
-                    var g, p = [f, h], d = t(f, h), v = a ? d ? 0 : u(f, h) : d ? u(f + (0 > f ? Bo : -Bo), h) : 0;
-                    if (!e && (c = o = d) && n.lineStart(), d !== o && (g = r(e, p), (Ot(e, g) || Ot(p, g)) && (p[0] += $o, p[1] += $o, d = t(p[0], p[1]))), d !== o)
-                        s = 0, d ? (n.lineStart(), g = r(p, e), n.point(g[0], g[1])) : (g = r(e, p), n.point(g[0], g[1]), n.lineEnd()), e = g;
-                    else if (l && e && a ^ d) {
-                        var m;
-                        v & i || !(m = r(p, e, !0)) || (s = 0, a ? (n.lineStart(), n.point(m[0][0], m[0][1]), n.point(m[1][0], m[1][1]), n.lineEnd()) : (n.point(m[1][0], m[1][1]), n.lineEnd(), n.lineStart(), n.point(m[0][0], m[0][1])))
-                    }
-                    !d || e && Ot(e, p) || n.point(p[0], p[1]), e = p, o = d, i = v
-                }, lineEnd: function () {
-                    o && n.lineEnd(), e = null
-                }, clean: function () {
-                    return s | (c && o) << 1
-                }}
-        }
-        function r(n, t, e) {
-            var r = Ct(n), u = Ct(t), i = [1, 0, 0], a = jt(r, u), c = Dt(a, a), l = a[0], s = c - l * l;
-            if (!s)
-                return!e && n;
-            var f = o * c / s, h = -o * l / s, g = jt(i, a), p = Ht(i, f), d = Ht(a, h);
-            Lt(p, d);
-            var v = g, m = Dt(p, v), y = Dt(v, v), M = m * m - y * (Dt(p, p) - 1);
-            if (!(0 > M)) {
-                var x = Math.sqrt(M), b = Ht(v, (-m - x) / y);
-                if (Lt(b, p), b = Pt(b), !e)
-                    return b;
-                var _, w = n[0], S = t[0], E = n[1], k = t[1];
-                w > S && (_ = w, w = S, S = _);
-                var A = S - w, N = Math.abs(A - Bo) < $o, q = N || $o > A;
-                if (!N && E > k && (_ = E, E = k, k = _), q ? N ? E + k > 0 ^ b[1] < (Math.abs(b[0] - w) < $o ? E : k) : E <= b[1] && b[1] <= k : A > Bo ^ (w <= b[0] && b[0] <= S)) {
-                    var T = Ht(v, (-m + x) / y);
-                    return Lt(T, p), [b, Pt(T)]
-                }
-            }
-        }
-        function u(t, e) {
-            var r = a ? n : Bo - n, u = 0;
-            return-r > t ? u |= 1 : t > r && (u |= 2), -r > e ? u |= 4 : e > r && (u |= 8), u
-        }
-        function i(n) {
-            return Kt(c, n)
-        }
-        var o = Math.cos(n), a = o > 0, c = [n, 0], l = Math.abs(o) > $o, s = qe(n, 6 * Jo);
-        return $t(t, e, s, i)
-    }
-    function ue(n, t, e, r) {
-        function u(r, u) {
-            return Math.abs(r[0] - n) < $o ? u > 0 ? 0 : 3 : Math.abs(r[0] - e) < $o ? u > 0 ? 2 : 1 : Math.abs(r[1] - t) < $o ? u > 0 ? 1 : 0 : u > 0 ? 3 : 2
-        }
-        function i(n, t) {
-            return o(n.point, t.point)
-        }
-        function o(n, t) {
-            var e = u(n, 1), r = u(t, 1);
-            return e !== r ? e - r : 0 === e ? t[1] - n[1] : 1 === e ? n[0] - t[0] : 2 === e ? n[1] - t[1] : t[0] - n[0]
-        }
-        function a(u, i) {
-            var o = i[0] - u[0], a = i[1] - u[1], c = [0, 1];
-            return Math.abs(o) < $o && Math.abs(a) < $o ? n <= u[0] && u[0] <= e && t <= u[1] && u[1] <= r : ie(n - u[0], o, c) && ie(u[0] - e, -o, c) && ie(t - u[1], a, c) && ie(u[1] - r, -a, c) ? (c[1] < 1 && (i[0] = u[0] + c[1] * o, i[1] = u[1] + c[1] * a), c[0] > 0 && (u[0] += c[0] * o, u[1] += c[0] * a), !0) : !1
-        }
-        return function (c) {
-            function l(i) {
-                var o = u(i, -1), a = s([0 === o || 3 === o ? n : e, o > 1 ? r : t]);
-                return a
-            }
-            function s(n) {
-                for (var t = 0, e = M.length, r = n[1], u = 0; e > u; ++u)
-                    for (var i, o = 1, a = M[u], c = a.length, l = a[0]; c > o; ++o)
-                        i = a[o], l[1] <= r ? i[1] > r && f(l, i, n) > 0 && ++t : i[1] <= r && f(l, i, n) < 0 && --t, l = i;
-                return 0 !== t
-            }
-            function f(n, t, e) {
-                return(t[0] - n[0]) * (e[1] - n[1]) - (e[0] - n[0]) * (t[1] - n[1])
-            }
-            function h(i, a, c, l) {
-                var s = 0, f = 0;
-                if (null == i || (s = u(i, c)) !== (f = u(a, c)) || o(i, a) < 0 ^ c > 0) {
-                    do
-                        l.point(0 === s || 3 === s ? n : e, s > 1 ? r : t);
-                    while ((s = (s + c + 4) % 4) !== f)
-                } else
-                    l.point(a[0], a[1])
-            }
-            function g(u, i) {
-                return u >= n && e >= u && i >= t && r >= i
-            }
-            function p(n, t) {
-                g(n, t) && c.point(n, t)
-            }
-            function d() {
-                T.point = m, M && M.push(x = []), A = !0, k = !1, S = E = 0 / 0
-            }
-            function v() {
-                y && (m(b, _), w && k && q.rejoin(), y.push(q.buffer())), T.point = p, k && c.lineEnd()
-            }
-            function m(n, t) {
-                n = Math.max(-$a, Math.min($a, n)), t = Math.max(-$a, Math.min($a, 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);
-                else {
-                    var r = [S, E], u = [n, t];
-                    a(r, u) ? (k || (c.lineStart(), c.point(r[0], r[1])), c.point(u[0], u[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 = Jt(), T = {point: p, lineStart: d, lineEnd: v, polygonStart: function () {
-                    c = q, y = [], M = []
-                }, polygonEnd: function () {
-                    c = N, (y = vo.merge(y)).length ? (c.polygonStart(), Xt(y, i, l, h, c), c.polygonEnd()) : s([n, t]) && (c.polygonStart(), c.lineStart(), h(null, null, 1, c), c.lineEnd(), c.polygonEnd()), y = M = x = null
-                }};
-            return T
-        }
-    }
-    function ie(n, t, e) {
-        if (Math.abs(t) < $o)
-            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 oe(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 ae(n) {
-        var t = 0, e = Bo / 3, r = _e(n), u = r(t, e);
-        return u.parallels = function (n) {
-            return arguments.length ? r(t = n[0] * Bo / 180, e = n[1] * Bo / 180) : [180 * (t / Bo), 180 * (e / Bo)]
-        }, u
-    }
-    function ce(n, t) {
-        function e(n, t) {
-            var e = Math.sqrt(i - 2 * u * Math.sin(t)) / u;
-            return[e * Math.sin(n *= u), o - e * Math.cos(n)]
-        }
-        var r = Math.sin(n), u = (r + Math.sin(t)) / 2, i = 1 + r * (2 * u - r), o = Math.sqrt(i) / u;
-        return e.invert = function (n, t) {
-            var e = o - t;
-            return[Math.atan2(n, e) / u, O((i - (n * n + e * e) * u * u) / (2 * u))]
-        }, e
-    }
-    function le() {
-        function n(n, t) {
-            Ja += u * n - r * t, r = n, u = t
-        }
-        var t, e, r, u;
-        tc.point = function (i, o) {
-            tc.point = n, t = r = i, e = u = o
-        }, tc.lineEnd = function () {
-            n(t, e)
-        }
-    }
-    function se(n, t) {
-        Ga > n && (Ga = n), n > Qa && (Qa = n), Ka > t && (Ka = t), t > nc && (nc = t)
-    }
-    function fe() {
-        function n(n, t) {
-            o.push("M", n, ",", t, i)
-        }
-        function t(n, t) {
-            o.push("M", n, ",", t), a.point = e
-        }
-        function e(n, t) {
-            o.push("L", n, ",", t)
-        }
-        function r() {
-            a.point = n
-        }
-        function u() {
-            o.push("Z")
-        }
-        var i = he(4.5), o = [], a = {point: n, lineStart: function () {
-                a.point = t
-            }, lineEnd: r, polygonStart: function () {
-                a.lineEnd = u
-            }, polygonEnd: function () {
-                a.lineEnd = r, a.point = n
-            }, pointRadius: function (n) {
-                return i = he(n), a
-            }, result: function () {
-                if (o.length) {
-                    var n = o.join("");
-                    return o = [], n
-                }
-            }};
-        return a
-    }
-    function he(n) {
-        return"m0," + n + "a" + n + "," + n + " 0 1,1 0," + -2 * n + "a" + n + "," + n + " 0 1,1 0," + 2 * n + "z"
-    }
-    function ge(n, t) {
-        Ha += n, Fa += t, ++Pa
-    }
-    function pe() {
-        function n(n, r) {
-            var u = n - t, i = r - e, o = Math.sqrt(u * u + i * i);
-            Oa += o * (t + n) / 2, Ra += o * (e + r) / 2, Ya += o, ge(t = n, e = r)
-        }
-        var t, e;
-        rc.point = function (r, u) {
-            rc.point = n, ge(t = r, e = u)
-        }
-    }
-    function de() {
-        rc.point = ge
-    }
-    function ve() {
-        function n(n, t) {
-            var e = n - r, i = t - u, o = Math.sqrt(e * e + i * i);
-            Oa += o * (r + n) / 2, Ra += o * (u + t) / 2, Ya += o, o = u * n - r * t, Ia += o * (r + n), Ua += o * (u + t), Va += 3 * o, ge(r = n, u = t)
-        }
-        var t, e, r, u;
-        rc.point = function (i, o) {
-            rc.point = n, ge(t = r = i, e = u = o)
-        }, rc.lineEnd = function () {
-            n(t, e)
-        }
-    }
-    function me(n) {
-        function t(t, e) {
-            n.moveTo(t, e), n.arc(t, e, o, 0, 2 * Bo)
-        }
-        function e(t, e) {
-            n.moveTo(t, e), a.point = r
-        }
-        function r(t, e) {
-            n.lineTo(t, e)
-        }
-        function u() {
-            a.point = t
-        }
-        function i() {
-            n.closePath()
-        }
-        var o = 4.5, a = {point: t, lineStart: function () {
-                a.point = e
-            }, lineEnd: u, polygonStart: function () {
-                a.lineEnd = i
-            }, polygonEnd: function () {
-                a.lineEnd = u, a.point = t
-            }, pointRadius: function (n) {
-                return o = n, a
-            }, result: c};
-        return a
-    }
-    function ye(n) {
-        function t(t) {
-            function r(e, r) {
-                e = n(e, r), t.point(e[0], e[1])
-            }
-            function u() {
-                M = 0 / 0, S.point = o, t.lineStart()
-            }
-            function o(r, u) {
-                var o = Ct([r, u]), a = n(r, u);
-                e(M, x, y, b, _, w, M = a[0], x = a[1], y = r, b = o[0], _ = o[1], w = o[2], i, t), t.point(M, x)
-            }
-            function a() {
-                S.point = r, t.lineEnd()
-            }
-            function c() {
-                u(), S.point = l, S.lineEnd = s
-            }
-            function l(n, t) {
-                o(f = n, h = t), g = M, p = x, d = b, v = _, m = w, S.point = o
-            }
-            function s() {
-                e(M, x, y, b, _, w, g, p, f, d, v, m, i, t), S.lineEnd = a, a()
-            }
-            var f, h, g, p, d, v, m, y, M, x, b, _, w, S = {point: r, lineStart: u, lineEnd: a, polygonStart: function () {
-                    t.polygonStart(), S.lineStart = c
-                }, polygonEnd: function () {
-                    t.polygonEnd(), S.lineStart = u
-                }};
-            return S
-        }
-        function e(t, i, o, a, c, l, s, f, h, g, p, d, v, m) {
-            var y = s - t, M = f - i, x = y * y + M * M;
-            if (x > 4 * r && v--) {
-                var b = a + g, _ = c + p, w = l + d, S = Math.sqrt(b * b + _ * _ + w * w), E = Math.asin(w /= S), k = Math.abs(Math.abs(w) - 1) < $o ? (o + h) / 2 : Math.atan2(_, b), A = n(k, E), N = A[0], q = A[1], T = N - t, z = q - i, C = M * T - y * z;
-                (C * C / x > r || Math.abs((y * T + M * z) / x - .5) > .3 || u > a * g + c * p + l * d) && (e(t, i, o, a, c, l, N, q, k, b /= S, _ /= S, w, v, m), m.point(N, q), e(N, q, k, b, _, w, s, f, h, g, p, d, v, m))
-            }
-        }
-        var r = .5, u = Math.cos(30 * Jo), i = 16;
-        return t.precision = function (n) {
-            return arguments.length ? (i = (r = n * n) > 0 && 16, t) : Math.sqrt(r)
-        }, t
-    }
-    function Me(n) {
-        this.stream = n
-    }
-    function xe(n) {
-        var t = ye(function (t, e) {
-            return n([t * Go, e * Go])
-        });
-        return function (n) {
-            var e = new Me(n = t(n));
-            return e.point = function (t, e) {
-                n.point(t * Jo, e * Jo)
-            }, e
-        }
-    }
-    function be(n) {
-        return _e(function () {
-            return n
-        })()
-    }
-    function _e(n) {
-        function t(n) {
-            return n = a(n[0] * Jo, n[1] * Jo), [n[0] * h + c, l - n[1] * h]
-        }
-        function e(n) {
-            return n = a.invert((n[0] - c) / h, (l - n[1]) / h), n && [n[0] * Go, n[1] * Go]
-        }
-        function r() {
-            a = oe(o = Ee(m, y, M), i);
-            var n = i(d, v);
-            return c = g - n[0] * h, l = p + n[1] * h, u()
-        }
-        function u() {
-            return s && (s.valid = !1, s = null), t
-        }
-        var i, o, a, c, l, s, f = ye(function (n, t) {
-            return n = i(n, t), [n[0] * h + c, l - n[1] * h]
-        }), h = 150, g = 480, p = 250, d = 0, v = 0, m = 0, y = 0, M = 0, x = Xa, b = dt, _ = null, w = null;
-        return t.stream = function (n) {
-            return s && (s.valid = !1), s = we(o, x(f(b(n)))), s.valid = !0, s
-        }, t.clipAngle = function (n) {
-            return arguments.length ? (x = null == n ? (_ = n, Xa) : re((_ = +n) * Jo), u()) : _
-        }, t.clipExtent = function (n) {
-            return arguments.length ? (w = n, b = n ? ue(n[0][0], n[0][1], n[1][0], n[1][1]) : dt, u()) : w
-        }, t.scale = function (n) {
-            return arguments.length ? (h = +n, r()) : h
-        }, t.translate = function (n) {
-            return arguments.length ? (g = +n[0], p = +n[1], r()) : [g, p]
-        }, t.center = function (n) {
-            return arguments.length ? (d = n[0] % 360 * Jo, v = n[1] % 360 * Jo, r()) : [d * Go, v * Go]
-        }, t.rotate = function (n) {
-            return arguments.length ? (m = n[0] % 360 * Jo, y = n[1] % 360 * Jo, M = n.length > 2 ? n[2] % 360 * Jo : 0, r()) : [m * Go, y * Go, M * Go]
-        }, vo.rebind(t, f, "precision"), function () {
-            return i = n.apply(this, arguments), t.invert = i.invert && e, r()
-        }
-    }
-    function we(n, t) {
-        var e = new Me(t);
-        return e.point = function (e, r) {
-            r = n(e * Jo, r * Jo), e = r[0], t.point(e > Bo ? e - 2 * Bo : -Bo > e ? e + 2 * Bo : e, r[1])
-        }, e
-    }
-    function Se(n, t) {
-        return[n, t]
-    }
-    function Ee(n, t, e) {
-        return n ? t || e ? oe(Ae(n), Ne(t, e)) : Ae(n) : t || e ? Ne(t, e) : Se
-    }
-    function ke(n) {
-        return function (t, e) {
-            return t += n, [t > Bo ? t - 2 * Bo : -Bo > t ? t + 2 * Bo : t, e]
-        }
-    }
-    function Ae(n) {
-        var t = ke(n);
-        return t.invert = ke(-n), t
-    }
-    function Ne(n, t) {
-        function e(n, t) {
-            var e = Math.cos(t), a = Math.cos(n) * e, c = Math.sin(n) * e, l = Math.sin(t), s = l * r + a * u;
-            return[Math.atan2(c * i - s * o, a * r - l * u), O(s * i + c * o)]
-        }
-        var r = Math.cos(n), u = Math.sin(n), i = Math.cos(t), o = Math.sin(t);
-        return e.invert = function (n, t) {
-            var e = Math.cos(t), a = Math.cos(n) * e, c = Math.sin(n) * e, l = Math.sin(t), s = l * i - c * o;
-            return[Math.atan2(c * i + l * o, a * r + s * u), O(s * r - a * u)]
-        }, e
-    }
-    function qe(n, t) {
-        var e = Math.cos(n), r = Math.sin(n);
-        return function (u, i, o, a) {
-            var c = o * t;
-            null != u ? (u = Te(e, u), i = Te(e, i), (o > 0 ? i > u : u > i) && (u += 2 * o * Bo)) : (u = n + 2 * o * Bo, i = n - .5 * c);
-            for (var l, s = u; o > 0?s > i:i > s; s -= c)
-                a.point((l = Pt([e, -r * Math.cos(s), -r * Math.sin(s)]))[0], l[1])
-        }
-    }
-    function Te(n, t) {
-        var e = Ct(t);
-        e[0] -= n, Ft(e);
-        var r = P(-e[1]);
-        return((-e[2] < 0 ? -r : r) + 2 * Math.PI - $o) % (2 * Math.PI)
-    }
-    function ze(n, t, e) {
-        var r = vo.range(n, t - $o, e).concat(t);
-        return function (n) {
-            return r.map(function (t) {
-                return[n, t]
-            })
-        }
-    }
-    function Ce(n, t, e) {
-        var r = vo.range(n, t - $o, e).concat(t);
-        return function (n) {
-            return r.map(function (t) {
-                return[t, n]
-            })
-        }
-    }
-    function De(n) {
-        return n.source
-    }
-    function je(n) {
-        return n.target
-    }
-    function Le(n, t, e, r) {
-        var u = Math.cos(t), i = Math.sin(t), o = Math.cos(r), a = Math.sin(r), c = u * Math.cos(n), l = u * Math.sin(n), s = o * Math.cos(e), f = o * Math.sin(e), h = 2 * Math.asin(Math.sqrt(U(r - t) + u * o * U(e - n))), g = 1 / Math.sin(h), p = h ? function (n) {
-            var t = Math.sin(n *= h) * g, e = Math.sin(h - n) * g, r = e * c + t * s, u = e * l + t * f, o = e * i + t * a;
-            return[Math.atan2(u, r) * Go, Math.atan2(o, Math.sqrt(r * r + u * u)) * Go]
-        } : function () {
-            return[n * Go, t * Go]
-        };
-        return p.distance = h, p
-    }
-    function He() {
-        function n(n, u) {
-            var i = Math.sin(u *= Jo), o = Math.cos(u), a = Math.abs((n *= Jo) - t), c = Math.cos(a);
-            uc += Math.atan2(Math.sqrt((a = o * Math.sin(a)) * a + (a = r * i - e * o * c) * a), e * i + r * o * c), t = n, e = i, r = o
-        }
-        var t, e, r;
-        ic.point = function (u, i) {
-            t = u * Jo, e = Math.sin(i *= Jo), r = Math.cos(i), ic.point = n
-        }, ic.lineEnd = function () {
-            ic.point = ic.lineEnd = c
-        }
-    }
-    function Fe(n, t) {
-        function e(t, e) {
-            var r = Math.cos(t), u = Math.cos(e), i = n(r * u);
-            return[i * u * Math.sin(t), i * Math.sin(e)]
-        }
-        return e.invert = function (n, e) {
-            var r = Math.sqrt(n * n + e * e), u = t(r), i = Math.sin(u), o = Math.cos(u);
-            return[Math.atan2(n * i, r * o), Math.asin(r && e * i / r)]
-        }, e
-    }
-    function Pe(n, t) {
-        function e(n, t) {
-            var e = Math.abs(Math.abs(t) - Bo / 2) < $o ? 0 : o / Math.pow(u(t), i);
-            return[e * Math.sin(i * n), o - e * Math.cos(i * n)]
-        }
-        var r = Math.cos(n), u = function (n) {
-            return Math.tan(Bo / 4 + n / 2)
-        }, i = n === t ? Math.sin(n) : Math.log(r / Math.cos(t)) / Math.log(u(t) / u(n)), o = r * Math.pow(u(n), i) / i;
-        return i ? (e.invert = function (n, t) {
-            var e = o - t, r = F(i) * Math.sqrt(n * n + e * e);
-            return[Math.atan2(n, e) / i, 2 * Math.atan(Math.pow(o / r, 1 / i)) - Bo / 2]
-        }, e) : Re
-    }
-    function Oe(n, t) {
-        function e(n, t) {
-            var e = i - t;
-            return[e * Math.sin(u * n), i - e * Math.cos(u * n)]
-        }
-        var r = Math.cos(n), u = n === t ? Math.sin(n) : (r - Math.cos(t)) / (t - n), i = r / u + n;
-        return Math.abs(u) < $o ? Se : (e.invert = function (n, t) {
-            var e = i - t;
-            return[Math.atan2(n, e) / u, i - F(u) * Math.sqrt(n * n + e * e)]
-        }, e)
-    }
-    function Re(n, t) {
-        return[n, Math.log(Math.tan(Bo / 4 + t / 2))]
-    }
-    function Ye(n) {
-        var t, e = be(n), r = e.scale, u = e.translate, i = 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 = u.apply(e, arguments);
-            return n === e ? t ? e.clipExtent(null) : e : n
-        }, e.clipExtent = function (n) {
-            var o = i.apply(e, arguments);
-            if (o === e) {
-                if (t = null == n) {
-                    var a = Bo * r(), c = u();
-                    i([[c[0] - a, c[1] - a], [c[0] + a, c[1] + a]])
-                }
-            } else
-                t && (o = null);
-            return o
-        }, e.clipExtent(null)
-    }
-    function Ie(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 Ue(n) {
-        function t(t) {
-            function o() {
-                l.push("M", i(n(s), a))
-            }
-            for (var c, l = [], s = [], f = -1, h = t.length, g = pt(e), p = pt(r); ++f < h; )
-                u.call(this, c = t[f], f) ? s.push([+g.call(this, c, f), +p.call(this, c, f)]) : s.length && (o(), s = []);
-            return s.length && o(), l.length ? l.join("") : null
-        }
-        var e = Ve, r = Ze, u = Zt, i = Xe, o = i.key, a = .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 ? (u = n, t) : u
-        }, t.interpolate = function (n) {
-            return arguments.length ? (o = "function" == typeof n ? i = n : (i = fc.get(n) || Xe).key, t) : o
-        }, t.tension = function (n) {
-            return arguments.length ? (a = n, t) : a
-        }, t
-    }
-    function Ve(n) {
-        return n[0]
-    }
-    function Ze(n) {
-        return n[1]
-    }
-    function Xe(n) {
-        return n.join("L")
-    }
-    function Be(n) {
-        return Xe(n) + "Z"
-    }
-    function $e(n) {
-        for (var t = 0, e = n.length, r = n[0], u = [r[0], ",", r[1]]; ++t < e; )
-            u.push("H", (r[0] + (r = n[t])[0]) / 2, "V", r[1]);
-        return e > 1 && u.push("H", r[0]), u.join("")
-    }
-    function We(n) {
-        for (var t = 0, e = n.length, r = n[0], u = [r[0], ",", r[1]]; ++t < e; )
-            u.push("V", (r = n[t])[1], "H", r[0]);
-        return u.join("")
-    }
-    function Je(n) {
-        for (var t = 0, e = n.length, r = n[0], u = [r[0], ",", r[1]]; ++t < e; )
-            u.push("H", (r = n[t])[0], "V", r[1]);
-        return u.join("")
-    }
-    function Ge(n, t) {
-        return n.length < 4 ? Xe(n) : n[1] + nr(n.slice(1, n.length - 1), tr(n, t))
-    }
-    function Ke(n, t) {
-        return n.length < 3 ? Xe(n) : n[0] + nr((n.push(n[0]), n), tr([n[n.length - 2]].concat(n, [n[1]]), t))
-    }
-    function Qe(n, t) {
-        return n.length < 3 ? Xe(n) : n[0] + nr(n, tr(n, t))
-    }
-    function nr(n, t) {
-        if (t.length < 1 || n.length != t.length && n.length != t.length + 2)
-            return Xe(n);
-        var e = n.length != t.length, r = "", u = n[0], i = n[1], o = t[0], a = o, c = 1;
-        if (e && (r += "Q" + (i[0] - 2 * o[0] / 3) + "," + (i[1] - 2 * o[1] / 3) + "," + i[0] + "," + i[1], u = n[1], c = 2), t.length > 1) {
-            a = t[1], i = n[c], c++, r += "C" + (u[0] + o[0]) + "," + (u[1] + o[1]) + "," + (i[0] - a[0]) + "," + (i[1] - a[1]) + "," + i[0] + "," + i[1];
-            for (var l = 2; l < t.length; l++, c++)
-                i = n[c], a = t[l], r += "S" + (i[0] - a[0]) + "," + (i[1] - a[1]) + "," + i[0] + "," + i[1]
-        }
-        if (e) {
-            var s = n[c];
-            r += "Q" + (i[0] + 2 * a[0] / 3) + "," + (i[1] + 2 * a[1] / 3) + "," + s[0] + "," + s[1]
-        }
-        return r
-    }
-    function tr(n, t) {
-        for (var e, r = [], u = (1 - t) / 2, i = n[0], o = n[1], a = 1, c = n.length; ++a < c; )
-            e = i, i = o, o = n[a], r.push([u * (o[0] - e[0]), u * (o[1] - e[1])]);
-        return r
-    }
-    function er(n) {
-        if (n.length < 3)
-            return Xe(n);
-        var t = 1, e = n.length, r = n[0], u = r[0], i = r[1], o = [u, u, u, (r = n[1])[0]], a = [i, i, i, r[1]], c = [u, ",", i, "L", or(pc, o), ",", or(pc, a)];
-        for (n.push(n[e - 1]); ++t <= e; )
-            r = n[t], o.shift(), o.push(r[0]), a.shift(), a.push(r[1]), ar(c, o, a);
-        return n.pop(), c.push("L", r), c.join("")
-    }
-    function rr(n) {
-        if (n.length < 4)
-            return Xe(n);
-        for (var t, e = [], r = -1, u = n.length, i = [0], o = [0]; ++r < 3; )
-            t = n[r], i.push(t[0]), o.push(t[1]);
-        for (e.push(or(pc, i) + "," + or(pc, o)), --r; ++r < u; )
-            t = n[r], i.shift(), i.push(t[0]), o.shift(), o.push(t[1]), ar(e, i, o);
-        return e.join("")
-    }
-    function ur(n) {
-        for (var t, e, r = -1, u = n.length, i = u + 4, o = [], a = []; ++r < 4; )
-            e = n[r % u], o.push(e[0]), a.push(e[1]);
-        for (t = [or(pc, o), ",", or(pc, a)], --r; ++r < i; )
-            e = n[r % u], o.shift(), o.push(e[0]), a.shift(), a.push(e[1]), ar(t, o, a);
-        return t.join("")
-    }
-    function ir(n, t) {
-        var e = n.length - 1;
-        if (e)
-            for (var r, u, i = n[0][0], o = n[0][1], a = n[e][0] - i, c = n[e][1] - o, l = -1; ++l <= e; )
-                r = n[l], u = l / e, r[0] = t * r[0] + (1 - t) * (i + u * a), r[1] = t * r[1] + (1 - t) * (o + u * c);
-        return er(n)
-    }
-    function or(n, t) {
-        return n[0] * t[0] + n[1] * t[1] + n[2] * t[2] + n[3] * t[3]
-    }
-    function ar(n, t, e) {
-        n.push("C", or(hc, t), ",", or(hc, e), ",", or(gc, t), ",", or(gc, e), ",", or(pc, t), ",", or(pc, e))
-    }
-    function cr(n, t) {
-        return(t[1] - n[1]) / (t[0] - n[0])
-    }
-    function lr(n) {
-        for (var t = 0, e = n.length - 1, r = [], u = n[0], i = n[1], o = r[0] = cr(u, i); ++t < e; )
-            r[t] = (o + (o = cr(u = i, i = n[t + 1]))) / 2;
-        return r[t] = o, r
-    }
-    function sr(n) {
-        for (var t, e, r, u, i = [], o = lr(n), a = -1, c = n.length - 1; ++a < c; )
-            t = cr(n[a], n[a + 1]), Math.abs(t) < 1e-6 ? o[a] = o[a + 1] = 0 : (e = o[a] / t, r = o[a + 1] / t, u = e * e + r * r, u > 9 && (u = 3 * t / Math.sqrt(u), o[a] = u * e, o[a + 1] = u * r));
-        for (a = - 1; ++a <= c; )
-            u = (n[Math.min(c, a + 1)][0] - n[Math.max(0, a - 1)][0]) / (6 * (1 + o[a] * o[a])), i.push([u || 0, o[a] * u || 0]);
-        return i
-    }
-    function fr(n) {
-        return n.length < 3 ? Xe(n) : n[0] + nr(n, sr(n))
-    }
-    function hr(n, t, e, r) {
-        var u, i, o, a, c, l, s;
-        return u = r[n], i = u[0], o = u[1], u = r[t], a = u[0], c = u[1], u = r[e], l = u[0], s = u[1], (s - o) * (a - i) - (c - o) * (l - i) > 0
-    }
-    function gr(n, t, e) {
-        return(e[0] - t[0]) * (n[1] - t[1]) < (e[1] - t[1]) * (n[0] - t[0])
-    }
-    function pr(n, t, e, r) {
-        var u = n[0], i = e[0], o = t[0] - u, a = r[0] - i, c = n[1], l = e[1], s = t[1] - c, f = r[1] - l, h = (a * (c - l) - f * (u - i)) / (f * o - a * s);
-        return[u + h * o, c + h * s]
-    }
-    function dr(n) {
-        var t = n[0], e = n[n.length - 1];
-        return!(t[0] - e[0] || t[1] - e[1])
-    }
-    function vr(n, t) {
-        var e = {list: n.map(function (n, t) {
-                return{index: t, x: n[0], y: n[1]}
-            }).sort(function (n, t) {
-                return n.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 && u.rightOf(t, n));
-                return t = t.l
-            }, del: function (n) {
-                n.l.r = n.r, n.r.l = n.l, n.edge = null
-            }, right: function (n) {
-                return n.r
-            }, left: function (n) {
-                return n.l
-            }, leftRegion: function (n) {
-                return null == n.edge ? e.bottomSite : n.edge.region[n.side]
-            }, rightRegion: function (n) {
-                return null == n.edge ? e.bottomSite : n.edge.region[vc[n.side]]
-            }}, u = {bisect: function (n, t) {
-                var e = {region: {l: n, r: t}, ep: {l: null, r: null}}, r = t.x - n.x, u = t.y - n.y, i = r > 0 ? r : -r, o = u > 0 ? u : -u;
-                return e.c = n.x * r + n.y * u + .5 * (r * r + u * u), i > o ? (e.a = 1, e.b = u / r, e.c /= r) : (e.b = 1, e.a = r / u, e.c /= u), e
-            }, intersect: function (n, t) {
-                var e = n.edge, r = t.edge;
-                if (!e || !r || e.region.r == r.region.r)
-                    return null;
-                var u = e.a * r.b - e.b * r.a;
-                if (Math.abs(u) < 1e-10)
-                    return null;
-                var i, o, a = (e.c * r.b - r.c * e.b) / u, c = (r.c * e.a - e.c * r.a) / u, l = e.region.r, s = r.region.r;
-                l.y < s.y || l.y == s.y && l.x < s.x ? (i = n, o = e) : (i = t, o = r);
-                var f = a >= o.region.r.x;
-                return f && "l" === i.side || !f && "r" === i.side ? null : {x: a, y: c}
-            }, rightOf: function (n, t) {
-                var e = n.edge, r = e.region.r, u = t.x > r.x;
-                if (u && "l" === n.side)
-                    return 1;
-                if (!u && "r" === n.side)
-                    return 0;
-                if (1 === e.a) {
-                    var i = t.y - r.y, o = t.x - r.x, a = 0, c = 0;
-                    if (!u && e.b < 0 || u && e.b >= 0 ? c = a = i >= e.b * o : (c = t.x + t.y * e.b > e.c, e.b < 0 && (c = !c), c || (a = 1)), !a) {
-                        var l = r.x - e.region.l.x;
-                        c = e.b * (o * o - i * i) < l * i * (1 + 2 * o / l + e.b * e.b), e.b < 0 && (c = !c)
-                    }
-                } else {
-                    var s = e.c - e.a * t.x, f = t.y - s, h = t.x - r.x, g = s - r.y;
-                    c = f * f > h * h + g * g
-                }
-                return"l" === n.side ? c : !c
-            }, endPoint: function (n, e, r) {
-                n.ep[e] = r, n.ep[vc[e]] && t(n)
-            }, distance: function (n, t) {
-                var e = n.x - t.x, r = n.y - t.y;
-                return Math.sqrt(e * e + r * r)
-            }}, i = {list: [], insert: function (n, t, e) {
-                n.vertex = t, n.ystar = t.y + e;
-                for (var r = 0, u = i.list, o = u.length; o > r; r++) {
-                    var a = u[r];
-                    if (!(n.ystar > a.ystar || n.ystar == a.ystar && t.x > a.vertex.x))
-                        break
-                }
-                u.splice(r, 0, n)
-            }, del: function (n) {
-                for (var t = 0, e = i.list, r = e.length; r > t && e[t] != n; ++t)
-                    ;
-                e.splice(t, 1)
-            }, empty: function () {
-                return 0 === i.list.length
-            }, nextEvent: function (n) {
-                for (var t = 0, e = i.list, r = e.length; r > t; ++t)
-                    if (e[t] == n)
-                        return e[t + 1];
-                return null
-            }, min: function () {
-                var n = i.list[0];
-                return{x: n.vertex.x, y: n.ystar}
-            }, extractMin: function () {
-                return i.list.shift()
-            }};
-        r.init(), e.bottomSite = e.list.shift();
-        for (var o, a, c, l, s, f, h, g, p, d, v, m, y, M = e.list.shift(); ; )
-            if (i.empty() || (o = i.min()), M && (i.empty() || M.y < o.y || M.y == o.y && M.x < o.x))
-                a = r.leftBound(M), c = r.right(a), h = r.rightRegion(a), m = u.bisect(h, M), f = r.createHalfEdge(m, "l"), r.insert(a, f), d = u.intersect(a, f), d && (i.del(a), i.insert(a, d, u.distance(d, M))), a = f, f = r.createHalfEdge(m, "r"), r.insert(a, f), d = u.intersect(f, c), d && i.insert(f, d, u.distance(d, M)), M = e.list.shift();
-            else {
-                if (i.empty())
-                    break;
-                a = i.extractMin(), l = r.left(a), c = r.right(a), s = r.right(c), h = r.leftRegion(a), g = r.rightRegion(c), v = a.vertex, u.endPoint(a.edge, a.side, v), u.endPoint(c.edge, c.side, v), r.del(a), i.del(c), r.del(c), y = "l", h.y > g.y && (p = h, h = g, g = p, y = "r"), m = u.bisect(h, g), f = r.createHalfEdge(m, y), r.insert(l, f), u.endPoint(m, vc[y], v), d = u.intersect(l, f), d && (i.del(l), i.insert(l, d, u.distance(d, h))), d = u.intersect(f, s), d && i.insert(f, d, u.distance(d, h))
-            }
-        for (a = r.right(r.leftEnd); a != r.rightEnd; a = r.right(a))
-            t(a.edge)
-    }
-    function mr(n) {
-        return n.x
-    }
-    function yr(n) {
-        return n.y
-    }
-    function Mr() {
-        return{leaf: !0, nodes: [], point: null, x: null, y: null}
-    }
-    function xr(n, t, e, r, u, i) {
-        if (!n(t, e, r, u, i)) {
-            var o = .5 * (e + u), a = .5 * (r + i), c = t.nodes;
-            c[0] && xr(n, c[0], e, r, o, a), c[1] && xr(n, c[1], o, r, u, a), c[2] && xr(n, c[2], e, a, o, i), c[3] && xr(n, c[3], o, a, u, i)
-        }
-    }
-    function br(n, t) {
-        n = vo.rgb(n), t = vo.rgb(t);
-        var e = n.r, r = n.g, u = n.b, i = t.r - e, o = t.g - r, a = t.b - u;
-        return function (n) {
-            return"#" + ct(Math.round(e + i * n)) + ct(Math.round(r + o * n)) + ct(Math.round(u + a * n))
-        }
-    }
-    function _r(n, t) {
-        var e, r = {}, u = {};
-        for (e in n)
-            e in t ? r[e] = Er(n[e], t[e]) : u[e] = n[e];
-        for (e in t)
-            e in n || (u[e] = t[e]);
-        return function (n) {
-            for (e in r)
-                u[e] = r[e](n);
-            return u
-        }
-    }
-    function wr(n, t) {
-        return t -= n = +n, function (e) {
-            return n + t * e
-        }
-    }
-    function Sr(n, t) {
-        var e, r, u, i, o, a = 0, c = 0, l = [], s = [];
-        for (n += "", t += "", mc.lastIndex = 0, r = 0; e = mc.exec(t); ++r)
-            e.index && l.push(t.substring(a, c = e.index)), s.push({i: l.length, x: e[0]}), l.push(null), a = mc.lastIndex;
-        for (a < t.length && l.push(t.substring(a)), r = 0, i = s.length; (e = mc.exec(n)) && i > r; ++r)
-            if (o = s[r], o.x == e[0]) {
-                if (o.i)
-                    if (null == l[o.i + 1])
-                        for (l[o.i - 1] += o.x, l.splice(o.i, 1), u = r + 1; i > u; ++u)
-                            s[u].i--;
-                    else
-                        for (l[o.i - 1] += o.x + l[o.i + 1], l.splice(o.i, 2), u = r + 1; i > u; ++u)
-                            s[u].i -= 2;
-                else if (null == l[o.i + 1])
-                    l[o.i] = o.x;
-                else
-                    for (l[o.i] = o.x + l[o.i + 1], l.splice(o.i + 1, 1), u = r + 1; i > u; ++u)
-                        s[u].i--;
-                s.splice(r, 1), i--, r--
-            } else
-                o.x = wr(parseFloat(e[0]), parseFloat(o.x));
-        for (; i > r; )
-            o = s.pop(), null == l[o.i + 1] ? l[o.i] = o.x : (l[o.i] = o.x + l[o.i + 1], l.splice(o.i + 1, 1)), i--;
-        return 1 === l.length ? null == l[0] ? (o = s[0].x, function (n) {
-            return o(n) + ""
-        }) : function () {
-            return t
-        } : function (n) {
-            for (r = 0; i > r; ++r)
-                l[(o = s[r]).i] = o.x(n);
-            return l.join("")
-        }
-    }
-    function Er(n, t) {
-        for (var e, r = vo.interpolators.length; --r >= 0 && !(e = vo.interpolators[r](n, t)); )
-            ;
-        return e
-    }
-    function kr(n, t) {
-        var e, r = [], u = [], i = n.length, o = t.length, a = Math.min(n.length, t.length);
-        for (e = 0; a > e; ++e)
-            r.push(Er(n[e], t[e]));
-        for (; i > e; ++e)
-            u[e] = n[e];
-        for (; o > e; ++e)
-            u[e] = t[e];
-        return function (n) {
-            for (e = 0; a > e; ++e)
-                u[e] = r[e](n);
-            return u
-        }
-    }
-    function Ar(n) {
-        return function (t) {
-            return 0 >= t ? 0 : t >= 1 ? 1 : n(t)
-        }
-    }
-    function Nr(n) {
-        return function (t) {
-            return 1 - n(1 - t)
-        }
-    }
-    function qr(n) {
-        return function (t) {
-            return.5 * (.5 > t ? n(2 * t) : 2 - n(2 - 2 * t))
-        }
-    }
-    function Tr(n) {
-        return n * n
-    }
-    function zr(n) {
-        return n * n * n
-    }
-    function Cr(n) {
-        if (0 >= n)
-            return 0;
-        if (n >= 1)
-            return 1;
-        var t = n * n, e = t * n;
-        return 4 * (.5 > n ? e : 3 * (n - t) + e - .75)
-    }
-    function Dr(n) {
-        return function (t) {
-            return Math.pow(t, n)
-        }
-    }
-    function jr(n) {
-        return 1 - Math.cos(n * Bo / 2)
-    }
-    function Lr(n) {
-        return Math.pow(2, 10 * (n - 1))
-    }
-    function Hr(n) {
-        return 1 - Math.sqrt(1 - n * n)
-    }
-    function Fr(n, t) {
-        var e;
-        return arguments.length < 2 && (t = .45), arguments.length ? e = t / (2 * Bo) * Math.asin(1 / n) : (n = 1, e = t / 4), function (r) {
-            return 1 + n * Math.pow(2, 10 * -r) * Math.sin(2 * (r - e) * Bo / t)
-        }
-    }
-    function Pr(n) {
-        return n || (n = 1.70158), function (t) {
-            return t * t * ((n + 1) * t - n)
-        }
-    }
-    function Or(n) {
-        return 1 / 2.75 > n ? 7.5625 * n * n : 2 / 2.75 > n ? 7.5625 * (n -= 1.5 / 2.75) * n + .75 : 2.5 / 2.75 > n ? 7.5625 * (n -= 2.25 / 2.75) * n + .9375 : 7.5625 * (n -= 2.625 / 2.75) * n + .984375
-    }
-    function Rr(n, t) {
-        n = vo.hcl(n), t = vo.hcl(t);
-        var e = n.h, r = n.c, u = n.l, i = t.h - e, o = t.c - r, a = t.l - u;
-        return isNaN(o) && (o = 0, r = isNaN(r) ? t.c : r), isNaN(i) ? (i = 0, e = isNaN(e) ? t.h : e) : i > 180 ? i -= 360 : -180 > i && (i += 360), function (n) {
-            return J(e + i * n, r + o * n, u + a * n) + ""
-        }
-    }
-    function Yr(n, t) {
-        n = vo.hsl(n), t = vo.hsl(t);
-        var e = n.h, r = n.s, u = n.l, i = t.h - e, o = t.s - r, a = t.l - u;
-        return isNaN(o) && (o = 0, r = isNaN(r) ? t.s : r), isNaN(i) ? (i = 0, e = isNaN(e) ? t.h : e) : i > 180 ? i -= 360 : -180 > i && (i += 360), function (n) {
-            return B(e + i * n, r + o * n, u + a * n) + ""
-        }
-    }
-    function Ir(n, t) {
-        n = vo.lab(n), t = vo.lab(t);
-        var e = n.l, r = n.a, u = n.b, i = t.l - e, o = t.a - r, a = t.b - u;
-        return function (n) {
-            return Q(e + i * n, r + o * n, u + a * n) + ""
-        }
-    }
-    function Ur(n, t) {
-        return t -= n, function (e) {
-            return Math.round(n + t * e)
-        }
-    }
-    function Vr(n) {
-        var t = [n.a, n.b], e = [n.c, n.d], r = Xr(t), u = Zr(t, e), i = Xr(Br(e, t, -u)) || 0;
-        t[0] * e[1] < e[0] * t[1] && (t[0] *= -1, t[1] *= -1, r *= -1, u *= -1), this.rotate = (r ? Math.atan2(t[1], t[0]) : Math.atan2(-e[0], e[1])) * Go, this.translate = [n.e, n.f], this.scale = [r, i], this.skew = i ? Math.atan2(u, i) * Go : 0
-    }
-    function Zr(n, t) {
-        return n[0] * t[0] + n[1] * t[1]
-    }
-    function Xr(n) {
-        var t = Math.sqrt(Zr(n, n));
-        return t && (n[0] /= t, n[1] /= t), t
-    }
-    function Br(n, t, e) {
-        return n[0] += e * t[0], n[1] += e * t[1], n
-    }
-    function $r(n, t) {
-        var e, r = [], u = [], i = vo.transform(n), o = vo.transform(t), a = i.translate, c = o.translate, l = i.rotate, s = o.rotate, f = i.skew, h = o.skew, g = i.scale, p = o.scale;
-        return a[0] != c[0] || a[1] != c[1] ? (r.push("translate(", null, ",", null, ")"), u.push({i: 1, x: wr(a[0], c[0])}, {i: 3, x: wr(a[1], c[1])})) : c[0] || c[1] ? r.push("translate(" + c + ")") : r.push(""), l != s ? (l - s > 180 ? s += 360 : s - l > 180 && (l += 360), u.push({i: r.push(r.pop() + "rotate(", null, ")") - 2, x: wr(l, s)})) : s && r.push(r.pop() + "rotate(" + s + ")"), f != h ? u.push({i: r.push(r.pop() + "skewX(", null, ")") - 2, x: wr(f, h)}) : h && r.push(r.pop() + "skewX(" + h + ")"), g[0] != p[0] || g[1] != p[1] ? (e = r.push(r.pop() + "scale(", null, ",", null, ")"), u.push({i: e - 4, x: wr(g[0], p[0])}, {i: e - 2, x: wr(g[1], p[1])})) : (1 != p[0] || 1 != p[1]) && r.push(r.pop() + "scale(" + p + ")"), e = u.length, function (n) {
-            for (var t, i = -1; ++i < e; )
-                r[(t = u[i]).i] = t.x(n);
-            return r.join("")
-        }
-    }
-    function Wr(n, t) {
-        return t = t - (n = +n) ? 1 / (t - n) : 0, function (e) {
-            return(e - n) * t
-        }
-    }
-    function Jr(n, t) {
-        return t = t - (n = +n) ? 1 / (t - n) : 0, function (e) {
-            return Math.max(0, Math.min(1, (e - n) * t))
-        }
-    }
-    function Gr(n) {
-        for (var t = n.source, e = n.target, r = Qr(t, e), u = [t]; t !== r; )
-            t = t.parent, u.push(t);
-        for (var i = u.length; e !== r; )
-            u.splice(i, 0, e), e = e.parent;
-        return u
-    }
-    function Kr(n) {
-        for (var t = [], e = n.parent; null != e; )
-            t.push(n), n = e, e = e.parent;
-        return t.push(n), t
-    }
-    function Qr(n, t) {
-        if (n === t)
-            return n;
-        for (var e = Kr(n), r = Kr(t), u = e.pop(), i = r.pop(), o = null; u === i; )
-            o = u, u = e.pop(), i = r.pop();
-        return o
-    }
-    function nu(n) {
-        n.fixed |= 2
-    }
-    function tu(n) {
-        n.fixed &= -7
-    }
-    function eu(n) {
-        n.fixed |= 4, n.px = n.x, n.py = n.y
-    }
-    function ru(n) {
-        n.fixed &= -5
-    }
-    function uu(n, t, e) {
-        var r = 0, u = 0;
-        if (n.charge = 0, !n.leaf)
-            for (var i, o = n.nodes, a = o.length, c = -1; ++c < a; )
-                i = o[c], null != i && (uu(i, t, e), n.charge += i.charge, r += i.charge * i.cx, u += i.charge * i.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, u += l * n.point.y
-        }
-        n.cx = r / n.charge, n.cy = u / n.charge
-    }
-    function iu(n, t) {
-        return vo.rebind(n, t, "sort", "children", "value"), n.nodes = n, n.links = lu, n
-    }
-    function ou(n) {
-        return n.children
-    }
-    function au(n) {
-        return n.value
-    }
-    function cu(n, t) {
-        return t.value - n.value
-    }
-    function lu(n) {
-        return vo.merge(n.map(function (n) {
-            return(n.children || []).map(function (t) {
-                return{source: n, target: t}
-            })
-        }))
-    }
-    function su(n) {
-        return n.x
-    }
-    function fu(n) {
-        return n.y
-    }
-    function hu(n, t, e) {
-        n.y0 = t, n.y = e
-    }
-    function gu(n) {
-        return vo.range(n.length)
-    }
-    function pu(n) {
-        for (var t = -1, e = n[0].length, r = []; ++t < e; )
-            r[t] = 0;
-        return r
-    }
-    function du(n) {
-        for (var t, e = 1, r = 0, u = n[0][1], i = n.length; i > e; ++e)
-            (t = n[e][1]) > u && (r = e, u = t);
-        return r
-    }
-    function vu(n) {
-        return n.reduce(mu, 0)
-    }
-    function mu(n, t) {
-        return n + t[1]
-    }
-    function yu(n, t) {
-        return Mu(n, Math.ceil(Math.log(t.length) / Math.LN2 + 1))
-    }
-    function Mu(n, t) {
-        for (var e = -1, r = +n[0], u = (n[1] - r) / t, i = []; ++e <= t; )
-            i[e] = u * e + r;
-        return i
-    }
-    function xu(n) {
-        return[vo.min(n), vo.max(n)]
-    }
-    function bu(n, t) {
-        return n.parent == t.parent ? 1 : 2
-    }
-    function _u(n) {
-        var t = n.children;
-        return t && t.length ? t[0] : n._tree.thread
-    }
-    function wu(n) {
-        var t, e = n.children;
-        return e && (t = e.length) ? e[t - 1] : n._tree.thread
-    }
-    function Su(n, t) {
-        var e = n.children;
-        if (e && (u = e.length))
-            for (var r, u, i = -1; ++i < u; )
-                t(r = Su(e[i], t), n) > 0 && (n = r);
-        return n
-    }
-    function Eu(n, t) {
-        return n.x - t.x
-    }
-    function ku(n, t) {
-        return t.x - n.x
-    }
-    function Au(n, t) {
-        return n.depth - t.depth
-    }
-    function Nu(n, t) {
-        function e(n, r) {
-            var u = n.children;
-            if (u && (o = u.length))
-                for (var i, o, a = null, c = -1; ++c < o; )
-                    i = u[c], e(i, a), a = i;
-            t(n, r)
-        }
-        e(n, null)
-    }
-    function qu(n) {
-        for (var t, e = 0, r = 0, u = n.children, i = u.length; --i >= 0; )
-            t = u[i]._tree, t.prelim += e, t.mod += e, e += t.shift + (r += t.change)
-    }
-    function Tu(n, t, e) {
-        n = n._tree, t = t._tree;
-        var r = e / (t.number - n.number);
-        n.change += r, t.change -= r, t.shift += e, t.prelim += e, t.mod += e
-    }
-    function zu(n, t, e) {
-        return n._tree.ancestor.parent == t.parent ? n._tree.ancestor : e
-    }
-    function Cu(n, t) {
-        return n.value - t.value
-    }
-    function Du(n, t) {
-        var e = n._pack_next;
-        n._pack_next = t, t._pack_prev = n, t._pack_next = e, e._pack_prev = t
-    }
-    function ju(n, t) {
-        n._pack_next = t, t._pack_prev = n
-    }
-    function Lu(n, t) {
-        var e = t.x - n.x, r = t.y - n.y, u = n.r + t.r;
-        return.999 * u * u > e * e + r * r
-    }
-    function Hu(n) {
-        function t(n) {
-            s = Math.min(n.x - n.r, s), f = Math.max(n.x + n.r, f), h = Math.min(n.y - n.r, h), g = Math.max(n.y + n.r, g)
-        }
-        if ((e = n.children) && (l = e.length)) {
-            var e, r, u, i, o, a, c, l, s = 1 / 0, f = -1 / 0, h = 1 / 0, g = -1 / 0;
-            if (e.forEach(Fu), r = e[0], r.x = -r.r, r.y = 0, t(r), l > 1 && (u = e[1], u.x = u.r, u.y = 0, t(u), l > 2))
-                for (i = e[2], Ru(r, u, i), t(i), Du(r, i), r._pack_prev = i, Du(i, u), u = r._pack_next, o = 3; l > o; o++) {
-                    Ru(r, u, i = e[o]);
-                    var p = 0, d = 1, v = 1;
-                    for (a = u._pack_next; a !== u; a = a._pack_next, d++)
-                        if (Lu(a, i)) {
-                            p = 1;
-                            break
-                        }
-                    if (1 == p)
-                        for (c = r._pack_prev; c !== a._pack_prev && !Lu(c, i); c = c._pack_prev, v++)
-                            ;
-                    p ? (v > d || d == v && u.r < r.r ? ju(r, u = a) : ju(r = c, u), o--) : (Du(r, i), u = i, t(i))
-                }
-            var m = (s + f) / 2, y = (h + g) / 2, M = 0;
-            for (o = 0; l > o; o++)
-                i = e[o], i.x -= m, i.y -= y, M = Math.max(M, i.r + Math.sqrt(i.x * i.x + i.y * i.y));
-            n.r = M, e.forEach(Pu)
-        }
-    }
-    function Fu(n) {
-        n._pack_next = n._pack_prev = n
-    }
-    function Pu(n) {
-        delete n._pack_next, delete n._pack_prev
-    }
-    function Ou(n, t, e, r) {
-        var u = n.children;
-        if (n.x = t += r * n.x, n.y = e += r * n.y, n.r *= r, u)
-            for (var i = -1, o = u.length; ++i < o; )
-                Ou(u[i], t, e, r)
-    }
-    function Ru(n, t, e) {
-        var r = n.r + e.r, u = t.x - n.x, i = t.y - n.y;
-        if (r && (u || i)) {
-            var o = t.r + e.r, a = u * u + i * i;
-            o *= o, r *= r;
-            var c = .5 + (r - o) / (2 * a), l = Math.sqrt(Math.max(0, 2 * o * (r + a) - (r -= a) * r - o * o)) / (2 * a);
-            e.x = n.x + c * u + l * i, e.y = n.y + c * i - l * u
-        } else
-            e.x = n.x + r, e.y = n.y
-    }
-    function Yu(n) {
-        return 1 + vo.max(n, function (n) {
-            return n.y
-        })
-    }
-    function Iu(n) {
-        return n.reduce(function (n, t) {
-            return n + t.x
-        }, 0) / n.length
-    }
-    function Uu(n) {
-        var t = n.children;
-        return t && t.length ? Uu(t[0]) : n
-    }
-    function Vu(n) {
-        var t, e = n.children;
-        return e && (t = e.length) ? Vu(e[t - 1]) : n
-    }
-    function Zu(n) {
-        return{x: n.x, y: n.y, dx: n.dx, dy: n.dy}
-    }
-    function Xu(n, t) {
-        var e = n.x + t[3], r = n.y + t[0], u = n.dx - t[1] - t[3], i = n.dy - t[0] - t[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 Bu(n) {
-        var t = n[0], e = n[n.length - 1];
-        return e > t ? [t, e] : [e, t]
-    }
-    function $u(n) {
-        return n.rangeExtent ? n.rangeExtent() : Bu(n.range())
-    }
-    function Wu(n, t, e, r) {
-        var u = e(n[0], n[1]), i = r(t[0], t[1]);
-        return function (n) {
-            return i(u(n))
-        }
-    }
-    function Ju(n, t) {
-        var e, r = 0, u = n.length - 1, i = n[r], o = n[u];
-        return i > o && (e = r, r = u, u = e, e = i, i = o, o = e), n[r] = t.floor(i), n[u] = t.ceil(o), n
-    }
-    function Gu(n) {
-        return n ? {floor: function (t) {
-                return Math.floor(t / n) * n
-            }, ceil: function (t) {
-                return Math.ceil(t / n) * n
-            }} : Ac
-    }
-    function Ku(n, t, e, r) {
-        var u = [], i = [], o = 0, a = Math.min(n.length, t.length) - 1;
-        for (n[a] < n[0] && (n = n.slice().reverse(), t = t.slice().reverse()); ++o <= a; )
-            u.push(e(n[o - 1], n[o])), i.push(r(t[o - 1], t[o]));
-        return function (t) {
-            var e = vo.bisect(n, t, 1, a) - 1;
-            return i[e](u[e](t))
-        }
-    }
-    function Qu(n, t, e, r) {
-        function u() {
-            var u = Math.min(n.length, t.length) > 2 ? Ku : Wu, c = r ? Jr : Wr;
-            return o = u(n, t, c, e), a = u(t, n, c, Er), i
-        }
-        function i(n) {
-            return o(n)
-        }
-        var o, a;
-        return i.invert = function (n) {
-            return a(n)
-        }, i.domain = function (t) {
-            return arguments.length ? (n = t.map(Number), u()) : n
-        }, i.range = function (n) {
-            return arguments.length ? (t = n, u()) : t
-        }, i.rangeRound = function (n) {
-            return i.range(n).interpolate(Ur)
-        }, i.clamp = function (n) {
-            return arguments.length ? (r = n, u()) : r
-        }, i.interpolate = function (n) {
-            return arguments.length ? (e = n, u()) : e
-        }, i.ticks = function (t) {
-            return ri(n, t)
-        }, i.tickFormat = function (t, e) {
-            return ui(n, t, e)
-        }, i.nice = function (t) {
-            return ti(n, t), u()
-        }, i.copy = function () {
-            return Qu(n, t, e, r)
-        }, u()
-    }
-    function ni(n, t) {
-        return vo.rebind(n, t, "range", "rangeRound", "interpolate", "clamp")
-    }
-    function ti(n, t) {
-        return Ju(n, Gu(ei(n, t)[2]))
-    }
-    function ei(n, t) {
-        null == t && (t = 10);
-        var e = Bu(n), r = e[1] - e[0], u = Math.pow(10, Math.floor(Math.log(r / t) / Math.LN10)), i = t / r * u;
-        return.15 >= i ? u *= 10 : .35 >= i ? u *= 5 : .75 >= i && (u *= 2), e[0] = Math.ceil(e[0] / u) * u, e[1] = Math.floor(e[1] / u) * u + .5 * u, e[2] = u, e
-    }
-    function ri(n, t) {
-        return vo.range.apply(vo, ei(n, t))
-    }
-    function ui(n, t, e) {
-        var r = -Math.floor(Math.log(ei(n, t)[2]) / Math.LN10 + .01);
-        return vo.format(e ? e.replace(Sa, function (n, t, e, u, i, o, a, c, l, s) {
-            return[t, e, u, i, o, a, c, l || "." + (r - 2 * ("%" === s)), s].join("")
-        }) : ",." + r + "f")
-    }
-    function ii(n, t, e, r) {
-        function u(n) {
-            return(e ? Math.log(0 > n ? 0 : n) : -Math.log(n > 0 ? 0 : -n)) / Math.log(t)
-        }
-        function i(n) {
-            return e ? Math.pow(t, n) : -Math.pow(t, -n)
-        }
-        function o(t) {
-            return n(u(t))
-        }
-        return o.invert = function (t) {
-            return i(n.invert(t))
-        }, o.domain = function (t) {
-            return arguments.length ? (e = t[0] >= 0, n.domain((r = t.map(Number)).map(u)), o) : r
-        }, o.base = function (e) {
-            return arguments.length ? (t = +e, n.domain(r.map(u)), o) : t
-        }, o.nice = function () {
-            var t = Ju(r.map(u), e ? Math : qc);
-            return n.domain(t), r = t.map(i), o
-        }, o.ticks = function () {
-            var n = Bu(r), o = [], a = n[0], c = n[1], l = Math.floor(u(a)), s = Math.ceil(u(c)), f = t % 1 ? 2 : t;
-            if (isFinite(s - l)) {
-                if (e) {
-                    for (; s > l; l++)
-                        for (var h = 1; f > h; h++)
-                            o.push(i(l) * h);
-                    o.push(i(l))
-                } else
-                    for (o.push(i(l)); l++ < s; )
-                        for (var h = f - 1; h > 0; h--)
-                            o.push(i(l) * h);
-                for (l = 0; o[l] < a; l++)
-                    ;
-                for (s = o.length; o[s - 1] > c; s--)
-                    ;
-                o = o.slice(l, s)
-            }
-            return o
-        }, o.tickFormat = function (n, t) {
-            if (!arguments.length)
-                return Nc;
-            arguments.length < 2 ? t = Nc : "function" != typeof t && (t = vo.format(t));
-            var r, a = Math.max(.1, n / o.ticks().length), c = e ? (r = 1e-12, Math.ceil) : (r = -1e-12, Math.floor);
-            return function (n) {
-                return n / i(c(u(n) + r)) <= a ? t(n) : ""
-            }
-        }, o.copy = function () {
-            return ii(n.copy(), t, e, r)
-        }, ni(o, n)
-    }
-    function oi(n, t, e) {
-        function r(t) {
-            return n(u(t))
-        }
-        var u = ai(t), i = ai(1 / t);
-        return r.invert = function (t) {
-            return i(n.invert(t))
-        }, r.domain = function (t) {
-            return arguments.length ? (n.domain((e = t.map(Number)).map(u)), r) : e
-        }, r.ticks = function (n) {
-            return ri(e, n)
-        }, r.tickFormat = function (n, t) {
-            return ui(e, n, t)
-        }, r.nice = function (n) {
-            return r.domain(ti(e, n))
-        }, r.exponent = function (o) {
-            return arguments.length ? (u = ai(t = o), i = ai(1 / t), n.domain(e.map(u)), r) : t
-        }, r.copy = function () {
-            return oi(n.copy(), t, e)
-        }, ni(r, n)
-    }
-    function ai(n) {
-        return function (t) {
-            return 0 > t ? -Math.pow(-t, n) : Math.pow(t, n)
-        }
-    }
-    function ci(n, t) {
-        function e(t) {
-            return o[((i.get(t) || i.set(t, n.push(t))) - 1) % o.length]
-        }
-        function r(t, e) {
-            return vo.range(n.length).map(function (n) {
-                return t + e * n
-            })
-        }
-        var i, o, a;
-        return e.domain = function (r) {
-            if (!arguments.length)
-                return n;
-            n = [], i = new u;
-            for (var o, a = -1, c = r.length; ++a < c; )
-                i.has(o = r[a]) || i.set(o, n.push(o));
-            return e[t.t].apply(e, t.a)
-        }, e.range = function (n) {
-            return arguments.length ? (o = n, a = 0, t = {t: "range", a: arguments}, e) : o
-        }, e.rangePoints = function (u, i) {
-            arguments.length < 2 && (i = 0);
-            var c = u[0], l = u[1], s = (l - c) / (Math.max(1, n.length - 1) + i);
-            return o = r(n.length < 2 ? (c + l) / 2 : c + s * i / 2, s), a = 0, t = {t: "rangePoints", a: arguments}, e
-        }, e.rangeBands = function (u, i, c) {
-            arguments.length < 2 && (i = 0), arguments.length < 3 && (c = i);
-            var l = u[1] < u[0], s = u[l - 0], f = u[1 - l], h = (f - s) / (n.length - i + 2 * c);
-            return o = r(s + h * c, h), l && o.reverse(), a = h * (1 - i), t = {t: "rangeBands", a: arguments}, e
-        }, e.rangeRoundBands = function (u, i, c) {
-            arguments.length < 2 && (i = 0), arguments.length < 3 && (c = i);
-            var l = u[1] < u[0], s = u[l - 0], f = u[1 - l], h = Math.floor((f - s) / (n.length - i + 2 * c)), g = f - s - (n.length - i) * h;
-            return o = r(s + Math.round(g / 2), h), l && o.reverse(), a = Math.round(h * (1 - i)), t = {t: "rangeRoundBands", a: arguments}, e
-        }, e.rangeBand = function () {
-            return a
-        }, e.rangeExtent = function () {
-            return Bu(t.a[0])
-        }, e.copy = function () {
-            return ci(n, t)
-        }, e.domain(n)
-    }
-    function li(n, t) {
-        function e() {
-            var e = 0, i = t.length;
-            for (u = []; ++e < i; )
-                u[e - 1] = vo.quantile(n, e / i);
-            return r
-        }
-        function r(n) {
-            return isNaN(n = +n) ? void 0 : t[vo.bisect(u, n)]
-        }
-        var u;
-        return r.domain = function (t) {
-            return arguments.length ? (n = t.filter(function (n) {
-                return!isNaN(n)
-            }).sort(vo.ascending), e()) : n
-        }, r.range = function (n) {
-            return arguments.length ? (t = n, e()) : t
-        }, r.quantiles = function () {
-            return u
-        }, r.invertExtent = function (e) {
-            return e = t.indexOf(e), 0 > e ? [0 / 0, 0 / 0] : [e > 0 ? u[e - 1] : n[0], e < u.length ? u[e] : n[n.length - 1]]
-        }, r.copy = function () {
-            return li(n, t)
-        }, e()
-    }
-    function si(n, t, e) {
-        function r(t) {
-          

<TRUNCATED>

[21/28] incubator-nifi git commit: NIFI-27: - Latest version of slickgrid.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.dataview.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.dataview.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.dataview.js
index 07f5900..f1c1b5e 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.dataview.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.dataview.js
@@ -1,914 +1,1126 @@
 (function ($) {
-    $.extend(true, window, {
-        Slick: {
-            Data: {
-                DataView: DataView,
-                Aggregators: {
-                    Avg: AvgAggregator,
-                    Min: MinAggregator,
-                    Max: MaxAggregator,
-                    Sum: SumAggregator
-                }
-            }
+  $.extend(true, window, {
+    Slick: {
+      Data: {
+        DataView: DataView,
+        Aggregators: {
+          Avg: AvgAggregator,
+          Min: MinAggregator,
+          Max: MaxAggregator,
+          Sum: SumAggregator
         }
-    });
-
+      }
+    }
+  });
+
+
+  /***
+   * A sample Model implementation.
+   * Provides a filtered view of the underlying data.
+   *
+   * Relies on the data item having an "id" property uniquely identifying it.
+   */
+  function DataView(options) {
+    var self = this;
+
+    var defaults = {
+      groupItemMetadataProvider: null,
+      inlineFilters: false
+    };
+
+
+    // private
+    var idProperty = "id";  // property holding a unique row id
+    var items = [];         // data by index
+    var rows = [];          // data by row
+    var idxById = {};       // indexes by id
+    var rowsById = null;    // rows by id; lazy-calculated
+    var filter = null;      // filter function
+    var updated = null;     // updated item ids
+    var suspend = false;    // suspends the recalculation
+    var sortAsc = true;
+    var fastSortField;
+    var sortComparer;
+    var refreshHints = {};
+    var prevRefreshHints = {};
+    var filterArgs;
+    var filteredItems = [];
+    var compiledFilter;
+    var compiledFilterWithCaching;
+    var filterCache = [];
+
+    // grouping
+    var groupingInfoDefaults = {
+      getter: null,
+      formatter: null,
+      comparer: function(a, b) { return a.value - b.value; },
+      predefinedValues: [],
+      aggregators: [],
+      aggregateEmpty: false,
+      aggregateCollapsed: false,
+      aggregateChildGroups: false,
+      collapsed: false,
+      displayTotalsRow: true,
+      lazyTotalsCalculation: false
+    };
+    var groupingInfos = [];
+    var groups = [];
+    var toggledGroupsByLevel = [];
+    var groupingDelimiter = ':|:';
+
+    var pagesize = 0;
+    var pagenum = 0;
+    var totalRows = 0;
+
+    // events
+    var onRowCountChanged = new Slick.Event();
+    var onRowsChanged = new Slick.Event();
+    var onPagingInfoChanged = new Slick.Event();
+
+    options = $.extend(true, {}, defaults, options);
+
+
+    function beginUpdate() {
+      suspend = true;
+    }
+
+    function endUpdate() {
+      suspend = false;
+      refresh();
+    }
+
+    function setRefreshHints(hints) {
+      refreshHints = hints;
+    }
+
+    function setFilterArgs(args) {
+      filterArgs = args;
+    }
+
+    function updateIdxById(startingIndex) {
+      startingIndex = startingIndex || 0;
+      var id;
+      for (var i = startingIndex, l = items.length; i < l; i++) {
+        id = items[i][idProperty];
+        if (id === undefined) {
+          throw "Each data element must implement a unique 'id' property";
+        }
+        idxById[id] = i;
+      }
+    }
+
+    function ensureIdUniqueness() {
+      var id;
+      for (var i = 0, l = items.length; i < l; i++) {
+        id = items[i][idProperty];
+        if (id === undefined || idxById[id] !== i) {
+          throw "Each data element must implement a unique 'id' property";
+        }
+      }
+    }
+
+    function getItems() {
+      return items;
+    }
+
+    function setItems(data, objectIdProperty) {
+      if (objectIdProperty !== undefined) {
+        idProperty = objectIdProperty;
+      }
+      items = filteredItems = data;
+      idxById = {};
+      updateIdxById();
+      ensureIdUniqueness();
+      refresh();
+    }
+
+    function setPagingOptions(args) {
+      if (args.pageSize != undefined) {
+        pagesize = args.pageSize;
+        pagenum = pagesize ? Math.min(pagenum, Math.max(0, Math.ceil(totalRows / pagesize) - 1)) : 0;
+      }
+
+      if (args.pageNum != undefined) {
+        pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(totalRows / pagesize) - 1));
+      }
+
+      onPagingInfoChanged.notify(getPagingInfo(), null, self);
+
+      refresh();
+    }
+
+    function getPagingInfo() {
+      var totalPages = pagesize ? Math.max(1, Math.ceil(totalRows / pagesize)) : 1;
+      return {pageSize: pagesize, pageNum: pagenum, totalRows: totalRows, totalPages: totalPages};
+    }
+
+    function sort(comparer, ascending) {
+      sortAsc = ascending;
+      sortComparer = comparer;
+      fastSortField = null;
+      if (ascending === false) {
+        items.reverse();
+      }
+      items.sort(comparer);
+      if (ascending === false) {
+        items.reverse();
+      }
+      idxById = {};
+      updateIdxById();
+      refresh();
+    }
 
     /***
-     * A sample Model implementation.
-     * Provides a filtered view of the underlying data.
-     *
-     * Relies on the data item having an "id" property uniquely identifying it.
+     * Provides a workaround for the extremely slow sorting in IE.
+     * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString
+     * to return the value of that field and then doing a native Array.sort().
      */
-    function DataView(options) {
-        var self = this;
-
-        var defaults = {
-            groupItemMetadataProvider: null,
-            inlineFilters: false
-        };
-
-
-        // private
-        var idProperty = "id";  // property holding a unique row id
-        var items = [];         // data by index
-        var rows = [];          // data by row
-        var idxById = {};       // indexes by id
-        var rowsById = null;    // rows by id; lazy-calculated
-        var filter = null;      // filter function
-        var updated = null;     // updated item ids
-        var suspend = false;    // suspends the recalculation
-        var sortAsc = true;
-        var fastSortField;
-        var sortComparer;
-        var refreshHints = {};
-        var prevRefreshHints = {};
-        var filterArgs;
-        var filteredItems = [];
-        var compiledFilter;
-        var compiledFilterWithCaching;
-        var filterCache = [];
-
-        // grouping
-        var groupingGetter;
-        var groupingGetterIsAFn;
-        var groupingFormatter;
-        var groupingComparer;
-        var groups = [];
-        var collapsedGroups = {};
-        var aggregators;
-        var aggregateCollapsed = false;
-        var compiledAccumulators;
-
-        var pagesize = 0;
-        var pagenum = 0;
-        var totalRows = 0;
-
-        // events
-        var onRowCountChanged = new Slick.Event();
-        var onRowsChanged = new Slick.Event();
-        var onPagingInfoChanged = new Slick.Event();
-
-        options = $.extend(true, {}, defaults, options);
-
-
-        function beginUpdate() {
-            suspend = true;
-        }
-
-        function endUpdate() {
-            suspend = false;
-            refresh();
-        }
-
-        function setRefreshHints(hints) {
-            refreshHints = hints;
-        }
-
-        function setFilterArgs(args) {
-            filterArgs = args;
-        }
-
-        function updateIdxById(startingIndex) {
-            startingIndex = startingIndex || 0;
-            var id;
-            for (var i = startingIndex, l = items.length; i < l; i++) {
-                id = items[i][idProperty];
-                if (id === undefined) {
-                    throw "Each data element must implement a unique 'id' property";
-                }
-                idxById[id] = i;
-            }
+    function fastSort(field, ascending) {
+      sortAsc = ascending;
+      fastSortField = field;
+      sortComparer = null;
+      var oldToString = Object.prototype.toString;
+      Object.prototype.toString = (typeof field == "function") ? field : function () {
+        return this[field]
+      };
+      // an extra reversal for descending sort keeps the sort stable
+      // (assuming a stable native sort implementation, which isn't true in some cases)
+      if (ascending === false) {
+        items.reverse();
+      }
+      items.sort();
+      Object.prototype.toString = oldToString;
+      if (ascending === false) {
+        items.reverse();
+      }
+      idxById = {};
+      updateIdxById();
+      refresh();
+    }
+
+    function reSort() {
+      if (sortComparer) {
+        sort(sortComparer, sortAsc);
+      } else if (fastSortField) {
+        fastSort(fastSortField, sortAsc);
+      }
+    }
+
+    function setFilter(filterFn) {
+      filter = filterFn;
+      if (options.inlineFilters) {
+        compiledFilter = compileFilter();
+        compiledFilterWithCaching = compileFilterWithCaching();
+      }
+      refresh();
+    }
+
+    function getGrouping() {
+      return groupingInfos;
+    }
+
+    function setGrouping(groupingInfo) {
+      if (!options.groupItemMetadataProvider) {
+        options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
+      }
+
+      groups = [];
+      toggledGroupsByLevel = [];
+      groupingInfo = groupingInfo || [];
+      groupingInfos = (groupingInfo instanceof Array) ? groupingInfo : [groupingInfo];
+
+      for (var i = 0; i < groupingInfos.length; i++) {
+        var gi = groupingInfos[i] = $.extend(true, {}, groupingInfoDefaults, groupingInfos[i]);
+        gi.getterIsAFn = typeof gi.getter === "function";
+
+        // pre-compile accumulator loops
+        gi.compiledAccumulators = [];
+        var idx = gi.aggregators.length;
+        while (idx--) {
+          gi.compiledAccumulators[idx] = compileAccumulatorLoop(gi.aggregators[idx]);
         }
 
-        function ensureIdUniqueness() {
-            var id;
-            for (var i = 0, l = items.length; i < l; i++) {
-                id = items[i][idProperty];
-                if (id === undefined || idxById[id] !== i) {
-                    throw "Each data element must implement a unique 'id' property";
-                }
-            }
-        }
+        toggledGroupsByLevel[i] = {};
+      }
 
-        function getItems() {
-            return items;
-        }
+      refresh();
+    }
 
-        function setItems(data, objectIdProperty) {
-            if (objectIdProperty !== undefined) {
-                idProperty = objectIdProperty;
-            }
-            items = filteredItems = data;
-            idxById = {};
-            updateIdxById();
-            ensureIdUniqueness();
-            refresh();
+    /**
+     * @deprecated Please use {@link setGrouping}.
+     */
+    function groupBy(valueGetter, valueFormatter, sortComparer) {
+      if (valueGetter == null) {
+        setGrouping([]);
+        return;
+      }
+
+      setGrouping({
+        getter: valueGetter,
+        formatter: valueFormatter,
+        comparer: sortComparer
+      });
+    }
+
+    /**
+     * @deprecated Please use {@link setGrouping}.
+     */
+    function setAggregators(groupAggregators, includeCollapsed) {
+      if (!groupingInfos.length) {
+        throw new Error("At least one grouping must be specified before calling setAggregators().");
+      }
+
+      groupingInfos[0].aggregators = groupAggregators;
+      groupingInfos[0].aggregateCollapsed = includeCollapsed;
+
+      setGrouping(groupingInfos);
+    }
+
+    function getItemByIdx(i) {
+      return items[i];
+    }
+
+    function getIdxById(id) {
+      return idxById[id];
+    }
+
+    function ensureRowsByIdCache() {
+      if (!rowsById) {
+        rowsById = {};
+        for (var i = 0, l = rows.length; i < l; i++) {
+          rowsById[rows[i][idProperty]] = i;
         }
-
-        function setPagingOptions(args) {
-            if (args.pageSize != undefined) {
-                pagesize = args.pageSize;
-                pagenum = pagesize ? Math.min(pagenum, Math.max(0, Math.ceil(totalRows / pagesize) - 1)) : 0;
-            }
-
-            if (args.pageNum != undefined) {
-                pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(totalRows / pagesize) - 1));
-            }
-
-            onPagingInfoChanged.notify(getPagingInfo(), null, self);
-
-            refresh();
+      }
+    }
+
+    function getRowById(id) {
+      ensureRowsByIdCache();
+      return rowsById[id];
+    }
+
+    function getItemById(id) {
+      return items[idxById[id]];
+    }
+
+    function mapIdsToRows(idArray) {
+      var rows = [];
+      ensureRowsByIdCache();
+      for (var i = 0, l = idArray.length; i < l; i++) {
+        var row = rowsById[idArray[i]];
+        if (row != null) {
+          rows[rows.length] = row;
         }
-
-        function getPagingInfo() {
-            var totalPages = pagesize ? Math.max(1, Math.ceil(totalRows / pagesize)) : 1;
-            return {pageSize: pagesize, pageNum: pagenum, totalRows: totalRows, totalPages: totalPages};
+      }
+      return rows;
+    }
+
+    function mapRowsToIds(rowArray) {
+      var ids = [];
+      for (var i = 0, l = rowArray.length; i < l; i++) {
+        if (rowArray[i] < rows.length) {
+          ids[ids.length] = rows[rowArray[i]][idProperty];
         }
-
-        function sort(comparer, ascending) {
-            sortAsc = ascending;
-            sortComparer = comparer;
-            fastSortField = null;
-            if (ascending === false) {
-                items.reverse();
-            }
-            items.sort(comparer);
-            if (ascending === false) {
-                items.reverse();
-            }
-            idxById = {};
-            updateIdxById();
-            refresh();
-        }
-
-        /***
-         * Provides a workaround for the extremely slow sorting in IE.
-         * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString
-         * to return the value of that field and then doing a native Array.sort().
-         */
-        function fastSort(field, ascending) {
-            sortAsc = ascending;
-            fastSortField = field;
-            sortComparer = null;
-            var oldToString = Object.prototype.toString;
-            Object.prototype.toString = (typeof field == "function") ? field : function () {
-                return this[field]
-            };
-            // an extra reversal for descending sort keeps the sort stable
-            // (assuming a stable native sort implementation, which isn't true in some cases)
-            if (ascending === false) {
-                items.reverse();
-            }
-            items.sort();
-            Object.prototype.toString = oldToString;
-            if (ascending === false) {
-                items.reverse();
-            }
-            idxById = {};
-            updateIdxById();
-            refresh();
+      }
+      return ids;
+    }
+
+    function updateItem(id, item) {
+      if (idxById[id] === undefined || id !== item[idProperty]) {
+        throw "Invalid or non-matching id";
+      }
+      items[idxById[id]] = item;
+      if (!updated) {
+        updated = {};
+      }
+      updated[id] = true;
+      refresh();
+    }
+
+    function insertItem(insertBefore, item) {
+      items.splice(insertBefore, 0, item);
+      updateIdxById(insertBefore);
+      refresh();
+    }
+
+    function addItem(item) {
+      items.push(item);
+      updateIdxById(items.length - 1);
+      refresh();
+    }
+
+    function deleteItem(id) {
+      var idx = idxById[id];
+      if (idx === undefined) {
+        throw "Invalid id";
+      }
+      delete idxById[id];
+      items.splice(idx, 1);
+      updateIdxById(idx);
+      refresh();
+    }
+
+    function getLength() {
+      return rows.length;
+    }
+
+    function getItem(i) {
+      var item = rows[i];
+
+      // if this is a group row, make sure totals are calculated and update the title
+      if (item && item.__group && item.totals && !item.totals.initialized) {
+        var gi = groupingInfos[item.level];
+        if (!gi.displayTotalsRow) {
+          calculateTotals(item.totals);
+          item.title = gi.formatter ? gi.formatter(item) : item.value;
         }
-
-        function reSort() {
-            if (sortComparer) {
-                sort(sortComparer, sortAsc);
-            } else if (fastSortField) {
-                fastSort(fastSortField, sortAsc);
-            }
+      }
+      // if this is a totals row, make sure it's calculated
+      else if (item && item.__groupTotals && !item.initialized) {
+        calculateTotals(item);
+      }
+
+      return item;
+    }
+
+    function getItemMetadata(i) {
+      var item = rows[i];
+      if (item === undefined) {
+        return null;
+      }
+
+      // overrides for grouping rows
+      if (item.__group) {
+        return options.groupItemMetadataProvider.getGroupRowMetadata(item);
+      }
+
+      // overrides for totals rows
+      if (item.__groupTotals) {
+        return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
+      }
+
+      return null;
+    }
+
+    function expandCollapseAllGroups(level, collapse) {
+      if (level == null) {
+        for (var i = 0; i < groupingInfos.length; i++) {
+          toggledGroupsByLevel[i] = {};
+          groupingInfos[i].collapsed = collapse;
         }
+      } else {
+        toggledGroupsByLevel[level] = {};
+        groupingInfos[level].collapsed = collapse;
+      }
+      refresh();
+    }
+
+    /**
+     * @param level {Number} Optional level to collapse.  If not specified, applies to all levels.
+     */
+    function collapseAllGroups(level) {
+      expandCollapseAllGroups(level, true);
+    }
 
-        function setFilter(filterFn) {
-            filter = filterFn;
-            if (options.inlineFilters) {
-                compiledFilter = compileFilter();
-                compiledFilterWithCaching = compileFilterWithCaching();
-            }
-            refresh();
+    /**
+     * @param level {Number} Optional level to expand.  If not specified, applies to all levels.
+     */
+    function expandAllGroups(level) {
+      expandCollapseAllGroups(level, false);
+    }
+
+    function expandCollapseGroup(level, groupingKey, collapse) {
+      toggledGroupsByLevel[level][groupingKey] = groupingInfos[level].collapsed ^ collapse;
+      refresh();
+    }
+
+    /**
+     * @param varArgs Either a Slick.Group's "groupingKey" property, or a
+     *     variable argument list of grouping values denoting a unique path to the row.  For
+     *     example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of
+     *     the 'high' group.
+     */
+    function collapseGroup(varArgs) {
+      var args = Array.prototype.slice.call(arguments);
+      var arg0 = args[0];
+      if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
+        expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, true);
+      } else {
+        expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), true);
+      }
+    }
+
+    /**
+     * @param varArgs Either a Slick.Group's "groupingKey" property, or a
+     *     variable argument list of grouping values denoting a unique path to the row.  For
+     *     example, calling expandGroup('high', '10%') will expand the '10%' subgroup of
+     *     the 'high' group.
+     */
+    function expandGroup(varArgs) {
+      var args = Array.prototype.slice.call(arguments);
+      var arg0 = args[0];
+      if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
+        expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, false);
+      } else {
+        expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), false);
+      }
+    }
+
+    function getGroups() {
+      return groups;
+    }
+
+    function extractGroups(rows, parentGroup) {
+      var group;
+      var val;
+      var groups = [];
+      var groupsByVal = {};
+      var r;
+      var level = parentGroup ? parentGroup.level + 1 : 0;
+      var gi = groupingInfos[level];
+
+      for (var i = 0, l = gi.predefinedValues.length; i < l; i++) {
+        val = gi.predefinedValues[i];
+        group = groupsByVal[val];
+        if (!group) {
+          group = new Slick.Group();
+          group.value = val;
+          group.level = level;
+          group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : '') + val;
+          groups[groups.length] = group;
+          groupsByVal[val] = group;
         }
-
-        function groupBy(valueGetter, valueFormatter, sortComparer) {
-            if (!options.groupItemMetadataProvider) {
-                options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
-            }
-
-            groupingGetter = valueGetter;
-            groupingGetterIsAFn = typeof groupingGetter === "function";
-            groupingFormatter = valueFormatter;
-            groupingComparer = sortComparer;
-            collapsedGroups = {};
-            groups = [];
-            refresh();
-        }
-
-        function setAggregators(groupAggregators, includeCollapsed) {
-            aggregators = groupAggregators;
-            aggregateCollapsed = (includeCollapsed !== undefined)
-                    ? includeCollapsed : aggregateCollapsed;
-
-            // pre-compile accumulator loops
-            compiledAccumulators = [];
-            var idx = aggregators.length;
-            while (idx--) {
-                compiledAccumulators[idx] = compileAccumulatorLoop(aggregators[idx]);
-            }
-
-            refresh();
+      }
+
+      for (var i = 0, l = rows.length; i < l; i++) {
+        r = rows[i];
+        val = gi.getterIsAFn ? gi.getter(r) : r[gi.getter];
+        group = groupsByVal[val];
+        if (!group) {
+          group = new Slick.Group();
+          group.value = val;
+          group.level = level;
+          group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : '') + val;
+          groups[groups.length] = group;
+          groupsByVal[val] = group;
         }
 
-        function getItemByIdx(i) {
-            return items[i];
-        }
+        group.rows[group.count++] = r;
+      }
 
-        function getIdxById(id) {
-            return idxById[id];
+      if (level < groupingInfos.length - 1) {
+        for (var i = 0; i < groups.length; i++) {
+          group = groups[i];
+          group.groups = extractGroups(group.rows, group);
         }
-
-        function ensureRowsByIdCache() {
-            if (!rowsById) {
-                rowsById = {};
-                for (var i = 0, l = rows.length; i < l; i++) {
-                    rowsById[rows[i][idProperty]] = i;
-                }
-            }
+      }      
+
+      groups.sort(groupingInfos[level].comparer);
+
+      return groups;
+    }
+
+    function calculateTotals(totals) {
+      var group = totals.group;
+      var gi = groupingInfos[group.level];
+      var isLeafLevel = (group.level == groupingInfos.length);
+      var agg, idx = gi.aggregators.length;
+
+      if (!isLeafLevel && gi.aggregateChildGroups) {
+        // make sure all the subgroups are calculated
+        var i = group.groups.length;
+        while (i--) {
+          if (!group.groups[i].initialized) {
+            calculateTotals(group.groups[i]);
+          }
         }
-
-        function getRowById(id) {
-            ensureRowsByIdCache();
-            return rowsById[id];
+      }
+
+      while (idx--) {
+        agg = gi.aggregators[idx];
+        agg.init();
+        if (!isLeafLevel && gi.aggregateChildGroups) {
+          gi.compiledAccumulators[idx].call(agg, group.groups);
+        } else {
+          gi.compiledAccumulators[idx].call(agg, group.rows);
         }
-
-        function getItemById(id) {
-            return items[idxById[id]];
+        agg.storeResult(totals);
+      }
+      totals.initialized = true;
+    }
+
+    function addGroupTotals(group) {
+      var gi = groupingInfos[group.level];
+      var totals = new Slick.GroupTotals();
+      totals.group = group;
+      group.totals = totals;
+      if (!gi.lazyTotalsCalculation) {
+        calculateTotals(totals);
+      }
+    }
+
+    function addTotals(groups, level) {
+      level = level || 0;
+      var gi = groupingInfos[level];
+      var groupCollapsed = gi.collapsed;
+      var toggledGroups = toggledGroupsByLevel[level];      
+      var idx = groups.length, g;
+      while (idx--) {
+        g = groups[idx];
+
+        if (g.collapsed && !gi.aggregateCollapsed) {
+          continue;
         }
 
-        function mapIdsToRows(idArray) {
-            var rows = [];
-            ensureRowsByIdCache();
-            for (var i = 0; i < idArray.length; i++) {
-                var row = rowsById[idArray[i]];
-                if (row != null) {
-                    rows[rows.length] = row;
-                }
-            }
-            return rows;
+        // Do a depth-first aggregation so that parent group aggregators can access subgroup totals.
+        if (g.groups) {
+          addTotals(g.groups, level + 1);
         }
 
-        function mapRowsToIds(rowArray) {
-            var ids = [];
-            for (var i = 0; i < rowArray.length; i++) {
-                if (rowArray[i] < rows.length) {
-                    ids[ids.length] = rows[rowArray[i]][idProperty];
-                }
-            }
-            return ids;
+        if (gi.aggregators.length && (
+            gi.aggregateEmpty || g.rows.length || (g.groups && g.groups.length))) {
+          addGroupTotals(g);
         }
 
-        function updateItem(id, item) {
-            if (idxById[id] === undefined || id !== item[idProperty]) {
-                throw "Invalid or non-matching id";
-            }
-            items[idxById[id]] = item;
-            if (!updated) {
-                updated = {};
-            }
-            updated[id] = true;
-            refresh();
+        g.collapsed = groupCollapsed ^ toggledGroups[g.groupingKey];
+        g.title = gi.formatter ? gi.formatter(g) : g.value;
+      }
+    } 
+
+    function flattenGroupedRows(groups, level) {
+      level = level || 0;
+      var gi = groupingInfos[level];
+      var groupedRows = [], rows, gl = 0, g;
+      for (var i = 0, l = groups.length; i < l; i++) {
+        g = groups[i];
+        groupedRows[gl++] = g;
+
+        if (!g.collapsed) {
+          rows = g.groups ? flattenGroupedRows(g.groups, level + 1) : g.rows;
+          for (var j = 0, jj = rows.length; j < jj; j++) {
+            groupedRows[gl++] = rows[j];
+          }
         }
 
-        function insertItem(insertBefore, item) {
-            items.splice(insertBefore, 0, item);
-            updateIdxById(insertBefore);
-            refresh();
+        if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) {
+          groupedRows[gl++] = g.totals;
         }
-
-        function addItem(item) {
-            items.push(item);
-            updateIdxById(items.length - 1);
-            refresh();
+      }
+      return groupedRows;
+    }
+
+    function getFunctionInfo(fn) {
+      var fnRegex = /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
+      var matches = fn.toString().match(fnRegex);
+      return {
+        params: matches[1].split(","),
+        body: matches[2]
+      };
+    }
+
+    function compileAccumulatorLoop(aggregator) {
+      var accumulatorInfo = getFunctionInfo(aggregator.accumulate);
+      var fn = new Function(
+          "_items",
+          "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
+              accumulatorInfo.params[0] + " = _items[_i]; " +
+              accumulatorInfo.body +
+          "}"
+      );
+      fn.displayName = fn.name = "compiledAccumulatorLoop";
+      return fn;
+    }
+
+    function compileFilter() {
+      var filterInfo = getFunctionInfo(filter);
+
+      var filterBody = filterInfo.body
+          .replace(/return false\s*([;}]|$)/gi, "{ continue _coreloop; }$1")
+          .replace(/return true\s*([;}]|$)/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }$1")
+          .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
+          "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
+
+      // This preserves the function template code after JS compression,
+      // so that replace() commands still work as expected.
+      var tpl = [
+        //"function(_items, _args) { ",
+        "var _retval = [], _idx = 0; ",
+        "var $item$, $args$ = _args; ",
+        "_coreloop: ",
+        "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
+        "$item$ = _items[_i]; ",
+        "$filter$; ",
+        "} ",
+        "return _retval; "
+        //"}"
+      ].join("");
+      tpl = tpl.replace(/\$filter\$/gi, filterBody);
+      tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
+      tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
+
+      var fn = new Function("_items,_args", tpl);
+      fn.displayName = fn.name = "compiledFilter";
+      return fn;
+    }
+
+    function compileFilterWithCaching() {
+      var filterInfo = getFunctionInfo(filter);
+
+      var filterBody = filterInfo.body
+          .replace(/return false\s*([;}]|$)/gi, "{ continue _coreloop; }$1")
+          .replace(/return true\s*([;}]|$)/gi, "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1")
+          .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
+          "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
+
+      // This preserves the function template code after JS compression,
+      // so that replace() commands still work as expected.
+      var tpl = [
+        //"function(_items, _args, _cache) { ",
+        "var _retval = [], _idx = 0; ",
+        "var $item$, $args$ = _args; ",
+        "_coreloop: ",
+        "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
+        "$item$ = _items[_i]; ",
+        "if (_cache[_i]) { ",
+        "_retval[_idx++] = $item$; ",
+        "continue _coreloop; ",
+        "} ",
+        "$filter$; ",
+        "} ",
+        "return _retval; "
+        //"}"
+      ].join("");
+      tpl = tpl.replace(/\$filter\$/gi, filterBody);
+      tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
+      tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
+
+      var fn = new Function("_items,_args,_cache", tpl);
+      fn.displayName = fn.name = "compiledFilterWithCaching";
+      return fn;
+    }
+
+    function uncompiledFilter(items, args) {
+      var retval = [], idx = 0;
+
+      for (var i = 0, ii = items.length; i < ii; i++) {
+        if (filter(items[i], args)) {
+          retval[idx++] = items[i];
         }
+      }
 
-        function deleteItem(id) {
-            var idx = idxById[id];
-            if (idx === undefined) {
-                throw "Invalid id";
-            }
-            delete idxById[id];
-            items.splice(idx, 1);
-            updateIdxById(idx);
-            refresh();
-        }
+      return retval;
+    }
 
-        function getLength() {
-            return rows.length;
-        }
+    function uncompiledFilterWithCaching(items, args, cache) {
+      var retval = [], idx = 0, item;
 
-        function getItem(i) {
-            return rows[i];
+      for (var i = 0, ii = items.length; i < ii; i++) {
+        item = items[i];
+        if (cache[i]) {
+          retval[idx++] = item;
+        } else if (filter(item, args)) {
+          retval[idx++] = item;
+          cache[i] = true;
         }
-
-        function getItemMetadata(i) {
-            var item = rows[i];
-            if (item === undefined) {
-                return null;
-            }
-
-            // overrides for group rows
-            if (item.__group) {
-                return options.groupItemMetadataProvider.getGroupRowMetadata(item);
-            }
-
-            // overrides for totals rows
-            if (item.__groupTotals) {
-                return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
-            }
-
-            return null;
+      }
+
+      return retval;
+    }
+
+    function getFilteredAndPagedItems(items) {
+      if (filter) {
+        var batchFilter = options.inlineFilters ? compiledFilter : uncompiledFilter;
+        var batchFilterWithCaching = options.inlineFilters ? compiledFilterWithCaching : uncompiledFilterWithCaching;
+
+        if (refreshHints.isFilterNarrowing) {
+          filteredItems = batchFilter(filteredItems, filterArgs);
+        } else if (refreshHints.isFilterExpanding) {
+          filteredItems = batchFilterWithCaching(items, filterArgs, filterCache);
+        } else if (!refreshHints.isFilterUnchanged) {
+          filteredItems = batchFilter(items, filterArgs);
         }
-
-        function collapseGroup(groupingValue) {
-            collapsedGroups[groupingValue] = true;
-            refresh();
+      } else {
+        // special case:  if not filtering and not paging, the resulting
+        // rows collection needs to be a copy so that changes due to sort
+        // can be caught
+        filteredItems = pagesize ? items : items.concat();
+      }
+
+      // get the current page
+      var paged;
+      if (pagesize) {
+        if (filteredItems.length < pagenum * pagesize) {
+          pagenum = Math.floor(filteredItems.length / pagesize);
         }
-
-        function expandGroup(groupingValue) {
-            delete collapsedGroups[groupingValue];
-            refresh();
+        paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
+      } else {
+        paged = filteredItems;
+      }
+
+      return {totalRows: filteredItems.length, rows: paged};
+    }
+
+    function getRowDiffs(rows, newRows) {
+      var item, r, eitherIsNonData, diff = [];
+      var from = 0, to = newRows.length;
+
+      if (refreshHints && refreshHints.ignoreDiffsBefore) {
+        from = Math.max(0,
+            Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
+      }
+
+      if (refreshHints && refreshHints.ignoreDiffsAfter) {
+        to = Math.min(newRows.length,
+            Math.max(0, refreshHints.ignoreDiffsAfter));
+      }
+
+      for (var i = from, rl = rows.length; i < to; i++) {
+        if (i >= rl) {
+          diff[diff.length] = i;
+        } else {
+          item = newRows[i];
+          r = rows[i];
+
+          if ((groupingInfos.length && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
+              item.__group !== r.__group ||
+              item.__group && !item.equals(r))
+              || (eitherIsNonData &&
+              // no good way to compare totals since they are arbitrary DTOs
+              // deep object comparison is pretty expensive
+              // always considering them 'dirty' seems easier for the time being
+              (item.__groupTotals || r.__groupTotals))
+              || item[idProperty] != r[idProperty]
+              || (updated && updated[item[idProperty]])
+              ) {
+            diff[diff.length] = i;
+          }
         }
-
-        function getGroups() {
-            return groups;
+      }
+      return diff;
+    }
+
+    function recalc(_items) {
+      rowsById = null;
+
+      if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
+          refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
+        filterCache = [];
+      }
+
+      var filteredItems = getFilteredAndPagedItems(_items);
+      totalRows = filteredItems.totalRows;
+      var newRows = filteredItems.rows;
+
+      groups = [];
+      if (groupingInfos.length) {
+        groups = extractGroups(newRows);
+        if (groups.length) {
+          addTotals(groups);
+          newRows = flattenGroupedRows(groups);
         }
+      }
 
-        function extractGroups(rows) {
-            var group;
-            var val;
-            var groups = [];
-            var groupsByVal = [];
-            var r;
+      var diff = getRowDiffs(rows, newRows);
 
-            for (var i = 0, l = rows.length; i < l; i++) {
-                r = rows[i];
-                val = (groupingGetterIsAFn) ? groupingGetter(r) : r[groupingGetter];
-                val = val || 0;
-                group = groupsByVal[val];
-                if (!group) {
-                    group = new Slick.Group();
-                    group.count = 0;
-                    group.value = val;
-                    group.rows = [];
-                    groups[groups.length] = group;
-                    groupsByVal[val] = group;
-                }
+      rows = newRows;
 
-                group.rows[group.count++] = r;
-            }
+      return diff;
+    }
 
-            return groups;
-        }
+    function refresh() {
+      if (suspend) {
+        return;
+      }
 
-        // TODO:  lazy totals calculation
-        function calculateGroupTotals(group) {
-            if (group.collapsed && !aggregateCollapsed) {
-                return;
-            }
+      var countBefore = rows.length;
+      var totalRowsBefore = totalRows;
 
-            // TODO:  try moving iterating over groups into compiled accumulator
-            var totals = new Slick.GroupTotals();
-            var agg, idx = aggregators.length;
-            while (idx--) {
-                agg = aggregators[idx];
-                agg.init();
-                compiledAccumulators[idx].call(agg, group.rows);
-                agg.storeResult(totals);
-            }
-            totals.group = group;
-            group.totals = totals;
-        }
+      var diff = recalc(items, filter); // pass as direct refs to avoid closure perf hit
 
-        function calculateTotals(groups) {
-            var idx = groups.length;
-            while (idx--) {
-                calculateGroupTotals(groups[idx]);
-            }
-        }
+      // if the current page is no longer valid, go to last page and recalc
+      // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized
+      if (pagesize && totalRows < pagenum * pagesize) {
+        pagenum = Math.max(0, Math.ceil(totalRows / pagesize) - 1);
+        diff = recalc(items, filter);
+      }
 
-        function finalizeGroups(groups) {
-            var idx = groups.length, g;
-            while (idx--) {
-                g = groups[idx];
-                g.collapsed = (g.value in collapsedGroups);
-                g.title = groupingFormatter ? groupingFormatter(g) : g.value;
-            }
-        }
+      updated = null;
+      prevRefreshHints = refreshHints;
+      refreshHints = {};
 
-        function flattenGroupedRows(groups) {
-            var groupedRows = [], gl = 0, g;
-            for (var i = 0, l = groups.length; i < l; i++) {
-                g = groups[i];
-                groupedRows[gl++] = g;
+      if (totalRowsBefore != totalRows) {
+        onPagingInfoChanged.notify(getPagingInfo(), null, self);
+      }
+      if (countBefore != rows.length) {
+        onRowCountChanged.notify({previous: countBefore, current: rows.length}, null, self);
+      }
+      if (diff.length > 0) {
+        onRowsChanged.notify({rows: diff}, null, self);
+      }
+    }
 
-                if (!g.collapsed) {
-                    for (var j = 0, jj = g.rows.length; j < jj; j++) {
-                        groupedRows[gl++] = g.rows[j];
-                    }
-                }
-
-                if (g.totals && (!g.collapsed || aggregateCollapsed)) {
-                    groupedRows[gl++] = g.totals;
-                }
-            }
-            return groupedRows;
-        }
-
-        function getFunctionInfo(fn) {
-            var fnRegex = /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
-            var matches = fn.toString().match(fnRegex);
-            return {
-                params: matches[1].split(","),
-                body: matches[2]
-            };
-        }
-
-        function compileAccumulatorLoop(aggregator) {
-            var accumulatorInfo = getFunctionInfo(aggregator.accumulate);
-            var fn = new Function(
-                    "_items",
-                    "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
-                    accumulatorInfo.params[0] + " = _items[_i]; " +
-                    accumulatorInfo.body +
-                    "}"
-                    );
-            fn.displayName = fn.name = "compiledAccumulatorLoop";
-            return fn;
-        }
-
-        function compileFilter() {
-            var filterInfo = getFunctionInfo(filter);
-
-            var filterBody = filterInfo.body
-                    .replace(/return false[;}]/gi, "{ continue _coreloop; }")
-                    .replace(/return true[;}]/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }")
-                    .replace(/return ([^;}]+?);/gi,
-                            "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }");
-
-            // This preserves the function template code after JS compression,
-            // so that replace() commands still work as expected.
-            var tpl = [
-                //"function(_items, _args) { ",
-                "var _retval = [], _idx = 0; ",
-                "var $item$, $args$ = _args; ",
-                "_coreloop: ",
-                "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
-                "$item$ = _items[_i]; ",
-                "$filter$; ",
-                "} ",
-                "return _retval; "
-                        //"}"
-            ].join("");
-            tpl = tpl.replace(/\$filter\$/gi, filterBody);
-            tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
-            tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
-
-            var fn = new Function("_items,_args", tpl);
-            fn.displayName = fn.name = "compiledFilter";
-            return fn;
-        }
-
-        function compileFilterWithCaching() {
-            var filterInfo = getFunctionInfo(filter);
-
-            var filterBody = filterInfo.body
-                    .replace(/return false[;}]/gi, "{ continue _coreloop; }")
-                    .replace(/return true[;}]/gi, "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }")
-                    .replace(/return ([^;}]+?);/gi,
-                            "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }");
-
-            // This preserves the function template code after JS compression,
-            // so that replace() commands still work as expected.
-            var tpl = [
-                //"function(_items, _args, _cache) { ",
-                "var _retval = [], _idx = 0; ",
-                "var $item$, $args$ = _args; ",
-                "_coreloop: ",
-                "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
-                "$item$ = _items[_i]; ",
-                "if (_cache[_i]) { ",
-                "_retval[_idx++] = $item$; ",
-                "continue _coreloop; ",
-                "} ",
-                "$filter$; ",
-                "} ",
-                "return _retval; "
-                        //"}"
-            ].join("");
-            tpl = tpl.replace(/\$filter\$/gi, filterBody);
-            tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
-            tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
-
-            var fn = new Function("_items,_args,_cache", tpl);
-            fn.displayName = fn.name = "compiledFilterWithCaching";
-            return fn;
-        }
-
-        function uncompiledFilter(items, args) {
-            var retval = [], idx = 0;
-
-            for (var i = 0, ii = items.length; i < ii; i++) {
-                if (filter(items[i], args)) {
-                    retval[idx++] = items[i];
-                }
-            }
-
-            return retval;
+    /***
+     * Wires the grid and the DataView together to keep row selection tied to item ids.
+     * This is useful since, without it, the grid only knows about rows, so if the items
+     * move around, the same rows stay selected instead of the selection moving along
+     * with the items.
+     *
+     * NOTE:  This doesn't work with cell selection model.
+     *
+     * @param grid {Slick.Grid} The grid to sync selection with.
+     * @param preserveHidden {Boolean} Whether to keep selected items that go out of the
+     *     view due to them getting filtered out.
+     * @param preserveHiddenOnSelectionChange {Boolean} Whether to keep selected items
+     *     that are currently out of the view (see preserveHidden) as selected when selection
+     *     changes.
+     * @return {Slick.Event} An event that notifies when an internal list of selected row ids
+     *     changes.  This is useful since, in combination with the above two options, it allows
+     *     access to the full list selected row ids, and not just the ones visible to the grid.
+     * @method syncGridSelection
+     */
+    function syncGridSelection(grid, preserveHidden, preserveHiddenOnSelectionChange) {
+      var self = this;
+      var inHandler;
+      var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
+      var onSelectedRowIdsChanged = new Slick.Event();
+
+      function setSelectedRowIds(rowIds) {
+        if (selectedRowIds.join(",") == rowIds.join(",")) {
+          return;
         }
 
-        function uncompiledFilterWithCaching(items, args, cache) {
-            var retval = [], idx = 0, item;
-
-            for (var i = 0, ii = items.length; i < ii; i++) {
-                item = items[i];
-                if (cache[i]) {
-                    retval[idx++] = item;
-                } else if (filter(item, args)) {
-                    retval[idx++] = item;
-                    cache[i] = true;
-                }
-            }
+        selectedRowIds = rowIds;
+
+        onSelectedRowIdsChanged.notify({
+          "grid": grid,
+          "ids": selectedRowIds
+        }, new Slick.EventData(), self);
+      }
+
+      function update() {
+        if (selectedRowIds.length > 0) {
+          inHandler = true;
+          var selectedRows = self.mapIdsToRows(selectedRowIds);
+          if (!preserveHidden) {
+            setSelectedRowIds(self.mapRowsToIds(selectedRows));       
+          }
+          grid.setSelectedRows(selectedRows);
+          inHandler = false;
+        }
+      }
+
+      grid.onSelectedRowsChanged.subscribe(function(e, args) {
+        if (inHandler) { return; }
+        var newSelectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
+        if (!preserveHiddenOnSelectionChange || !grid.getOptions().multiSelect) {
+          setSelectedRowIds(newSelectedRowIds);
+        } else {
+          // keep the ones that are hidden
+          var existing = $.grep(selectedRowIds, function(id) { return self.getRowById(id) === undefined; });
+          // add the newly selected ones
+          setSelectedRowIds(existing.concat(newSelectedRowIds));
+        }
+      });
 
-            return retval;
-        }
-
-        function getFilteredAndPagedItems(items) {
-            if (filter) {
-                var batchFilter = options.inlineFilters ? compiledFilter : uncompiledFilter;
-                var batchFilterWithCaching = options.inlineFilters ? compiledFilterWithCaching : uncompiledFilterWithCaching;
-
-                if (refreshHints.isFilterNarrowing) {
-                    filteredItems = batchFilter(filteredItems, filterArgs);
-                } else if (refreshHints.isFilterExpanding) {
-                    filteredItems = batchFilterWithCaching(items, filterArgs, filterCache);
-                } else if (!refreshHints.isFilterUnchanged) {
-                    filteredItems = batchFilter(items, filterArgs);
-                }
-            } else {
-                // special case:  if not filtering and not paging, the resulting
-                // rows collection needs to be a copy so that changes due to sort
-                // can be caught
-                filteredItems = pagesize ? items : items.concat();
-            }
+      this.onRowsChanged.subscribe(update);
 
-            // get the current page
-            var paged;
-            if (pagesize) {
-                if (filteredItems.length < pagenum * pagesize) {
-                    pagenum = Math.floor(filteredItems.length / pagesize);
-                }
-                paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
-            } else {
-                paged = filteredItems;
-            }
+      this.onRowCountChanged.subscribe(update);
 
-            return {totalRows: filteredItems.length, rows: paged};
-        }
+      return onSelectedRowIdsChanged;
+    }
 
-        function getRowDiffs(rows, newRows) {
-            var item, r, eitherIsNonData, diff = [];
-            var from = 0, to = newRows.length;
+    function syncGridCellCssStyles(grid, key) {
+      var hashById;
+      var inHandler;
 
-            if (refreshHints && refreshHints.ignoreDiffsBefore) {
-                from = Math.max(0,
-                        Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
-            }
+      // since this method can be called after the cell styles have been set,
+      // get the existing ones right away
+      storeCellCssStyles(grid.getCellCssStyles(key));
 
-            if (refreshHints && refreshHints.ignoreDiffsAfter) {
-                to = Math.min(newRows.length,
-                        Math.max(0, refreshHints.ignoreDiffsAfter));
+      function storeCellCssStyles(hash) {
+        hashById = {};
+        for (var row in hash) {
+          var id = rows[row][idProperty];
+          hashById[id] = hash[row];
+        }
+      }
+
+      function update() {
+        if (hashById) {
+          inHandler = true;
+          ensureRowsByIdCache();
+          var newHash = {};
+          for (var id in hashById) {
+            var row = rowsById[id];
+            if (row != undefined) {
+              newHash[row] = hashById[id];
             }
+          }
+          grid.setCellCssStyles(key, newHash);
+          inHandler = false;
+        }
+      }
 
-            for (var i = from, rl = rows.length; i < to; i++) {
-                if (i >= rl) {
-                    diff[diff.length] = i;
-                } else {
-                    item = newRows[i];
-                    r = rows[i];
-
-                    if ((groupingGetter && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
-                            item.__group !== r.__group ||
-                            item.__updated ||
-                            item.__group && !item.equals(r))
-                            || (aggregators && eitherIsNonData &&
-                                    // no good way to compare totals since they are arbitrary DTOs
-                                            // deep object comparison is pretty expensive
-                                                    // always considering them 'dirty' seems easier for the time being
-                                                            (item.__groupTotals || r.__groupTotals))
-                                                    || item[idProperty] != r[idProperty]
-                                                    || (updated && updated[item[idProperty]])
-                                                    ) {
-                                        diff[diff.length] = i;
-                                    }
-                                }
-                            }
-                            return diff;
-                        }
-
-                        function recalc(_items) {
-                            rowsById = null;
-
-                            if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
-                                    refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
-                                filterCache = [];
-                            }
-
-                            var filteredItems = getFilteredAndPagedItems(_items);
-                            totalRows = filteredItems.totalRows;
-                            var newRows = filteredItems.rows;
-
-                            groups = [];
-                            if (groupingGetter != null) {
-                                groups = extractGroups(newRows);
-                                if (groups.length) {
-                                    finalizeGroups(groups);
-                                    if (aggregators) {
-                                        calculateTotals(groups);
-                                    }
-                                    groups.sort(groupingComparer);
-                                    newRows = flattenGroupedRows(groups);
-                                }
-                            }
-
-                            var diff = getRowDiffs(rows, newRows);
-
-                            rows = newRows;
-
-                            return diff;
-                        }
-
-                        function refresh() {
-                            if (suspend) {
-                                return;
-                            }
-
-                            var countBefore = rows.length;
-                            var totalRowsBefore = totalRows;
-
-                            var diff = recalc(items, filter); // pass as direct refs to avoid closure perf hit
-
-                            // if the current page is no longer valid, go to last page and recalc
-                            // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized
-                            if (pagesize && totalRows < pagenum * pagesize) {
-                                pagenum = Math.max(0, Math.ceil(totalRows / pagesize) - 1);
-                                diff = recalc(items, filter);
-                            }
-
-                            updated = null;
-                            prevRefreshHints = refreshHints;
-                            refreshHints = {};
-
-                            if (totalRowsBefore != totalRows) {
-                                onPagingInfoChanged.notify(getPagingInfo(), null, self);
-                            }
-                            if (countBefore != rows.length) {
-                                onRowCountChanged.notify({previous: countBefore, current: rows.length}, null, self);
-                            }
-                            if (diff.length > 0) {
-                                onRowsChanged.notify({rows: diff}, null, self);
-                            }
-                        }
-
-                        function syncGridSelection(grid, preserveHidden) {
-                            var self = this;
-                            var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
-                            ;
-                            var inHandler;
-
-                            grid.onSelectedRowsChanged.subscribe(function (e, args) {
-                                if (inHandler) {
-                                    return;
-                                }
-                                selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
-                            });
-
-                            this.onRowsChanged.subscribe(function (e, args) {
-                                if (selectedRowIds.length > 0) {
-                                    inHandler = true;
-                                    var selectedRows = self.mapIdsToRows(selectedRowIds);
-                                    if (!preserveHidden) {
-                                        selectedRowIds = self.mapRowsToIds(selectedRows);
-                                    }
-                                    grid.setSelectedRows(selectedRows);
-                                    inHandler = false;
-                                }
-                            });
-                        }
-
-                        function syncGridCellCssStyles(grid, key) {
-                            var hashById;
-                            var inHandler;
-
-                            // since this method can be called after the cell styles have been set,
-                            // get the existing ones right away
-                            storeCellCssStyles(grid.getCellCssStyles(key));
-
-                            function storeCellCssStyles(hash) {
-                                hashById = {};
-                                for (var row in hash) {
-                                    var id = rows[row][idProperty];
-                                    hashById[id] = hash[row];
-                                }
-                            }
-
-                            grid.onCellCssStylesChanged.subscribe(function (e, args) {
-                                if (inHandler) {
-                                    return;
-                                }
-                                if (key != args.key) {
-                                    return;
-                                }
-                                if (args.hash) {
-                                    storeCellCssStyles(args.hash);
-                                }
-                            });
-
-                            this.onRowsChanged.subscribe(function (e, args) {
-                                if (hashById) {
-                                    inHandler = true;
-                                    ensureRowsByIdCache();
-                                    var newHash = {};
-                                    for (var id in hashById) {
-                                        var row = rowsById[id];
-                                        if (row != undefined) {
-                                            newHash[row] = hashById[id];
-                                        }
-                                    }
-                                    grid.setCellCssStyles(key, newHash);
-                                    inHandler = false;
-                                }
-                            });
-                        }
-
-                        return {
-                            // methods
-                            "beginUpdate": beginUpdate,
-                            "endUpdate": endUpdate,
-                            "setPagingOptions": setPagingOptions,
-                            "getPagingInfo": getPagingInfo,
-                            "getItems": getItems,
-                            "setItems": setItems,
-                            "setFilter": setFilter,
-                            "sort": sort,
-                            "fastSort": fastSort,
-                            "reSort": reSort,
-                            "groupBy": groupBy,
-                            "setAggregators": setAggregators,
-                            "collapseGroup": collapseGroup,
-                            "expandGroup": expandGroup,
-                            "getGroups": getGroups,
-                            "getIdxById": getIdxById,
-                            "getRowById": getRowById,
-                            "getItemById": getItemById,
-                            "getItemByIdx": getItemByIdx,
-                            "mapRowsToIds": mapRowsToIds,
-                            "mapIdsToRows": mapIdsToRows,
-                            "setRefreshHints": setRefreshHints,
-                            "setFilterArgs": setFilterArgs,
-                            "refresh": refresh,
-                            "updateItem": updateItem,
-                            "insertItem": insertItem,
-                            "addItem": addItem,
-                            "deleteItem": deleteItem,
-                            "syncGridSelection": syncGridSelection,
-                            "syncGridCellCssStyles": syncGridCellCssStyles,
-                            // data provider methods
-                            "getLength": getLength,
-                            "getItem": getItem,
-                            "getItemMetadata": getItemMetadata,
-                            // events
-                            "onRowCountChanged": onRowCountChanged,
-                            "onRowsChanged": onRowsChanged,
-                            "onPagingInfoChanged": onPagingInfoChanged
-                        };
-                    }
-
-                    function AvgAggregator(field) {
-                        this.field_ = field;
-
-                        this.init = function () {
-                            this.count_ = 0;
-                            this.nonNullCount_ = 0;
-                            this.sum_ = 0;
-                        };
-
-                        this.accumulate = function (item) {
-                            var val = item[this.field_];
-                            this.count_++;
-                            if (val != null && val != "" && val != NaN) {
-                                this.nonNullCount_++;
-                                this.sum_ += parseFloat(val);
-                            }
-                        };
-
-                        this.storeResult = function (groupTotals) {
-                            if (!groupTotals.avg) {
-                                groupTotals.avg = {};
-                            }
-                            if (this.nonNullCount_ != 0) {
-                                groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
-                            }
-                        };
-                    }
-
-                    function MinAggregator(field) {
-                        this.field_ = field;
-
-                        this.init = function () {
-                            this.min_ = null;
-                        };
-
-                        this.accumulate = function (item) {
-                            var val = item[this.field_];
-                            if (val != null && val != "" && val != NaN) {
-                                if (this.min_ == null || val < this.min_) {
-                                    this.min_ = val;
-                                }
-                            }
-                        };
-
-                        this.storeResult = function (groupTotals) {
-                            if (!groupTotals.min) {
-                                groupTotals.min = {};
-                            }
-                            groupTotals.min[this.field_] = this.min_;
-                        }
-                    }
-
-                    function MaxAggregator(field) {
-                        this.field_ = field;
-
-                        this.init = function () {
-                            this.max_ = null;
-                        };
-
-                        this.accumulate = function (item) {
-                            var val = item[this.field_];
-                            if (val != null && val != "" && val != NaN) {
-                                if (this.max_ == null || val > this.max_) {
-                                    this.max_ = val;
-                                }
-                            }
-                        };
-
-                        this.storeResult = function (groupTotals) {
-                            if (!groupTotals.max) {
-                                groupTotals.max = {};
-                            }
-                            groupTotals.max[this.field_] = this.max_;
-                        }
-                    }
-
-                    function SumAggregator(field) {
-                        this.field_ = field;
-
-                        this.init = function () {
-                            this.sum_ = null;
-                        };
-
-                        this.accumulate = function (item) {
-                            var val = item[this.field_];
-                            if (val != null && val != "" && val != NaN) {
-                                this.sum_ += parseFloat(val);
-                            }
-                        };
-
-                        this.storeResult = function (groupTotals) {
-                            if (!groupTotals.sum) {
-                                groupTotals.sum = {};
-                            }
-                            groupTotals.sum[this.field_] = this.sum_;
-                        }
-                    }
-
-                    // TODO:  add more built-in aggregators
-                    // TODO:  merge common aggregators in one to prevent needles iterating
-
-                })(jQuery);
\ No newline at end of file
+      grid.onCellCssStylesChanged.subscribe(function(e, args) {
+        if (inHandler) { return; }
+        if (key != args.key) { return; }
+        if (args.hash) {
+          storeCellCssStyles(args.hash);
+        }
+      });
+
+      this.onRowsChanged.subscribe(update);
+
+      this.onRowCountChanged.subscribe(update);
+    }
+
+    $.extend(this, {
+      // methods
+      "beginUpdate": beginUpdate,
+      "endUpdate": endUpdate,
+      "setPagingOptions": setPagingOptions,
+      "getPagingInfo": getPagingInfo,
+      "getItems": getItems,
+      "setItems": setItems,
+      "setFilter": setFilter,
+      "sort": sort,
+      "fastSort": fastSort,
+      "reSort": reSort,
+      "setGrouping": setGrouping,
+      "getGrouping": getGrouping,
+      "groupBy": groupBy,
+      "setAggregators": setAggregators,
+      "collapseAllGroups": collapseAllGroups,
+      "expandAllGroups": expandAllGroups,
+      "collapseGroup": collapseGroup,
+      "expandGroup": expandGroup,
+      "getGroups": getGroups,
+      "getIdxById": getIdxById,
+      "getRowById": getRowById,
+      "getItemById": getItemById,
+      "getItemByIdx": getItemByIdx,
+      "mapRowsToIds": mapRowsToIds,
+      "mapIdsToRows": mapIdsToRows,
+      "setRefreshHints": setRefreshHints,
+      "setFilterArgs": setFilterArgs,
+      "refresh": refresh,
+      "updateItem": updateItem,
+      "insertItem": insertItem,
+      "addItem": addItem,
+      "deleteItem": deleteItem,
+      "syncGridSelection": syncGridSelection,
+      "syncGridCellCssStyles": syncGridCellCssStyles,
+
+      // data provider methods
+      "getLength": getLength,
+      "getItem": getItem,
+      "getItemMetadata": getItemMetadata,
+
+      // events
+      "onRowCountChanged": onRowCountChanged,
+      "onRowsChanged": onRowsChanged,
+      "onPagingInfoChanged": onPagingInfoChanged
+    });
+  }
+
+  function AvgAggregator(field) {
+    this.field_ = field;
+
+    this.init = function () {
+      this.count_ = 0;
+      this.nonNullCount_ = 0;
+      this.sum_ = 0;
+    };
+
+    this.accumulate = function (item) {
+      var val = item[this.field_];
+      this.count_++;
+      if (val != null && val !== "" && val !== NaN) {
+        this.nonNullCount_++;
+        this.sum_ += parseFloat(val);
+      }
+    };
+
+    this.storeResult = function (groupTotals) {
+      if (!groupTotals.avg) {
+        groupTotals.avg = {};
+      }
+      if (this.nonNullCount_ != 0) {
+        groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
+      }
+    };
+  }
+
+  function MinAggregator(field) {
+    this.field_ = field;
+
+    this.init = function () {
+      this.min_ = null;
+    };
+
+    this.accumulate = function (item) {
+      var val = item[this.field_];
+      if (val != null && val !== "" && val !== NaN) {
+        if (this.min_ == null || val < this.min_) {
+          this.min_ = val;
+        }
+      }
+    };
+
+    this.storeResult = function (groupTotals) {
+      if (!groupTotals.min) {
+        groupTotals.min = {};
+      }
+      groupTotals.min[this.field_] = this.min_;
+    }
+  }
+
+  function MaxAggregator(field) {
+    this.field_ = field;
+
+    this.init = function () {
+      this.max_ = null;
+    };
+
+    this.accumulate = function (item) {
+      var val = item[this.field_];
+      if (val != null && val !== "" && val !== NaN) {
+        if (this.max_ == null || val > this.max_) {
+          this.max_ = val;
+        }
+      }
+    };
+
+    this.storeResult = function (groupTotals) {
+      if (!groupTotals.max) {
+        groupTotals.max = {};
+      }
+      groupTotals.max[this.field_] = this.max_;
+    }
+  }
+
+  function SumAggregator(field) {
+    this.field_ = field;
+
+    this.init = function () {
+      this.sum_ = null;
+    };
+
+    this.accumulate = function (item) {
+      var val = item[this.field_];
+      if (val != null && val !== "" && val !== NaN) {
+        this.sum_ += parseFloat(val);
+      }
+    };
+
+    this.storeResult = function (groupTotals) {
+      if (!groupTotals.sum) {
+        groupTotals.sum = {};
+      }
+      groupTotals.sum[this.field_] = this.sum_;
+    }
+  }
+
+  // TODO:  add more built-in aggregators
+  // TODO:  merge common aggregators in one to prevent needles iterating
+
+})(jQuery);


[11/28] incubator-nifi git commit: NIFI-54: When incrementing active thread count, if the value exceeds max, do not run

Posted by mc...@apache.org.
NIFI-54: When incrementing active thread count, if the value exceeds max, do not run


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/97f8ab0c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/97f8ab0c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/97f8ab0c

Branch: refs/heads/nifi-27
Commit: 97f8ab0cc50f77a2ff3a4e9d575ec05c185e5b80
Parents: 8254b75
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 11:57:33 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 11:57:33 2014 -0500

----------------------------------------------------------------------
 .../scheduling/EventDrivenSchedulingAgent.java  | 24 ++++++++++++++++++--
 .../controller/scheduling/ScheduleState.java    |  8 +++----
 2 files changed, 26 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/97f8ab0c/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java
index 5b237ff..af801bb 100644
--- a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java
+++ b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java
@@ -263,7 +263,17 @@ public class EventDrivenSchedulingAgent implements SchedulingAgent {
         }
 
         private void trigger(final Connectable worker, final ScheduleState scheduleState, final ConnectableProcessContext processContext, final ProcessSessionFactory sessionFactory) {
-            scheduleState.incrementActiveThreadCount();
+            final int newThreadCount = scheduleState.incrementActiveThreadCount();
+            if (newThreadCount > worker.getMaxConcurrentTasks() && worker.getMaxConcurrentTasks() > 0) {
+                 // its possible that the worker queue could give us a worker node that is eligible to run based
+                 // on the number of threads but another thread has already incremented the thread count, result in
+                 // reaching the maximum number of threads. we won't know this until we atomically increment the thread count 
+                 // on the Schedule State, so we check it here. in this case, we cannot trigger the Processor, as doing so would
+                 // result in using more than the maximum number of defined threads
+                 scheduleState.decrementActiveThreadCount();
+                 return;
+            }
+            
             try {
                 try (final AutoCloseable ncl = NarCloseable.withNarLoader()) {
                     worker.onTrigger(processContext, sessionFactory);
@@ -293,7 +303,17 @@ public class EventDrivenSchedulingAgent implements SchedulingAgent {
         }
 
         private void trigger(final ProcessorNode worker, final ProcessContext context, final ScheduleState scheduleState, final StandardProcessContext processContext, final ProcessSessionFactory sessionFactory) {
-            scheduleState.incrementActiveThreadCount();
+            final int newThreadCount = scheduleState.incrementActiveThreadCount();
+            if (newThreadCount > worker.getMaxConcurrentTasks() && worker.getMaxConcurrentTasks() > 0) {
+                 // its possible that the worker queue could give us a worker node that is eligible to run based
+                 // on the number of threads but another thread has already incremented the thread count, result in
+                 // reaching the maximum number of threads. we won't know this until we atomically increment the thread count 
+                 // on the Schedule State, so we check it here. in this case, we cannot trigger the Processor, as doing so would
+                 // result in using more than the maximum number of defined threads
+                 scheduleState.decrementActiveThreadCount();
+                 return;
+            }
+            
             try {
                 try (final AutoCloseable ncl = NarCloseable.withNarLoader()) {
                     worker.onTrigger(processContext, sessionFactory);

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/97f8ab0c/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/ScheduleState.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/ScheduleState.java b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/ScheduleState.java
index c10de83..eb5a437 100644
--- a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/ScheduleState.java
+++ b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/ScheduleState.java
@@ -31,12 +31,12 @@ public class ScheduleState {
     private final AtomicBoolean mustCallOnStoppedMethods = new AtomicBoolean(false);
     private volatile long lastStopTime = -1;
 
-    public void incrementActiveThreadCount() {
-        activeThreadCount.incrementAndGet();
+    public int incrementActiveThreadCount() {
+        return activeThreadCount.incrementAndGet();
     }
 
-    public void decrementActiveThreadCount() {
-        activeThreadCount.decrementAndGet();
+    public int decrementActiveThreadCount() {
+        return activeThreadCount.decrementAndGet();
     }
 
     public int getActiveThreadCount() {


[06/28] incubator-nifi git commit: NIFI-145: Added run-nifi.bat and fixed bugs

Posted by mc...@apache.org.
NIFI-145: Added run-nifi.bat and fixed bugs


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/6d468297
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/6d468297
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/6d468297

Branch: refs/heads/nifi-27
Commit: 6d46829795196afc797448cc386783fb147c0a7d
Parents: e544191
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 09:23:51 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 09:23:51 2014 -0500

----------------------------------------------------------------------
 .../src/main/resources/bin/run-nifi.bat         |  15 +++
 .../src/main/resources/conf/bootstrap.conf      |   7 ++
 .../java/org/apache/nifi/BootstrapListener.java |  19 ++--
 .../src/main/java/org/apache/nifi/NiFi.java     |  15 ++-
 .../java/org/apache/nifi/bootstrap/RunNiFi.java | 109 ++++++++++++++++---
 .../org/apache/nifi/bootstrap/ShutdownHook.java |  12 +-
 6 files changed, 144 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/6d468297/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat
new file mode 100644
index 0000000..ee00204
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat
@@ -0,0 +1,15 @@
+@echo off
+
+rem Use JAVA_HOME if it's set; otherwise, just use java
+IF "%JAVA_HOME%"=="" (SET JAVA_EXE=java) ELSE (SET JAVA_EXE=%JAVA_HOME%\bin\java.exe)
+
+SET LIB_DIR=%~dp0..\lib
+SET CONF_DIR=%~dp0..\conf
+
+SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
+SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+
+SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
+SET BOOTSTRAP_ACTION=run
+
+cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %BOOTSTRAP_ACTION%

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/6d468297/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf b/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf
index 97d48f8..c45d8f8 100644
--- a/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/conf/bootstrap.conf
@@ -1,7 +1,14 @@
+# Configure where NiFi's lib and conf directories live
 lib.dir=./lib
 conf.dir=./conf
+
+# How long to wait after telling NiFi to shutdown before explicitly killing the Process
+graceful.shutdown.seconds=20
+
+# Disable JSR 199 so that we can use JSP's without running a JDK
 java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true
 
+# JVM memory settings
 java.arg.2=-Xms256m
 java.arg.3=-Xmx512m
 

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/6d468297/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java
index 3bcbeb3..31f336c 100644
--- a/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java
+++ b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java
@@ -24,6 +24,7 @@ import java.io.OutputStream;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.net.SocketTimeoutException;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.concurrent.ExecutorService;
@@ -38,8 +39,8 @@ public class BootstrapListener {
 	private final NiFi nifi;
 	private final int bootstrapPort;
 
-	private Listener listener;
-	private ServerSocket serverSocket;
+	private volatile Listener listener;
+	private volatile ServerSocket serverSocket;
 	
 	
 	public BootstrapListener(final NiFi nifi, final int port) {
@@ -52,12 +53,14 @@ public class BootstrapListener {
 		
 		serverSocket = new ServerSocket();
 		serverSocket.bind(new InetSocketAddress("localhost", 0));
+		serverSocket.setSoTimeout(2000);
 		
 		final int localPort = serverSocket.getLocalPort();
 		logger.info("Started Bootstrap Listener, Listening for incoming requests on port {}", localPort);
 		
 		listener = new Listener(serverSocket);
 		final Thread listenThread = new Thread(listener);
+		listenThread.setDaemon(true);
 		listenThread.setName("Listen to Bootstrap");
 		listenThread.start();
 		
@@ -114,15 +117,17 @@ public class BootstrapListener {
 		
 		@Override
 		public void run() {
-			while (!serverSocket.isClosed()) {
+			while (!stopped) {
 				try {
-					if ( stopped ) {
-						return;
-					}
-					
 					final Socket socket;
 					try {
 						socket = serverSocket.accept();
+					} catch (final SocketTimeoutException ste) {
+						if ( stopped ) {
+							return;
+						}
+						
+						continue;
 					} catch (final IOException ioe) {
 						if ( stopped ) {
 							return;

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/6d468297/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
index bf50a21..13cd4d6 100644
--- a/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
+++ b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
@@ -48,6 +48,7 @@ public class NiFi {
     private final BootstrapListener bootstrapListener;
     
     public static final String BOOTSTRAP_PORT_PROPERTY = "nifi.bootstrap.listen.port";
+    private volatile boolean shutdown = false;
 
     public NiFi(final NiFiProperties properties) throws ClassNotFoundException, IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
         Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@@ -126,13 +127,21 @@ public class NiFi {
         final long startTime = System.nanoTime();
         nifiServer = (NiFiServer) jettyConstructor.newInstance(properties);
         nifiServer.setExtensionMapping(extensionMapping);
-        nifiServer.start();
-        final long endTime = System.nanoTime();
-        logger.info("Controller initialization took " + (endTime - startTime) + " nanoseconds.");
+        
+        if ( shutdown ) {
+        	logger.info("NiFi has been shutdown via NiFi Bootstrap. Will not start Controller");
+        } else {
+	        nifiServer.start();
+	        
+	        final long endTime = System.nanoTime();
+	        logger.info("Controller initialization took " + (endTime - startTime) + " nanoseconds.");
+        }
     }
 
     protected void shutdownHook() {
         try {
+        	this.shutdown = true;
+        	
             logger.info("Initiating shutdown of Jetty web server...");
             if (nifiServer != null) {
                 nifiServer.stop();

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/6d468297/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
index 54932c8..f93500f 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
@@ -57,6 +57,9 @@ public class RunNiFi {
 	public static final String DEFAULT_CONFIG_FILE = "./conf/boostrap.conf";
 	public static final String DEFAULT_NIFI_PROPS_FILE = "./conf/nifi.properties";
 
+	public static final String GRACEFUL_SHUTDOWN_PROP = "graceful.shutdown.seconds";
+	public static final String DEFAULT_GRACEFUL_SHUTDOWN_VALUE = "20";
+	
 	public static final int MAX_RESTART_ATTEMPTS = 5;
 	public static final int STARTUP_WAIT_SECONDS = 60;
 	
@@ -85,6 +88,7 @@ public class RunNiFi {
 		System.out.println("Start : Start a new instance of Apache NiFi");
 		System.out.println("Stop : Stop a running instance of Apache NiFi");
 		System.out.println("Status : Determine if there is a running instance of Apache NiFi");
+		System.out.println("Run : Start a new instance of Apache NiFi and monitor the Process, restarting if the instance dies");
 		System.out.println();
 	}
 	
@@ -96,6 +100,7 @@ public class RunNiFi {
 		
 		switch (args[0].toLowerCase()) {
 			case "start":
+			case "run":
 			case "stop":
 			case "status":
 				break;
@@ -127,7 +132,10 @@ public class RunNiFi {
 		
 		switch (args[0].toLowerCase()) {
 			case "start":
-				runNiFi.start();
+				runNiFi.start(false);
+				break;
+			case "run":
+				runNiFi.start(true);
 				break;
 			case "stop":
 				runNiFi.stop();
@@ -140,8 +148,10 @@ public class RunNiFi {
 	
 	
 	public File getStatusFile() {
-		final File rootDir = bootstrapConfigFile.getParentFile();
-		final File statusFile = new File(rootDir, "nifi.port");
+		final File confDir = bootstrapConfigFile.getParentFile();
+		final File nifiHome = confDir.getParentFile();
+		final File bin = new File(nifiHome, "bin");
+		final File statusFile = new File(bin, "nifi.port");
 		return statusFile;
 	}
 
@@ -165,11 +175,7 @@ public class RunNiFi {
 					return port;
 				}
 			} catch (final IOException ioe) {
-				System.out.println("Found NiFi instance info at " + statusFile + " but information appears to be stale. Removing file.");
-				if ( !statusFile.delete() ) {
-					System.err.println("Unable to remove status file");
-				}
-				
+				System.out.println("Found NiFi instance info at " + statusFile + " indicating that NiFi is running and listening to port " + port + " but unable to communicate with NiFi on that port. The process may have died or may be hung.");
 				throw ioe;
 			}
 		} catch (final Exception e) {
@@ -212,6 +218,11 @@ public class RunNiFi {
 			final String response = reader.readLine();
 			if ( SHUTDOWN_CMD.equals(response) ) {
 				System.out.println("Apache NiFi has accepted the Shutdown Command and is shutting down now");
+				
+				final File statusFile = getStatusFile();
+				if ( !statusFile.delete() ) {
+					System.err.println("Failed to delete status file " + statusFile + "; this file should be cleaned up manually");
+				}
 			} else {
 				System.err.println("When sending SHUTDOWN command to NiFi, got unexpected response " + response);
 			}
@@ -222,8 +233,17 @@ public class RunNiFi {
 	}
 	
 	
+	private boolean isAlive(final Process process) {
+		try {
+			process.exitValue();
+			return false;
+		} catch (final IllegalThreadStateException itse) {
+			return true;
+		}
+	}
+	
 	@SuppressWarnings({ "rawtypes", "unchecked" })
-	public void start() throws IOException, InterruptedException {
+	public void start(final boolean monitor) throws IOException, InterruptedException {
 		final Integer port = getCurrentPort();
 		if ( port != null ) {
 			System.out.println("Apache NiFi is already running, listening on port " + port);
@@ -344,16 +364,71 @@ public class RunNiFi {
 		System.out.println("Working Directory: " + workingDir.getAbsolutePath());
 		System.out.println("Command: " + cmdBuilder.toString());
 		
-		builder.start();
-		boolean started = waitForStart();
-		
-		if ( started ) {
-			System.out.println("Successfully started Apache NiFi");
+		if ( monitor ) {
+			String gracefulShutdown = props.get(GRACEFUL_SHUTDOWN_PROP);
+			if ( gracefulShutdown == null ) {
+				gracefulShutdown = DEFAULT_GRACEFUL_SHUTDOWN_VALUE;
+			}
+
+			final int gracefulShutdownSeconds;
+			try {
+				gracefulShutdownSeconds = Integer.parseInt(gracefulShutdown);
+			} catch (final NumberFormatException nfe) {
+				throw new NumberFormatException("The '" + GRACEFUL_SHUTDOWN_PROP + "' property in Boostrap Config File " + bootstrapConfigAbsoluteFile.getAbsolutePath() + " has an invalid value. Must be a non-negative integer");
+			}
+			
+			if ( gracefulShutdownSeconds < 0 ) {
+				throw new NumberFormatException("The '" + GRACEFUL_SHUTDOWN_PROP + "' property in Boostrap Config File " + bootstrapConfigAbsoluteFile.getAbsolutePath() + " has an invalid value. Must be a non-negative integer");
+			}
+			
+			Process process = builder.start();
+			
+			ShutdownHook shutdownHook = new ShutdownHook(process, this, gracefulShutdownSeconds);
+			final Runtime runtime = Runtime.getRuntime();
+			runtime.addShutdownHook(shutdownHook);
+			
+			while (true) {
+				final boolean alive = isAlive(process);
+				
+				if ( alive ) {
+					try {
+						Thread.sleep(1000L);
+					} catch (final InterruptedException ie) {
+					}
+				} else {
+					runtime.removeShutdownHook(shutdownHook);
+					
+					if (autoRestartNiFi) {
+						System.out.println("Apache NiFi appears to have died. Restarting...");
+						process = builder.start();
+						
+						shutdownHook = new ShutdownHook(process, this, gracefulShutdownSeconds);
+						runtime.addShutdownHook(shutdownHook);
+						
+						final boolean started = waitForStart();
+						
+						if ( started ) {
+							System.out.println("Successfully started Apache NiFi");
+						} else {
+							System.err.println("Apache NiFi does not appear to have started");
+						}
+					} else {
+						return;
+					}
+				}
+			}
 		} else {
-			System.err.println("Apache NiFi does not appear to have started");
+			builder.start();
+			boolean started = waitForStart();
+			
+			if ( started ) {
+				System.out.println("Successfully started Apache NiFi");
+			} else {
+				System.err.println("Apache NiFi does not appear to have started");
+			}
+			
+			listener.stop();
 		}
-		
-		listener.stop();
 	}
 	
 	

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/6d468297/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
index f804c7c..781b690 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
@@ -26,12 +26,12 @@ import java.util.concurrent.TimeUnit;
 public class ShutdownHook extends Thread {
 	private final Process nifiProcess;
 	private final RunNiFi runner;
+	private final int gracefulShutdownSeconds;
 	
-	public static final int WAIT_SECONDS = 10;
-	
-	public ShutdownHook(final Process nifiProcess, final RunNiFi runner) {
+	public ShutdownHook(final Process nifiProcess, final RunNiFi runner, final int gracefulShutdownSeconds) {
 		this.nifiProcess = nifiProcess;
 		this.runner = runner;
+		this.gracefulShutdownSeconds = gracefulShutdownSeconds;
 	}
 	
 	@Override
@@ -58,9 +58,9 @@ public class ShutdownHook extends Thread {
 		while ( isAlive(nifiProcess) ) {
 			final long waitNanos = System.nanoTime() - startWait;
 			final long waitSeconds = TimeUnit.NANOSECONDS.toSeconds(waitNanos);
-			if ( waitSeconds >= WAIT_SECONDS ) {
+			if ( waitSeconds >= gracefulShutdownSeconds && gracefulShutdownSeconds > 0 ) {
 				if ( isAlive(nifiProcess) ) {
-					System.out.println("NiFi has not finished shutting down after " + WAIT_SECONDS + " seconds. Killing process.");
+					System.out.println("NiFi has not finished shutting down after " + gracefulShutdownSeconds + " seconds. Killing process.");
 					nifiProcess.destroy();
 				}
 				break;
@@ -73,7 +73,7 @@ public class ShutdownHook extends Thread {
 		
 		final File statusFile = runner.getStatusFile();
 		if ( !statusFile.delete() ) {
-			System.err.println("Failed to delete status file " + statusFile.getAbsolutePath());
+			System.err.println("Failed to delete status file " + statusFile.getAbsolutePath() + "; this file should be cleaned up manually");
 		}
 	}
 	


[20/28] incubator-nifi git commit: NIFI-27: - Latest version of slickgrid.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.editors.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.editors.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.editors.js
index 2d8a482..04b20d2 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.editors.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.editors.js
@@ -5,508 +5,508 @@
  */
 
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "Editors": {
-                "Text": TextEditor,
-                "Integer": IntegerEditor,
-                "Date": DateEditor,
-                "YesNoSelect": YesNoSelectEditor,
-                "Checkbox": CheckboxEditor,
-                "PercentComplete": PercentCompleteEditor,
-                "LongText": LongTextEditor
-            }
-        }
-    });
-
-    function TextEditor(args) {
-        var $input;
-        var defaultValue;
-        var scope = this;
-
-        this.init = function () {
-            $input = $("<INPUT type=text class='editor-text' />")
-                    .appendTo(args.container)
-                    .bind("keydown.nav", function (e) {
-                        if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
-                            e.stopImmediatePropagation();
-                        }
-                    })
-                    .focus()
-                    .select();
-        };
-
-        this.destroy = function () {
-            $input.remove();
-        };
-
-        this.focus = function () {
-            $input.focus();
-        };
-
-        this.getValue = function () {
-            return $input.val();
-        };
-
-        this.setValue = function (val) {
-            $input.val(val);
-        };
-
-        this.loadValue = function (item) {
-            defaultValue = item[args.column.field] || "";
-            $input.val(defaultValue);
-            $input[0].defaultValue = defaultValue;
-            $input.select();
-        };
-
-        this.serializeValue = function () {
-            return $input.val();
-        };
-
-        this.applyValue = function (item, state) {
-            item[args.column.field] = state;
-        };
-
-        this.isValueChanged = function () {
-            return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-        };
-
-        this.validate = function () {
-            if (args.column.validator) {
-                var validationResults = args.column.validator($input.val());
-                if (!validationResults.valid) {
-                    return validationResults;
-                }
-            }
-
-            return {
-                valid: true,
-                msg: null
-            };
-        };
-
-        this.init();
-    }
-
-    function IntegerEditor(args) {
-        var $input;
-        var defaultValue;
-        var scope = this;
-
-        this.init = function () {
-            $input = $("<INPUT type=text class='editor-text' />");
-
-            $input.bind("keydown.nav", function (e) {
-                if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
-                    e.stopImmediatePropagation();
-                }
-            });
-
-            $input.appendTo(args.container);
-            $input.focus().select();
-        };
-
-        this.destroy = function () {
-            $input.remove();
-        };
-
-        this.focus = function () {
-            $input.focus();
-        };
-
-        this.loadValue = function (item) {
-            defaultValue = item[args.column.field];
-            $input.val(defaultValue);
-            $input[0].defaultValue = defaultValue;
-            $input.select();
-        };
-
-        this.serializeValue = function () {
-            return parseInt($input.val(), 10) || 0;
-        };
-
-        this.applyValue = function (item, state) {
-            item[args.column.field] = state;
-        };
-
-        this.isValueChanged = function () {
-            return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-        };
-
-        this.validate = function () {
-            if (isNaN($input.val())) {
-                return {
-                    valid: false,
-                    msg: "Please enter a valid integer"
-                };
-            }
-
-            return {
-                valid: true,
-                msg: null
-            };
-        };
-
-        this.init();
-    }
-
-    function DateEditor(args) {
-        var $input;
-        var defaultValue;
-        var scope = this;
-        var calendarOpen = false;
-
-        this.init = function () {
-            $input = $("<INPUT type=text class='editor-text' />");
-            $input.appendTo(args.container);
-            $input.focus().select();
-            $input.datepicker({
-                showOn: "button",
-                buttonImageOnly: true,
-                buttonImage: "../images/calendar.gif",
-                beforeShow: function () {
-                    calendarOpen = true
-                },
-                onClose: function () {
-                    calendarOpen = false
-                }
-            });
-            $input.width($input.width() - 18);
-        };
-
-        this.destroy = function () {
-            $.datepicker.dpDiv.stop(true, true);
-            $input.datepicker("hide");
-            $input.datepicker("destroy");
-            $input.remove();
-        };
-
-        this.show = function () {
-            if (calendarOpen) {
-                $.datepicker.dpDiv.stop(true, true).show();
-            }
-        };
-
-        this.hide = function () {
-            if (calendarOpen) {
-                $.datepicker.dpDiv.stop(true, true).hide();
-            }
-        };
-
-        this.position = function (position) {
-            if (!calendarOpen) {
-                return;
-            }
-            $.datepicker.dpDiv
-                    .css("top", position.top + 30)
-                    .css("left", position.left);
-        };
-
-        this.focus = function () {
-            $input.focus();
-        };
-
-        this.loadValue = function (item) {
-            defaultValue = item[args.column.field];
-            $input.val(defaultValue);
-            $input[0].defaultValue = defaultValue;
-            $input.select();
-        };
-
-        this.serializeValue = function () {
-            return $input.val();
-        };
-
-        this.applyValue = function (item, state) {
-            item[args.column.field] = state;
-        };
-
-        this.isValueChanged = function () {
-            return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-        };
-
-        this.validate = function () {
-            return {
-                valid: true,
-                msg: null
-            };
-        };
-
-        this.init();
-    }
-
-    function YesNoSelectEditor(args) {
-        var $select;
-        var defaultValue;
-        var scope = this;
-
-        this.init = function () {
-            $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");
-            $select.appendTo(args.container);
-            $select.focus();
-        };
-
-        this.destroy = function () {
-            $select.remove();
-        };
-
-        this.focus = function () {
-            $select.focus();
-        };
-
-        this.loadValue = function (item) {
-            $select.val((defaultValue = item[args.column.field]) ? "yes" : "no");
-            $select.select();
-        };
-
-        this.serializeValue = function () {
-            return ($select.val() == "yes");
-        };
-
-        this.applyValue = function (item, state) {
-            item[args.column.field] = state;
-        };
-
-        this.isValueChanged = function () {
-            return ($select.val() != defaultValue);
-        };
-
-        this.validate = function () {
-            return {
-                valid: true,
-                msg: null
-            };
-        };
-
-        this.init();
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "Editors": {
+        "Text": TextEditor,
+        "Integer": IntegerEditor,
+        "Date": DateEditor,
+        "YesNoSelect": YesNoSelectEditor,
+        "Checkbox": CheckboxEditor,
+        "PercentComplete": PercentCompleteEditor,
+        "LongText": LongTextEditor
+      }
     }
-
-    function CheckboxEditor(args) {
-        var $select;
-        var defaultValue;
-        var scope = this;
-
-        this.init = function () {
-            $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
-            $select.appendTo(args.container);
-            $select.focus();
-        };
-
-        this.destroy = function () {
-            $select.remove();
-        };
-
-        this.focus = function () {
-            $select.focus();
-        };
-
-        this.loadValue = function (item) {
-            defaultValue = item[args.column.field];
-            if (defaultValue) {
-                $select.attr("checked", "checked");
-            } else {
-                $select.removeAttr("checked");
+  });
+
+  function TextEditor(args) {
+    var $input;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $input = $("<INPUT type=text class='editor-text' />")
+          .appendTo(args.container)
+          .bind("keydown.nav", function (e) {
+            if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
+              e.stopImmediatePropagation();
             }
-        };
-
-        this.serializeValue = function () {
-            return $select.attr("checked");
-        };
-
-        this.applyValue = function (item, state) {
-            item[args.column.field] = state;
-        };
-
-        this.isValueChanged = function () {
-            return ($select.attr("checked") != defaultValue);
-        };
-
-        this.validate = function () {
-            return {
-                valid: true,
-                msg: null
-            };
-        };
-
-        this.init();
-    }
-
-    function PercentCompleteEditor(args) {
-        var $input, $picker;
-        var defaultValue;
-        var scope = this;
-
-        this.init = function () {
-            $input = $("<INPUT type=text class='editor-percentcomplete' />");
-            $input.width($(args.container).innerWidth() - 25);
-            $input.appendTo(args.container);
-
-            $picker = $("<div class='editor-percentcomplete-picker' />").appendTo(args.container);
-            $picker.append("<div class='editor-percentcomplete-helper'><div class='editor-percentcomplete-wrapper'><div class='editor-percentcomplete-slider' /><div class='editor-percentcomplete-buttons' /></div></div>");
-
-            $picker.find(".editor-percentcomplete-buttons").append("<button val=0>Not started</button><br/><button val=50>In Progress</button><br/><button val=100>Complete</button>");
-
-            $input.focus().select();
-
-            $picker.find(".editor-percentcomplete-slider").slider({
-                orientation: "vertical",
-                range: "min",
-                value: defaultValue,
-                slide: function (event, ui) {
-                    $input.val(ui.value)
-                }
-            });
-
-            $picker.find(".editor-percentcomplete-buttons button").bind("click", function (e) {
-                $input.val($(this).attr("val"));
-                $picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val"));
-            })
-        };
-
-        this.destroy = function () {
-            $input.remove();
-            $picker.remove();
-        };
-
-        this.focus = function () {
-            $input.focus();
-        };
-
-        this.loadValue = function (item) {
-            $input.val(defaultValue = item[args.column.field]);
-            $input.select();
-        };
-
-        this.serializeValue = function () {
-            return parseInt($input.val(), 10) || 0;
-        };
-
-        this.applyValue = function (item, state) {
-            item[args.column.field] = state;
-        };
-
-        this.isValueChanged = function () {
-            return (!($input.val() == "" && defaultValue == null)) && ((parseInt($input.val(), 10) || 0) != defaultValue);
-        };
-
-        this.validate = function () {
-            if (isNaN(parseInt($input.val(), 10))) {
-                return {
-                    valid: false,
-                    msg: "Please enter a valid positive number"
-                };
-            }
-
-            return {
-                valid: true,
-                msg: null
-            };
-        };
-
-        this.init();
-    }
-
-    /*
-     * An example of a "detached" editor.
-     * The UI is added onto document BODY and .position(), .show() and .hide() are implemented.
-     * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
-     */
-    function LongTextEditor(args) {
-        var $input, $wrapper;
-        var defaultValue;
-        var scope = this;
-
-        this.init = function () {
-            var $container = $("body");
-
-            $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
-                    .appendTo($container);
-
-            $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
-                    .appendTo($wrapper);
-
-            $("<DIV style='text-align:right'><BUTTON>Save</BUTTON><BUTTON>Cancel</BUTTON></DIV>")
-                    .appendTo($wrapper);
-
-            $wrapper.find("button:first").bind("click", this.save);
-            $wrapper.find("button:last").bind("click", this.cancel);
-            $input.bind("keydown", this.handleKeyDown);
-
-            scope.position(args.position);
-            $input.focus().select();
-        };
-
-        this.handleKeyDown = function (e) {
-            if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
-                scope.save();
-            } else if (e.which == $.ui.keyCode.ESCAPE) {
-                e.preventDefault();
-                scope.cancel();
-            } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
-                e.preventDefault();
-                grid.navigatePrev();
-            } else if (e.which == $.ui.keyCode.TAB) {
-                e.preventDefault();
-                grid.navigateNext();
-            }
-        };
-
-        this.save = function () {
-            args.commitChanges();
-        };
-
-        this.cancel = function () {
-            $input.val(defaultValue);
-            args.cancelChanges();
-        };
-
-        this.hide = function () {
-            $wrapper.hide();
-        };
-
-        this.show = function () {
-            $wrapper.show();
-        };
-
-        this.position = function (position) {
-            $wrapper
-                    .css("top", position.top - 5)
-                    .css("left", position.left - 5)
-        };
-
-        this.destroy = function () {
-            $wrapper.remove();
-        };
-
-        this.focus = function () {
-            $input.focus();
-        };
-
-        this.loadValue = function (item) {
-            $input.val(defaultValue = item[args.column.field]);
-            $input.select();
-        };
+          })
+          .focus()
+          .select();
+    };
+
+    this.destroy = function () {
+      $input.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.getValue = function () {
+      return $input.val();
+    };
+
+    this.setValue = function (val) {
+      $input.val(val);
+    };
+
+    this.loadValue = function (item) {
+      defaultValue = item[args.column.field] || "";
+      $input.val(defaultValue);
+      $input[0].defaultValue = defaultValue;
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (args.column.validator) {
+        var validationResults = args.column.validator($input.val());
+        if (!validationResults.valid) {
+          return validationResults;
+        }
+      }
 
-        this.serializeValue = function () {
-            return $input.val();
-        };
+      return {
+        valid: true,
+        msg: null
+      };
+    };
 
-        this.applyValue = function (item, state) {
-            item[args.column.field] = state;
-        };
+    this.init();
+  }
 
-        this.isValueChanged = function () {
-            return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-        };
+  function IntegerEditor(args) {
+    var $input;
+    var defaultValue;
+    var scope = this;
 
-        this.validate = function () {
-            return {
-                valid: true,
-                msg: null
-            };
-        };
+    this.init = function () {
+      $input = $("<INPUT type=text class='editor-text' />");
 
-        this.init();
-    }
+      $input.bind("keydown.nav", function (e) {
+        if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
+          e.stopImmediatePropagation();
+        }
+      });
+
+      $input.appendTo(args.container);
+      $input.focus().select();
+    };
+
+    this.destroy = function () {
+      $input.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      defaultValue = item[args.column.field];
+      $input.val(defaultValue);
+      $input[0].defaultValue = defaultValue;
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return parseInt($input.val(), 10) || 0;
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (isNaN($input.val())) {
+        return {
+          valid: false,
+          msg: "Please enter a valid integer"
+        };
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  function DateEditor(args) {
+    var $input;
+    var defaultValue;
+    var scope = this;
+    var calendarOpen = false;
+
+    this.init = function () {
+      $input = $("<INPUT type=text class='editor-text' />");
+      $input.appendTo(args.container);
+      $input.focus().select();
+      $input.datepicker({
+        showOn: "button",
+        buttonImageOnly: true,
+        buttonImage: "../images/calendar.gif",
+        beforeShow: function () {
+          calendarOpen = true
+        },
+        onClose: function () {
+          calendarOpen = false
+        }
+      });
+      $input.width($input.width() - 18);
+    };
+
+    this.destroy = function () {
+      $.datepicker.dpDiv.stop(true, true);
+      $input.datepicker("hide");
+      $input.datepicker("destroy");
+      $input.remove();
+    };
+
+    this.show = function () {
+      if (calendarOpen) {
+        $.datepicker.dpDiv.stop(true, true).show();
+      }
+    };
+
+    this.hide = function () {
+      if (calendarOpen) {
+        $.datepicker.dpDiv.stop(true, true).hide();
+      }
+    };
+
+    this.position = function (position) {
+      if (!calendarOpen) {
+        return;
+      }
+      $.datepicker.dpDiv
+          .css("top", position.top + 30)
+          .css("left", position.left);
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      defaultValue = item[args.column.field];
+      $input.val(defaultValue);
+      $input[0].defaultValue = defaultValue;
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  function YesNoSelectEditor(args) {
+    var $select;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");
+      $select.appendTo(args.container);
+      $select.focus();
+    };
+
+    this.destroy = function () {
+      $select.remove();
+    };
+
+    this.focus = function () {
+      $select.focus();
+    };
+
+    this.loadValue = function (item) {
+      $select.val((defaultValue = item[args.column.field]) ? "yes" : "no");
+      $select.select();
+    };
+
+    this.serializeValue = function () {
+      return ($select.val() == "yes");
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return ($select.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  function CheckboxEditor(args) {
+    var $select;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
+      $select.appendTo(args.container);
+      $select.focus();
+    };
+
+    this.destroy = function () {
+      $select.remove();
+    };
+
+    this.focus = function () {
+      $select.focus();
+    };
+
+    this.loadValue = function (item) {
+      defaultValue = !!item[args.column.field];
+      if (defaultValue) {
+        $select.prop('checked', true);
+      } else {
+        $select.prop('checked', false);
+      }
+    };
+
+    this.serializeValue = function () {
+      return $select.prop('checked');
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (this.serializeValue() !== defaultValue);
+    };
+
+    this.validate = function () {
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  function PercentCompleteEditor(args) {
+    var $input, $picker;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $input = $("<INPUT type=text class='editor-percentcomplete' />");
+      $input.width($(args.container).innerWidth() - 25);
+      $input.appendTo(args.container);
+
+      $picker = $("<div class='editor-percentcomplete-picker' />").appendTo(args.container);
+      $picker.append("<div class='editor-percentcomplete-helper'><div class='editor-percentcomplete-wrapper'><div class='editor-percentcomplete-slider' /><div class='editor-percentcomplete-buttons' /></div></div>");
+
+      $picker.find(".editor-percentcomplete-buttons").append("<button val=0>Not started</button><br/><button val=50>In Progress</button><br/><button val=100>Complete</button>");
+
+      $input.focus().select();
+
+      $picker.find(".editor-percentcomplete-slider").slider({
+        orientation: "vertical",
+        range: "min",
+        value: defaultValue,
+        slide: function (event, ui) {
+          $input.val(ui.value)
+        }
+      });
+
+      $picker.find(".editor-percentcomplete-buttons button").bind("click", function (e) {
+        $input.val($(this).attr("val"));
+        $picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val"));
+      })
+    };
+
+    this.destroy = function () {
+      $input.remove();
+      $picker.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      $input.val(defaultValue = item[args.column.field]);
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return parseInt($input.val(), 10) || 0;
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ((parseInt($input.val(), 10) || 0) != defaultValue);
+    };
+
+    this.validate = function () {
+      if (isNaN(parseInt($input.val(), 10))) {
+        return {
+          valid: false,
+          msg: "Please enter a valid positive number"
+        };
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  /*
+   * An example of a "detached" editor.
+   * The UI is added onto document BODY and .position(), .show() and .hide() are implemented.
+   * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
+   */
+  function LongTextEditor(args) {
+    var $input, $wrapper;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      var $container = $("body");
+
+      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
+          .appendTo($container);
+
+      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
+          .appendTo($wrapper);
+
+      $("<DIV style='text-align:right'><BUTTON>Save</BUTTON><BUTTON>Cancel</BUTTON></DIV>")
+          .appendTo($wrapper);
+
+      $wrapper.find("button:first").bind("click", this.save);
+      $wrapper.find("button:last").bind("click", this.cancel);
+      $input.bind("keydown", this.handleKeyDown);
+
+      scope.position(args.position);
+      $input.focus().select();
+    };
+
+    this.handleKeyDown = function (e) {
+      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
+        scope.save();
+      } else if (e.which == $.ui.keyCode.ESCAPE) {
+        e.preventDefault();
+        scope.cancel();
+      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
+        e.preventDefault();
+        args.grid.navigatePrev();
+      } else if (e.which == $.ui.keyCode.TAB) {
+        e.preventDefault();
+        args.grid.navigateNext();
+      }
+    };
+
+    this.save = function () {
+      args.commitChanges();
+    };
+
+    this.cancel = function () {
+      $input.val(defaultValue);
+      args.cancelChanges();
+    };
+
+    this.hide = function () {
+      $wrapper.hide();
+    };
+
+    this.show = function () {
+      $wrapper.show();
+    };
+
+    this.position = function (position) {
+      $wrapper
+          .css("top", position.top - 5)
+          .css("left", position.left - 5)
+    };
+
+    this.destroy = function () {
+      $wrapper.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      $input.val(defaultValue = item[args.column.field]);
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
 })(jQuery);

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.formatters.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.formatters.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.formatters.js
index cc30b8c..a31aaf9 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.formatters.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.formatters.js
@@ -1,55 +1,59 @@
 /***
  * Contains basic SlickGrid formatters.
+ * 
+ * NOTE:  These are merely examples.  You will most likely need to implement something more
+ *        robust/extensible/localizable/etc. for your use!
+ * 
  * @module Formatters
  * @namespace Slick
  */
 
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "Formatters": {
-                "PercentComplete": PercentCompleteFormatter,
-                "PercentCompleteBar": PercentCompleteBarFormatter,
-                "YesNo": YesNoFormatter,
-                "Checkmark": CheckmarkFormatter
-            }
-        }
-    });
-
-    function PercentCompleteFormatter(row, cell, value, columnDef, dataContext) {
-        if (value == null || value === "") {
-            return "-";
-        } else if (value < 50) {
-            return "<span style='color:red;font-weight:bold;'>" + value + "%</span>";
-        } else {
-            return "<span style='color:green'>" + value + "%</span>";
-        }
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "Formatters": {
+        "PercentComplete": PercentCompleteFormatter,
+        "PercentCompleteBar": PercentCompleteBarFormatter,
+        "YesNo": YesNoFormatter,
+        "Checkmark": CheckmarkFormatter
+      }
     }
+  });
+
+  function PercentCompleteFormatter(row, cell, value, columnDef, dataContext) {
+    if (value == null || value === "") {
+      return "-";
+    } else if (value < 50) {
+      return "<span style='color:red;font-weight:bold;'>" + value + "%</span>";
+    } else {
+      return "<span style='color:green'>" + value + "%</span>";
+    }
+  }
 
-    function PercentCompleteBarFormatter(row, cell, value, columnDef, dataContext) {
-        if (value == null || value === "") {
-            return "";
-        }
-
-        var color;
+  function PercentCompleteBarFormatter(row, cell, value, columnDef, dataContext) {
+    if (value == null || value === "") {
+      return "";
+    }
 
-        if (value < 30) {
-            color = "red";
-        } else if (value < 70) {
-            color = "silver";
-        } else {
-            color = "green";
-        }
+    var color;
 
-        return "<span class='percent-complete-bar' style='background:" + color + ";width:" + value + "%'></span>";
+    if (value < 30) {
+      color = "red";
+    } else if (value < 70) {
+      color = "silver";
+    } else {
+      color = "green";
     }
 
-    function YesNoFormatter(row, cell, value, columnDef, dataContext) {
-        return value ? "Yes" : "No";
-    }
+    return "<span class='percent-complete-bar' style='background:" + color + ";width:" + value + "%'></span>";
+  }
 
-    function CheckmarkFormatter(row, cell, value, columnDef, dataContext) {
-        return value ? "<img src='../images/tick.png'>" : "";
-    }
-})(jQuery);
\ No newline at end of file
+  function YesNoFormatter(row, cell, value, columnDef, dataContext) {
+    return value ? "Yes" : "No";
+  }
+
+  function CheckmarkFormatter(row, cell, value, columnDef, dataContext) {
+    return value ? "<img src='../images/tick.png'>" : "";
+  }
+})(jQuery);


[16/28] incubator-nifi git commit: NIFI-27: - Latest version of D3.

Posted by mc...@apache.org.
NIFI-27:
- Latest version of D3.


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/b61a1def
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/b61a1def
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/b61a1def

Branch: refs/heads/nifi-27
Commit: b61a1defa9d9b784491ab802c62381662a5cc719
Parents: 53f4406
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Dec 10 11:26:27 2014 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Wed Dec 10 12:19:26 2014 -0500

----------------------------------------------------------------------
 .../nifi-web-ui/src/main/webapp/js/d3/LICENSE   |   52 +-
 .../nifi-web-ui/src/main/webapp/js/d3/d3.min.js | 5390 +-----------------
 .../src/main/webapp/js/nf/nf-status-history.js  |   62 +-
 3 files changed, 42 insertions(+), 5462 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b61a1def/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/LICENSE
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/LICENSE b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/LICENSE
old mode 100755
new mode 100644
index 83602d5..8301346
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/LICENSE
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/d3/LICENSE
@@ -1,26 +1,26 @@
-Copyright (c) 2013, Michael Bostock
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-* The name Michael Bostock may not be used to endorse or promote products
-  derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c) 2010-2014, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


[24/28] incubator-nifi git commit: NIFI-27: - Latest version of codemirror.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.js
deleted file mode 100755
index a085720..0000000
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror.js
+++ /dev/null
@@ -1,8488 +0,0 @@
-// This is CodeMirror (http://codemirror.net), a code editor
-// implemented in JavaScript on top of the browser's DOM.
-//
-// You can find some technical background for some of the code below
-// at http://marijnhaverbeke.nl/blog/#cm-internals .
-
-(function (mod) {
-    if (typeof exports == "object" && typeof module == "object") // CommonJS
-        module.exports = mod();
-    else if (typeof define == "function" && define.amd) // AMD
-        return define([], mod);
-    else // Plain browser env
-        this.CodeMirror = mod();
-})(function () {
-    "use strict";
-
-    // BROWSER SNIFFING
-
-    // Kludges for bugs and behavior differences that can't be feature
-    // detected are enabled based on userAgent etc sniffing.
-
-    var gecko = /gecko\/\d/i.test(navigator.userAgent);
-    // ie_uptoN means Internet Explorer version N or lower
-    var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
-    var ie_upto7 = ie_upto10 && (document.documentMode == null || document.documentMode < 8);
-    var ie_upto8 = ie_upto10 && (document.documentMode == null || document.documentMode < 9);
-    var ie_upto9 = ie_upto10 && (document.documentMode == null || document.documentMode < 10);
-    var ie_11up = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent);
-    var ie = ie_upto10 || ie_11up;
-    var webkit = /WebKit\//.test(navigator.userAgent);
-    var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
-    var chrome = /Chrome\//.test(navigator.userAgent);
-    var presto = /Opera\//.test(navigator.userAgent);
-    var safari = /Apple Computer/.test(navigator.vendor);
-    var khtml = /KHTML\//.test(navigator.userAgent);
-    var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
-    var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
-    var phantom = /PhantomJS/.test(navigator.userAgent);
-
-    var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
-    // This is woefully incomplete. Suggestions for alternative methods welcome.
-    var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
-    var mac = ios || /Mac/.test(navigator.platform);
-    var windows = /win/i.test(navigator.platform);
-
-    var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
-    if (presto_version)
-        presto_version = Number(presto_version[1]);
-    if (presto_version && presto_version >= 15) {
-        presto = false;
-        webkit = true;
-    }
-    // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
-    var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
-    var captureRightClick = gecko || (ie && !ie_upto8);
-
-    // Optimize some code when these features are not used.
-    var sawReadOnlySpans = false, sawCollapsedSpans = false;
-
-    // EDITOR CONSTRUCTOR
-
-    // A CodeMirror instance represents an editor. This is the object
-    // that user code is usually dealing with.
-
-    function CodeMirror(place, options) {
-        if (!(this instanceof CodeMirror))
-            return new CodeMirror(place, options);
-
-        this.options = options = options || {};
-        // Determine effective options based on given values and defaults.
-        for (var opt in defaults)
-            if (!options.hasOwnProperty(opt))
-                options[opt] = defaults[opt];
-        setGuttersForLineNumbers(options);
-
-        var doc = options.value;
-        if (typeof doc == "string")
-            doc = new Doc(doc, options.mode);
-        this.doc = doc;
-
-        var display = this.display = new Display(place, doc);
-        display.wrapper.CodeMirror = this;
-        updateGutters(this);
-        themeChanged(this);
-        if (options.lineWrapping)
-            this.display.wrapper.className += " CodeMirror-wrap";
-        if (options.autofocus && !mobile)
-            focusInput(this);
-
-        this.state = {
-            keyMaps: [], // stores maps added by addKeyMap
-            overlays: [], // highlighting overlays, as added by addOverlay
-            modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
-            overwrite: false, focused: false,
-            suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
-            pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput
-            draggingText: false,
-            highlight: new Delayed() // stores highlight worker timeout
-        };
-
-        // Override magic textarea content restore that IE sometimes does
-        // on our hidden textarea on reload
-        if (ie_upto10)
-            setTimeout(bind(resetInput, this, true), 20);
-
-        registerEventHandlers(this);
-
-        var cm = this;
-        runInOp(this, function () {
-            cm.curOp.forceUpdate = true;
-            attachDoc(cm, doc);
-
-            if ((options.autofocus && !mobile) || activeElt() == display.input)
-                setTimeout(bind(onFocus, cm), 20);
-            else
-                onBlur(cm);
-
-            for (var opt in optionHandlers)
-                if (optionHandlers.hasOwnProperty(opt))
-                    optionHandlers[opt](cm, options[opt], Init);
-            for (var i = 0; i < initHooks.length; ++i)
-                initHooks[i](cm);
-        });
-    }
-
-    // DISPLAY CONSTRUCTOR
-
-    // The display handles the DOM integration, both for input reading
-    // and content drawing. It holds references to DOM nodes and
-    // display-related state.
-
-    function Display(place, doc) {
-        var d = this;
-
-        // The semihidden textarea that is focused when the editor is
-        // focused, and receives input.
-        var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
-        // The textarea is kept positioned near the cursor to prevent the
-        // fact that it'll be scrolled into view on input from scrolling
-        // our fake cursor out of view. On webkit, when wrap=off, paste is
-        // very slow. So make the area wide instead.
-        if (webkit)
-            input.style.width = "1000px";
-        else
-            input.setAttribute("wrap", "off");
-        // If border: 0; -- iOS fails to open keyboard (issue #1287)
-        if (ios)
-            input.style.border = "1px solid black";
-        input.setAttribute("autocorrect", "off");
-        input.setAttribute("autocapitalize", "off");
-        input.setAttribute("spellcheck", "false");
-
-        // Wraps and hides input textarea
-        d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
-        // The fake scrollbar elements.
-        d.scrollbarH = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
-        d.scrollbarV = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
-        // Covers bottom-right square when both scrollbars are present.
-        d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
-        // Covers bottom of gutter when coverGutterNextToScrollbar is on
-        // and h scrollbar is present.
-        d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
-        // Will contain the actual code, positioned to cover the viewport.
-        d.lineDiv = elt("div", null, "CodeMirror-code");
-        // Elements are added to these to represent selection and cursors.
-        d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
-        d.cursorDiv = elt("div", null, "CodeMirror-cursors");
-        // A visibility: hidden element used to find the size of things.
-        d.measure = elt("div", null, "CodeMirror-measure");
-        // When lines outside of the viewport are measured, they are drawn in this.
-        d.lineMeasure = elt("div", null, "CodeMirror-measure");
-        // Wraps everything that needs to exist inside the vertically-padded coordinate system
-        d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
-                null, "position: relative; outline: none");
-        // Moved around its parent to cover visible view.
-        d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
-        // Set to the height of the document, allowing scrolling.
-        d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
-        // Behavior of elts with overflow: auto and padding is
-        // inconsistent across browsers. This is used to ensure the
-        // scrollable area is big enough.
-        d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
-        // Will contain the gutters, if any.
-        d.gutters = elt("div", null, "CodeMirror-gutters");
-        d.lineGutter = null;
-        // Actual scrollable element.
-        d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
-        d.scroller.setAttribute("tabIndex", "-1");
-        // The element in which the editor lives.
-        d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
-            d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
-
-        // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
-        if (ie_upto7) {
-            d.gutters.style.zIndex = -1;
-            d.scroller.style.paddingRight = 0;
-        }
-        // Needed to hide big blue blinking cursor on Mobile Safari
-        if (ios)
-            input.style.width = "0px";
-        if (!webkit)
-            d.scroller.draggable = true;
-        // Needed to handle Tab key in KHTML
-        if (khtml) {
-            d.inputDiv.style.height = "1px";
-            d.inputDiv.style.position = "absolute";
-        }
-        // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
-        if (ie_upto7)
-            d.scrollbarH.style.minHeight = d.scrollbarV.style.minWidth = "18px";
-
-        if (place.appendChild)
-            place.appendChild(d.wrapper);
-        else
-            place(d.wrapper);
-
-        // Current rendered range (may be bigger than the view window).
-        d.viewFrom = d.viewTo = doc.first;
-        // Information about the rendered lines.
-        d.view = [];
-        // Holds info about a single rendered line when it was rendered
-        // for measurement, while not in view.
-        d.externalMeasured = null;
-        // Empty space (in pixels) above the view
-        d.viewOffset = 0;
-        d.lastSizeC = 0;
-        d.updateLineNumbers = null;
-
-        // Used to only resize the line number gutter when necessary (when
-        // the amount of lines crosses a boundary that makes its width change)
-        d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
-        // See readInput and resetInput
-        d.prevInput = "";
-        // Set to true when a non-horizontal-scrolling line widget is
-        // added. As an optimization, line widget aligning is skipped when
-        // this is false.
-        d.alignWidgets = false;
-        // Flag that indicates whether we expect input to appear real soon
-        // now (after some event like 'keypress' or 'input') and are
-        // polling intensively.
-        d.pollingFast = false;
-        // Self-resetting timeout for the poller
-        d.poll = new Delayed();
-
-        d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
-
-        // Tracks when resetInput has punted to just putting a short
-        // string into the textarea instead of the full selection.
-        d.inaccurateSelection = false;
-
-        // Tracks the maximum line length so that the horizontal scrollbar
-        // can be kept static when scrolling.
-        d.maxLine = null;
-        d.maxLineLength = 0;
-        d.maxLineChanged = false;
-
-        // Used for measuring wheel scrolling granularity
-        d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
-
-        // True when shift is held down.
-        d.shift = false;
-    }
-
-    // STATE UPDATES
-
-    // Used to get the editor into a consistent state again when options change.
-
-    function loadMode(cm) {
-        cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
-        resetModeState(cm);
-    }
-
-    function resetModeState(cm) {
-        cm.doc.iter(function (line) {
-            if (line.stateAfter)
-                line.stateAfter = null;
-            if (line.styles)
-                line.styles = null;
-        });
-        cm.doc.frontier = cm.doc.first;
-        startWorker(cm, 100);
-        cm.state.modeGen++;
-        if (cm.curOp)
-            regChange(cm);
-    }
-
-    function wrappingChanged(cm) {
-        if (cm.options.lineWrapping) {
-            cm.display.wrapper.className += " CodeMirror-wrap";
-            cm.display.sizer.style.minWidth = "";
-        } else {
-            cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
-            findMaxLine(cm);
-        }
-        estimateLineHeights(cm);
-        regChange(cm);
-        clearCaches(cm);
-        setTimeout(function () {
-            updateScrollbars(cm);
-        }, 100);
-    }
-
-    // Returns a function that estimates the height of a line, to use as
-    // first approximation until the line becomes visible (and is thus
-    // properly measurable).
-    function estimateHeight(cm) {
-        var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
-        var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
-        return function (line) {
-            if (lineIsHidden(cm.doc, line))
-                return 0;
-
-            var widgetsHeight = 0;
-            if (line.widgets)
-                for (var i = 0; i < line.widgets.length; i++) {
-                    if (line.widgets[i].height)
-                        widgetsHeight += line.widgets[i].height;
-                }
-
-            if (wrapping)
-                return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
-            else
-                return widgetsHeight + th;
-        };
-    }
-
-    function estimateLineHeights(cm) {
-        var doc = cm.doc, est = estimateHeight(cm);
-        doc.iter(function (line) {
-            var estHeight = est(line);
-            if (estHeight != line.height)
-                updateLineHeight(line, estHeight);
-        });
-    }
-
-    function keyMapChanged(cm) {
-        var map = keyMap[cm.options.keyMap], style = map.style;
-        cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
-                (style ? " cm-keymap-" + style : "");
-    }
-
-    function themeChanged(cm) {
-        cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
-                cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
-        clearCaches(cm);
-    }
-
-    function guttersChanged(cm) {
-        updateGutters(cm);
-        regChange(cm);
-        setTimeout(function () {
-            alignHorizontally(cm);
-        }, 20);
-    }
-
-    // Rebuild the gutter elements, ensure the margin to the left of the
-    // code matches their width.
-    function updateGutters(cm) {
-        var gutters = cm.display.gutters, specs = cm.options.gutters;
-        removeChildren(gutters);
-        for (var i = 0; i < specs.length; ++i) {
-            var gutterClass = specs[i];
-            var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
-            if (gutterClass == "CodeMirror-linenumbers") {
-                cm.display.lineGutter = gElt;
-                gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
-            }
-        }
-        gutters.style.display = i ? "" : "none";
-        var width = gutters.offsetWidth;
-        cm.display.sizer.style.marginLeft = width + "px";
-        if (i)
-            cm.display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;
-    }
-
-    // Compute the character length of a line, taking into account
-    // collapsed ranges (see markText) that might hide parts, and join
-    // other lines onto it.
-    function lineLength(line) {
-        if (line.height == 0)
-            return 0;
-        var len = line.text.length, merged, cur = line;
-        while (merged = collapsedSpanAtStart(cur)) {
-            var found = merged.find(0, true);
-            cur = found.from.line;
-            len += found.from.ch - found.to.ch;
-        }
-        cur = line;
-        while (merged = collapsedSpanAtEnd(cur)) {
-            var found = merged.find(0, true);
-            len -= cur.text.length - found.from.ch;
-            cur = found.to.line;
-            len += cur.text.length - found.to.ch;
-        }
-        return len;
-    }
-
-    // Find the longest line in the document.
-    function findMaxLine(cm) {
-        var d = cm.display, doc = cm.doc;
-        d.maxLine = getLine(doc, doc.first);
-        d.maxLineLength = lineLength(d.maxLine);
-        d.maxLineChanged = true;
-        doc.iter(function (line) {
-            var len = lineLength(line);
-            if (len > d.maxLineLength) {
-                d.maxLineLength = len;
-                d.maxLine = line;
-            }
-        });
-    }
-
-    // Make sure the gutters options contains the element
-    // "CodeMirror-linenumbers" when the lineNumbers option is true.
-    function setGuttersForLineNumbers(options) {
-        var found = indexOf(options.gutters, "CodeMirror-linenumbers");
-        if (found == -1 && options.lineNumbers) {
-            options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
-        } else if (found > -1 && !options.lineNumbers) {
-            options.gutters = options.gutters.slice(0);
-            options.gutters.splice(found, 1);
-        }
-    }
-
-    // SCROLLBARS
-
-    // Prepare DOM reads needed to update the scrollbars. Done in one
-    // shot to minimize update/measure roundtrips.
-    function measureForScrollbars(cm) {
-        var scroll = cm.display.scroller;
-        return {
-            clientHeight: scroll.clientHeight,
-            barHeight: cm.display.scrollbarV.clientHeight,
-            scrollWidth: scroll.scrollWidth, clientWidth: scroll.clientWidth,
-            barWidth: cm.display.scrollbarH.clientWidth,
-            docHeight: Math.round(cm.doc.height + paddingVert(cm.display))
-        };
-    }
-
-    // Re-synchronize the fake scrollbars with the actual size of the
-    // content.
-    function updateScrollbars(cm, measure) {
-        if (!measure)
-            measure = measureForScrollbars(cm);
-        var d = cm.display;
-        var scrollHeight = measure.docHeight + scrollerCutOff;
-        var needsH = measure.scrollWidth > measure.clientWidth;
-        var needsV = scrollHeight > measure.clientHeight;
-        if (needsV) {
-            d.scrollbarV.style.display = "block";
-            d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
-            // A bug in IE8 can cause this value to be negative, so guard it.
-            d.scrollbarV.firstChild.style.height =
-                    Math.max(0, scrollHeight - measure.clientHeight + (measure.barHeight || d.scrollbarV.clientHeight)) + "px";
-        } else {
-            d.scrollbarV.style.display = "";
-            d.scrollbarV.firstChild.style.height = "0";
-        }
-        if (needsH) {
-            d.scrollbarH.style.display = "block";
-            d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
-            d.scrollbarH.firstChild.style.width =
-                    (measure.scrollWidth - measure.clientWidth + (measure.barWidth || d.scrollbarH.clientWidth)) + "px";
-        } else {
-            d.scrollbarH.style.display = "";
-            d.scrollbarH.firstChild.style.width = "0";
-        }
-        if (needsH && needsV) {
-            d.scrollbarFiller.style.display = "block";
-            d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
-        } else
-            d.scrollbarFiller.style.display = "";
-        if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
-            d.gutterFiller.style.display = "block";
-            d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
-            d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
-        } else
-            d.gutterFiller.style.display = "";
-
-        if (mac_geLion && scrollbarWidth(d.measure) === 0) {
-            d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
-            var barMouseDown = function (e) {
-                if (e_target(e) != d.scrollbarV && e_target(e) != d.scrollbarH)
-                    operation(cm, onMouseDown)(e);
-            };
-            on(d.scrollbarV, "mousedown", barMouseDown);
-            on(d.scrollbarH, "mousedown", barMouseDown);
-        }
-    }
-
-    // Compute the lines that are visible in a given viewport (defaults
-    // the the current scroll position). viewPort may contain top,
-    // height, and ensure (see op.scrollToPos) properties.
-    function visibleLines(display, doc, viewPort) {
-        var top = viewPort && viewPort.top != null ? viewPort.top : display.scroller.scrollTop;
-        top = Math.floor(top - paddingTop(display));
-        var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight;
-
-        var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
-        // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
-        // forces those lines into the viewport (if possible).
-        if (viewPort && viewPort.ensure) {
-            var ensureFrom = viewPort.ensure.from.line, ensureTo = viewPort.ensure.to.line;
-            if (ensureFrom < from)
-                return {from: ensureFrom,
-                    to: lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)};
-            if (Math.min(ensureTo, doc.lastLine()) >= to)
-                return {from: lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight),
-                    to: ensureTo};
-        }
-        return {from: from, to: to};
-    }
-
-    // LINE NUMBERS
-
-    // Re-align line numbers and gutter marks to compensate for
-    // horizontal scrolling.
-    function alignHorizontally(cm) {
-        var display = cm.display, view = display.view;
-        if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter))
-            return;
-        var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
-        var gutterW = display.gutters.offsetWidth, left = comp + "px";
-        for (var i = 0; i < view.length; i++)
-            if (!view[i].hidden) {
-                if (cm.options.fixedGutter && view[i].gutter)
-                    view[i].gutter.style.left = left;
-                var align = view[i].alignable;
-                if (align)
-                    for (var j = 0; j < align.length; j++)
-                        align[j].style.left = left;
-            }
-        if (cm.options.fixedGutter)
-            display.gutters.style.left = (comp + gutterW) + "px";
-    }
-
-    // Used to ensure that the line number gutter is still the right
-    // size for the current document size. Returns true when an update
-    // is needed.
-    function maybeUpdateLineNumberWidth(cm) {
-        if (!cm.options.lineNumbers)
-            return false;
-        var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
-        if (last.length != display.lineNumChars) {
-            var test = display.measure.appendChild(elt("div", [elt("div", last)],
-                    "CodeMirror-linenumber CodeMirror-gutter-elt"));
-            var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
-            display.lineGutter.style.width = "";
-            display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
-            display.lineNumWidth = display.lineNumInnerWidth + padding;
-            display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
-            display.lineGutter.style.width = display.lineNumWidth + "px";
-            var width = display.gutters.offsetWidth;
-            display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;
-            display.sizer.style.marginLeft = width + "px";
-            return true;
-        }
-        return false;
-    }
-
-    function lineNumberFor(options, i) {
-        return String(options.lineNumberFormatter(i + options.firstLineNumber));
-    }
-
-    // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
-    // but using getBoundingClientRect to get a sub-pixel-accurate
-    // result.
-    function compensateForHScroll(display) {
-        return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
-    }
-
-    // DISPLAY DRAWING
-
-    // Updates the display, selection, and scrollbars, using the
-    // information in display.view to find out which nodes are no longer
-    // up-to-date. Tries to bail out early when no changes are needed,
-    // unless forced is true.
-    // Returns true if an actual update happened, false otherwise.
-    function updateDisplay(cm, viewPort, forced) {
-        var oldFrom = cm.display.viewFrom, oldTo = cm.display.viewTo, updated;
-        var visible = visibleLines(cm.display, cm.doc, viewPort);
-        for (var first = true; ; first = false) {
-            var oldWidth = cm.display.scroller.clientWidth;
-            if (!updateDisplayInner(cm, visible, forced))
-                break;
-            updated = true;
-
-            // If the max line changed since it was last measured, measure it,
-            // and ensure the document's width matches it.
-            if (cm.display.maxLineChanged && !cm.options.lineWrapping)
-                adjustContentWidth(cm);
-
-            var barMeasure = measureForScrollbars(cm);
-            updateSelection(cm);
-            setDocumentHeight(cm, barMeasure);
-            updateScrollbars(cm, barMeasure);
-            if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {
-                forced = true;
-                continue;
-            }
-            forced = false;
-
-            // Clip forced viewport to actual scrollable area.
-            if (viewPort && viewPort.top != null)
-                viewPort = {top: Math.min(barMeasure.docHeight - scrollerCutOff - barMeasure.clientHeight, viewPort.top)};
-            // Updated line heights might result in the drawn area not
-            // actually covering the viewport. Keep looping until it does.
-            visible = visibleLines(cm.display, cm.doc, viewPort);
-            if (visible.from >= cm.display.viewFrom && visible.to <= cm.display.viewTo)
-                break;
-        }
-
-        cm.display.updateLineNumbers = null;
-        if (updated) {
-            signalLater(cm, "update", cm);
-            if (cm.display.viewFrom != oldFrom || cm.display.viewTo != oldTo)
-                signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
-        }
-        return updated;
-    }
-
-    // Does the actual updating of the line display. Bails out
-    // (returning false) when there is nothing to be done and forced is
-    // false.
-    function updateDisplayInner(cm, visible, forced) {
-        var display = cm.display, doc = cm.doc;
-        if (!display.wrapper.offsetWidth) {
-            resetView(cm);
-            return;
-        }
-
-        // Bail out if the visible area is already rendered and nothing changed.
-        if (!forced && visible.from >= display.viewFrom && visible.to <= display.viewTo &&
-                countDirtyView(cm) == 0)
-            return;
-
-        if (maybeUpdateLineNumberWidth(cm))
-            resetView(cm);
-        var dims = getDimensions(cm);
-
-        // Compute a suitable new viewport (from & to)
-        var end = doc.first + doc.size;
-        var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
-        var to = Math.min(end, visible.to + cm.options.viewportMargin);
-        if (display.viewFrom < from && from - display.viewFrom < 20)
-            from = Math.max(doc.first, display.viewFrom);
-        if (display.viewTo > to && display.viewTo - to < 20)
-            to = Math.min(end, display.viewTo);
-        if (sawCollapsedSpans) {
-            from = visualLineNo(cm.doc, from);
-            to = visualLineEndNo(cm.doc, to);
-        }
-
-        var different = from != display.viewFrom || to != display.viewTo ||
-                display.lastSizeC != display.wrapper.clientHeight;
-        adjustView(cm, from, to);
-
-        display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
-        // Position the mover div to align with the current scroll position
-        cm.display.mover.style.top = display.viewOffset + "px";
-
-        var toUpdate = countDirtyView(cm);
-        if (!different && toUpdate == 0 && !forced)
-            return;
-
-        // For big changes, we hide the enclosing element during the
-        // update, since that speeds up the operations on most browsers.
-        var focused = activeElt();
-        if (toUpdate > 4)
-            display.lineDiv.style.display = "none";
-        patchDisplay(cm, display.updateLineNumbers, dims);
-        if (toUpdate > 4)
-            display.lineDiv.style.display = "";
-        // There might have been a widget with a focused element that got
-        // hidden or updated, if so re-focus it.
-        if (focused && activeElt() != focused && focused.offsetHeight)
-            focused.focus();
-
-        // Prevent selection and cursors from interfering with the scroll
-        // width.
-        removeChildren(display.cursorDiv);
-        removeChildren(display.selectionDiv);
-
-        if (different) {
-            display.lastSizeC = display.wrapper.clientHeight;
-            startWorker(cm, 400);
-        }
-
-        updateHeightsInViewport(cm);
-
-        return true;
-    }
-
-    function adjustContentWidth(cm) {
-        var display = cm.display;
-        var width = measureChar(cm, display.maxLine, display.maxLine.text.length).left;
-        display.maxLineChanged = false;
-        var minWidth = Math.max(0, width + 3);
-        var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + minWidth + scrollerCutOff - display.scroller.clientWidth);
-        display.sizer.style.minWidth = minWidth + "px";
-        if (maxScrollLeft < cm.doc.scrollLeft)
-            setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
-    }
-
-    function setDocumentHeight(cm, measure) {
-        cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measure.docHeight + "px";
-        cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px";
-    }
-
-    // Read the actual heights of the rendered lines, and update their
-    // stored heights to match.
-    function updateHeightsInViewport(cm) {
-        var display = cm.display;
-        var prevBottom = display.lineDiv.offsetTop;
-        for (var i = 0; i < display.view.length; i++) {
-            var cur = display.view[i], height;
-            if (cur.hidden)
-                continue;
-            if (ie_upto7) {
-                var bot = cur.node.offsetTop + cur.node.offsetHeight;
-                height = bot - prevBottom;
-                prevBottom = bot;
-            } else {
-                var box = cur.node.getBoundingClientRect();
-                height = box.bottom - box.top;
-            }
-            var diff = cur.line.height - height;
-            if (height < 2)
-                height = textHeight(display);
-            if (diff > .001 || diff < -.001) {
-                updateLineHeight(cur.line, height);
-                updateWidgetHeight(cur.line);
-                if (cur.rest)
-                    for (var j = 0; j < cur.rest.length; j++)
-                        updateWidgetHeight(cur.rest[j]);
-            }
-        }
-    }
-
-    // Read and store the height of line widgets associated with the
-    // given line.
-    function updateWidgetHeight(line) {
-        if (line.widgets)
-            for (var i = 0; i < line.widgets.length; ++i)
-                line.widgets[i].height = line.widgets[i].node.offsetHeight;
-    }
-
-    // Do a bulk-read of the DOM positions and sizes needed to draw the
-    // view, so that we don't interleave reading and writing to the DOM.
-    function getDimensions(cm) {
-        var d = cm.display, left = {}, width = {};
-        for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
-            left[cm.options.gutters[i]] = n.offsetLeft;
-            width[cm.options.gutters[i]] = n.offsetWidth;
-        }
-        return {fixedPos: compensateForHScroll(d),
-            gutterTotalWidth: d.gutters.offsetWidth,
-            gutterLeft: left,
-            gutterWidth: width,
-            wrapperWidth: d.wrapper.clientWidth};
-    }
-
-    // Sync the actual display DOM structure with display.view, removing
-    // nodes for lines that are no longer in view, and creating the ones
-    // that are not there yet, and updating the ones that are out of
-    // date.
-    function patchDisplay(cm, updateNumbersFrom, dims) {
-        var display = cm.display, lineNumbers = cm.options.lineNumbers;
-        var container = display.lineDiv, cur = container.firstChild;
-
-        function rm(node) {
-            var next = node.nextSibling;
-            // Works around a throw-scroll bug in OS X Webkit
-            if (webkit && mac && cm.display.currentWheelTarget == node)
-                node.style.display = "none";
-            else
-                node.parentNode.removeChild(node);
-            return next;
-        }
-
-        var view = display.view, lineN = display.viewFrom;
-        // Loop over the elements in the view, syncing cur (the DOM nodes
-        // in display.lineDiv) with the view as we go.
-        for (var i = 0; i < view.length; i++) {
-            var lineView = view[i];
-            if (lineView.hidden) {
-            } else if (!lineView.node) { // Not drawn yet
-                var node = buildLineElement(cm, lineView, lineN, dims);
-                container.insertBefore(node, cur);
-            } else { // Already drawn
-                while (cur != lineView.node)
-                    cur = rm(cur);
-                var updateNumber = lineNumbers && updateNumbersFrom != null &&
-                        updateNumbersFrom <= lineN && lineView.lineNumber;
-                if (lineView.changes) {
-                    if (indexOf(lineView.changes, "gutter") > -1)
-                        updateNumber = false;
-                    updateLineForChanges(cm, lineView, lineN, dims);
-                }
-                if (updateNumber) {
-                    removeChildren(lineView.lineNumber);
-                    lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
-                }
-                cur = lineView.node.nextSibling;
-            }
-            lineN += lineView.size;
-        }
-        while (cur)
-            cur = rm(cur);
-    }
-
-    // When an aspect of a line changes, a string is added to
-    // lineView.changes. This updates the relevant part of the line's
-    // DOM structure.
-    function updateLineForChanges(cm, lineView, lineN, dims) {
-        for (var j = 0; j < lineView.changes.length; j++) {
-            var type = lineView.changes[j];
-            if (type == "text")
-                updateLineText(cm, lineView);
-            else if (type == "gutter")
-                updateLineGutter(cm, lineView, lineN, dims);
-            else if (type == "class")
-                updateLineClasses(lineView);
-            else if (type == "widget")
-                updateLineWidgets(lineView, dims);
-        }
-        lineView.changes = null;
-    }
-
-    // Lines with gutter elements, widgets or a background class need to
-    // be wrapped, and have the extra elements added to the wrapper div
-    function ensureLineWrapped(lineView) {
-        if (lineView.node == lineView.text) {
-            lineView.node = elt("div", null, null, "position: relative");
-            if (lineView.text.parentNode)
-                lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
-            lineView.node.appendChild(lineView.text);
-            if (ie_upto7)
-                lineView.node.style.zIndex = 2;
-        }
-        return lineView.node;
-    }
-
-    function updateLineBackground(lineView) {
-        var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
-        if (cls)
-            cls += " CodeMirror-linebackground";
-        if (lineView.background) {
-            if (cls)
-                lineView.background.className = cls;
-            else {
-                lineView.background.parentNode.removeChild(lineView.background);
-                lineView.background = null;
-            }
-        } else if (cls) {
-            var wrap = ensureLineWrapped(lineView);
-            lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
-        }
-    }
-
-    // Wrapper around buildLineContent which will reuse the structure
-    // in display.externalMeasured when possible.
-    function getLineContent(cm, lineView) {
-        var ext = cm.display.externalMeasured;
-        if (ext && ext.line == lineView.line) {
-            cm.display.externalMeasured = null;
-            lineView.measure = ext.measure;
-            return ext.built;
-        }
-        return buildLineContent(cm, lineView);
-    }
-
-    // Redraw the line's text. Interacts with the background and text
-    // classes because the mode may output tokens that influence these
-    // classes.
-    function updateLineText(cm, lineView) {
-        var cls = lineView.text.className;
-        var built = getLineContent(cm, lineView);
-        if (lineView.text == lineView.node)
-            lineView.node = built.pre;
-        lineView.text.parentNode.replaceChild(built.pre, lineView.text);
-        lineView.text = built.pre;
-        if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
-            lineView.bgClass = built.bgClass;
-            lineView.textClass = built.textClass;
-            updateLineClasses(lineView);
-        } else if (cls) {
-            lineView.text.className = cls;
-        }
-    }
-
-    function updateLineClasses(lineView) {
-        updateLineBackground(lineView);
-        if (lineView.line.wrapClass)
-            ensureLineWrapped(lineView).className = lineView.line.wrapClass;
-        else if (lineView.node != lineView.text)
-            lineView.node.className = "";
-        var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
-        lineView.text.className = textClass || "";
-    }
-
-    function updateLineGutter(cm, lineView, lineN, dims) {
-        if (lineView.gutter) {
-            lineView.node.removeChild(lineView.gutter);
-            lineView.gutter = null;
-        }
-        var markers = lineView.line.gutterMarkers;
-        if (cm.options.lineNumbers || markers) {
-            var wrap = ensureLineWrapped(lineView);
-            var gutterWrap = lineView.gutter =
-                    wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "position: absolute; left: " +
-                            (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
-                            lineView.text);
-            if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
-                lineView.lineNumber = gutterWrap.appendChild(
-                        elt("div", lineNumberFor(cm.options, lineN),
-                                "CodeMirror-linenumber CodeMirror-gutter-elt",
-                                "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
-                                + cm.display.lineNumInnerWidth + "px"));
-            if (markers)
-                for (var k = 0; k < cm.options.gutters.length; ++k) {
-                    var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
-                    if (found)
-                        gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
-                                dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
-                }
-        }
-    }
-
-    function updateLineWidgets(lineView, dims) {
-        if (lineView.alignable)
-            lineView.alignable = null;
-        for (var node = lineView.node.firstChild, next; node; node = next) {
-            var next = node.nextSibling;
-            if (node.className == "CodeMirror-linewidget")
-                lineView.node.removeChild(node);
-        }
-        insertLineWidgets(lineView, dims);
-    }
-
-    // Build a line's DOM representation from scratch
-    function buildLineElement(cm, lineView, lineN, dims) {
-        var built = getLineContent(cm, lineView);
-        lineView.text = lineView.node = built.pre;
-        if (built.bgClass)
-            lineView.bgClass = built.bgClass;
-        if (built.textClass)
-            lineView.textClass = built.textClass;
-
-        updateLineClasses(lineView);
-        updateLineGutter(cm, lineView, lineN, dims);
-        insertLineWidgets(lineView, dims);
-        return lineView.node;
-    }
-
-    // A lineView may contain multiple logical lines (when merged by
-    // collapsed spans). The widgets for all of them need to be drawn.
-    function insertLineWidgets(lineView, dims) {
-        insertLineWidgetsFor(lineView.line, lineView, dims, true);
-        if (lineView.rest)
-            for (var i = 0; i < lineView.rest.length; i++)
-                insertLineWidgetsFor(lineView.rest[i], lineView, dims, false);
-    }
-
-    function insertLineWidgetsFor(line, lineView, dims, allowAbove) {
-        if (!line.widgets)
-            return;
-        var wrap = ensureLineWrapped(lineView);
-        for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
-            var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
-            if (!widget.handleMouseEvents)
-                node.ignoreEvents = true;
-            positionLineWidget(widget, node, lineView, dims);
-            if (allowAbove && widget.above)
-                wrap.insertBefore(node, lineView.gutter || lineView.text);
-            else
-                wrap.appendChild(node);
-            signalLater(widget, "redraw");
-        }
-    }
-
-    function positionLineWidget(widget, node, lineView, dims) {
-        if (widget.noHScroll) {
-            (lineView.alignable || (lineView.alignable = [])).push(node);
-            var width = dims.wrapperWidth;
-            node.style.left = dims.fixedPos + "px";
-            if (!widget.coverGutter) {
-                width -= dims.gutterTotalWidth;
-                node.style.paddingLeft = dims.gutterTotalWidth + "px";
-            }
-            node.style.width = width + "px";
-        }
-        if (widget.coverGutter) {
-            node.style.zIndex = 5;
-            node.style.position = "relative";
-            if (!widget.noHScroll)
-                node.style.marginLeft = -dims.gutterTotalWidth + "px";
-        }
-    }
-
-    // POSITION OBJECT
-
-    // A Pos instance represents a position within the text.
-    var Pos = CodeMirror.Pos = function (line, ch) {
-        if (!(this instanceof Pos))
-            return new Pos(line, ch);
-        this.line = line;
-        this.ch = ch;
-    };
-
-    // Compare two positions, return 0 if they are the same, a negative
-    // number when a is less, and a positive number otherwise.
-    var cmp = CodeMirror.cmpPos = function (a, b) {
-        return a.line - b.line || a.ch - b.ch;
-    };
-
-    function copyPos(x) {
-        return Pos(x.line, x.ch);
-    }
-    function maxPos(a, b) {
-        return cmp(a, b) < 0 ? b : a;
-    }
-    function minPos(a, b) {
-        return cmp(a, b) < 0 ? a : b;
-    }
-
-    // SELECTION / CURSOR
-
-    // Selection objects are immutable. A new one is created every time
-    // the selection changes. A selection is one or more non-overlapping
-    // (and non-touching) ranges, sorted, and an integer that indicates
-    // which one is the primary selection (the one that's scrolled into
-    // view, that getCursor returns, etc).
-    function Selection(ranges, primIndex) {
-        this.ranges = ranges;
-        this.primIndex = primIndex;
-    }
-
-    Selection.prototype = {
-        primary: function () {
-            return this.ranges[this.primIndex];
-        },
-        equals: function (other) {
-            if (other == this)
-                return true;
-            if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length)
-                return false;
-            for (var i = 0; i < this.ranges.length; i++) {
-                var here = this.ranges[i], there = other.ranges[i];
-                if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0)
-                    return false;
-            }
-            return true;
-        },
-        deepCopy: function () {
-            for (var out = [], i = 0; i < this.ranges.length; i++)
-                out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
-            return new Selection(out, this.primIndex);
-        },
-        somethingSelected: function () {
-            for (var i = 0; i < this.ranges.length; i++)
-                if (!this.ranges[i].empty())
-                    return true;
-            return false;
-        },
-        contains: function (pos, end) {
-            if (!end)
-                end = pos;
-            for (var i = 0; i < this.ranges.length; i++) {
-                var range = this.ranges[i];
-                if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
-                    return i;
-            }
-            return -1;
-        }
-    };
-
-    function Range(anchor, head) {
-        this.anchor = anchor;
-        this.head = head;
-    }
-
-    Range.prototype = {
-        from: function () {
-            return minPos(this.anchor, this.head);
-        },
-        to: function () {
-            return maxPos(this.anchor, this.head);
-        },
-        empty: function () {
-            return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
-        }
-    };
-
-    // Take an unsorted, potentially overlapping set of ranges, and
-    // build a selection out of it. 'Consumes' ranges array (modifying
-    // it).
-    function normalizeSelection(ranges, primIndex) {
-        var prim = ranges[primIndex];
-        ranges.sort(function (a, b) {
-            return cmp(a.from(), b.from());
-        });
-        primIndex = indexOf(ranges, prim);
-        for (var i = 1; i < ranges.length; i++) {
-            var cur = ranges[i], prev = ranges[i - 1];
-            if (cmp(prev.to(), cur.from()) >= 0) {
-                var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
-                var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
-                if (i <= primIndex)
-                    --primIndex;
-                ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
-            }
-        }
-        return new Selection(ranges, primIndex);
-    }
-
-    function simpleSelection(anchor, head) {
-        return new Selection([new Range(anchor, head || anchor)], 0);
-    }
-
-    // Most of the external API clips given positions to make sure they
-    // actually exist within the document.
-    function clipLine(doc, n) {
-        return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));
-    }
-    function clipPos(doc, pos) {
-        if (pos.line < doc.first)
-            return Pos(doc.first, 0);
-        var last = doc.first + doc.size - 1;
-        if (pos.line > last)
-            return Pos(last, getLine(doc, last).text.length);
-        return clipToLen(pos, getLine(doc, pos.line).text.length);
-    }
-    function clipToLen(pos, linelen) {
-        var ch = pos.ch;
-        if (ch == null || ch > linelen)
-            return Pos(pos.line, linelen);
-        else if (ch < 0)
-            return Pos(pos.line, 0);
-        else
-            return pos;
-    }
-    function isLine(doc, l) {
-        return l >= doc.first && l < doc.first + doc.size;
-    }
-    function clipPosArray(doc, array) {
-        for (var out = [], i = 0; i < array.length; i++)
-            out[i] = clipPos(doc, array[i]);
-        return out;
-    }
-
-    // SELECTION UPDATES
-
-    // The 'scroll' parameter given to many of these indicated whether
-    // the new cursor position should be scrolled into view after
-    // modifying the selection.
-
-    // If shift is held or the extend flag is set, extends a range to
-    // include a given position (and optionally a second position).
-    // Otherwise, simply returns the range between the given positions.
-    // Used for cursor motion and such.
-    function extendRange(doc, range, head, other) {
-        if (doc.cm && doc.cm.display.shift || doc.extend) {
-            var anchor = range.anchor;
-            if (other) {
-                var posBefore = cmp(head, anchor) < 0;
-                if (posBefore != (cmp(other, anchor) < 0)) {
-                    anchor = head;
-                    head = other;
-                } else if (posBefore != (cmp(head, other) < 0)) {
-                    head = other;
-                }
-            }
-            return new Range(anchor, head);
-        } else {
-            return new Range(other || head, head);
-        }
-    }
-
-    // Extend the primary selection range, discard the rest.
-    function extendSelection(doc, head, other, options) {
-        setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
-    }
-
-    // Extend all selections (pos is an array of selections with length
-    // equal the number of selections)
-    function extendSelections(doc, heads, options) {
-        for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
-            out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
-        var newSel = normalizeSelection(out, doc.sel.primIndex);
-        setSelection(doc, newSel, options);
-    }
-
-    // Updates a single range in the selection.
-    function replaceOneSelection(doc, i, range, options) {
-        var ranges = doc.sel.ranges.slice(0);
-        ranges[i] = range;
-        setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
-    }
-
-    // Reset the selection to a single range.
-    function setSimpleSelection(doc, anchor, head, options) {
-        setSelection(doc, simpleSelection(anchor, head), options);
-    }
-
-    // Give beforeSelectionChange handlers a change to influence a
-    // selection update.
-    function filterSelectionChange(doc, sel) {
-        var obj = {
-            ranges: sel.ranges,
-            update: function (ranges) {
-                this.ranges = [];
-                for (var i = 0; i < ranges.length; i++)
-                    this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
-                            clipPos(doc, ranges[i].head));
-            }
-        };
-        signal(doc, "beforeSelectionChange", doc, obj);
-        if (doc.cm)
-            signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
-        if (obj.ranges != sel.ranges)
-            return normalizeSelection(obj.ranges, obj.ranges.length - 1);
-        else
-            return sel;
-    }
-
-    function setSelectionReplaceHistory(doc, sel, options) {
-        var done = doc.history.done, last = lst(done);
-        if (last && last.ranges) {
-            done[done.length - 1] = sel;
-            setSelectionNoUndo(doc, sel, options);
-        } else {
-            setSelection(doc, sel, options);
-        }
-    }
-
-    // Set a new selection.
-    function setSelection(doc, sel, options) {
-        setSelectionNoUndo(doc, sel, options);
-        addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
-    }
-
-    function setSelectionNoUndo(doc, sel, options) {
-        if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
-            sel = filterSelectionChange(doc, sel);
-
-        var bias = cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1;
-        setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
-
-        if (!(options && options.scroll === false) && doc.cm)
-            ensureCursorVisible(doc.cm);
-    }
-
-    function setSelectionInner(doc, sel) {
-        if (sel.equals(doc.sel))
-            return;
-
-        doc.sel = sel;
-
-        if (doc.cm)
-            doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
-                    doc.cm.curOp.cursorActivity = true;
-        signalLater(doc, "cursorActivity", doc);
-    }
-
-    // Verify that the selection does not partially select any atomic
-    // marked ranges.
-    function reCheckSelection(doc) {
-        setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
-    }
-
-    // Return a selection that does not partially select any atomic
-    // ranges.
-    function skipAtomicInSelection(doc, sel, bias, mayClear) {
-        var out;
-        for (var i = 0; i < sel.ranges.length; i++) {
-            var range = sel.ranges[i];
-            var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
-            var newHead = skipAtomic(doc, range.head, bias, mayClear);
-            if (out || newAnchor != range.anchor || newHead != range.head) {
-                if (!out)
-                    out = sel.ranges.slice(0, i);
-                out[i] = new Range(newAnchor, newHead);
-            }
-        }
-        return out ? normalizeSelection(out, sel.primIndex) : sel;
-    }
-
-    // Ensure a given position is not inside an atomic range.
-    function skipAtomic(doc, pos, bias, mayClear) {
-        var flipped = false, curPos = pos;
-        var dir = bias || 1;
-        doc.cantEdit = false;
-        search: for (; ; ) {
-            var line = getLine(doc, curPos.line);
-            if (line.markedSpans) {
-                for (var i = 0; i < line.markedSpans.length; ++i) {
-                    var sp = line.markedSpans[i], m = sp.marker;
-                    if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
-                            (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
-                        if (mayClear) {
-                            signal(m, "beforeCursorEnter");
-                            if (m.explicitlyCleared) {
-                                if (!line.markedSpans)
-                                    break;
-                                else {
-                                    --i;
-                                    continue;
-                                }
-                            }
-                        }
-                        if (!m.atomic)
-                            continue;
-                        var newPos = m.find(dir < 0 ? -1 : 1);
-                        if (cmp(newPos, curPos) == 0) {
-                            newPos.ch += dir;
-                            if (newPos.ch < 0) {
-                                if (newPos.line > doc.first)
-                                    newPos = clipPos(doc, Pos(newPos.line - 1));
-                                else
-                                    newPos = null;
-                            } else if (newPos.ch > line.text.length) {
-                                if (newPos.line < doc.first + doc.size - 1)
-                                    newPos = Pos(newPos.line + 1, 0);
-                                else
-                                    newPos = null;
-                            }
-                            if (!newPos) {
-                                if (flipped) {
-                                    // Driven in a corner -- no valid cursor position found at all
-                                    // -- try again *with* clearing, if we didn't already
-                                    if (!mayClear)
-                                        return skipAtomic(doc, pos, bias, true);
-                                    // Otherwise, turn off editing until further notice, and return the start of the doc
-                                    doc.cantEdit = true;
-                                    return Pos(doc.first, 0);
-                                }
-                                flipped = true;
-                                newPos = pos;
-                                dir = -dir;
-                            }
-                        }
-                        curPos = newPos;
-                        continue search;
-                    }
-                }
-            }
-            return curPos;
-        }
-    }
-
-    // SELECTION DRAWING
-
-    // Redraw the selection and/or cursor
-    function updateSelection(cm) {
-        var display = cm.display, doc = cm.doc;
-        var curFragment = document.createDocumentFragment();
-        var selFragment = document.createDocumentFragment();
-
-        for (var i = 0; i < doc.sel.ranges.length; i++) {
-            var range = doc.sel.ranges[i];
-            var collapsed = range.empty();
-            if (collapsed || cm.options.showCursorWhenSelecting)
-                updateSelectionCursor(cm, range, curFragment);
-            if (!collapsed)
-                updateSelectionRange(cm, range, selFragment);
-        }
-
-        // Move the hidden textarea near the cursor to prevent scrolling artifacts
-        if (cm.options.moveInputWithCursor) {
-            var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
-            var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
-            var top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
-                    headPos.top + lineOff.top - wrapOff.top));
-            var left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
-                    headPos.left + lineOff.left - wrapOff.left));
-            display.inputDiv.style.top = top + "px";
-            display.inputDiv.style.left = left + "px";
-        }
-
-        removeChildrenAndAdd(display.cursorDiv, curFragment);
-        removeChildrenAndAdd(display.selectionDiv, selFragment);
-    }
-
-    // Draws a cursor for the given range
-    function updateSelectionCursor(cm, range, output) {
-        var pos = cursorCoords(cm, range.head, "div");
-
-        var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
-        cursor.style.left = pos.left + "px";
-        cursor.style.top = pos.top + "px";
-        cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
-
-        if (pos.other) {
-            // Secondary cursor, shown when on a 'jump' in bi-directional text
-            var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
-            otherCursor.style.display = "";
-            otherCursor.style.left = pos.other.left + "px";
-            otherCursor.style.top = pos.other.top + "px";
-            otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
-        }
-    }
-
-    // Draws the given range as a highlighted selection
-    function updateSelectionRange(cm, range, output) {
-        var display = cm.display, doc = cm.doc;
-        var fragment = document.createDocumentFragment();
-        var padding = paddingH(cm.display), leftSide = padding.left, rightSide = display.lineSpace.offsetWidth - padding.right;
-
-        function add(left, top, width, bottom) {
-            if (top < 0)
-                top = 0;
-            fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
-                    "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
-                    "px; height: " + (bottom - top) + "px"));
-        }
-
-        function drawForLine(line, fromArg, toArg) {
-            var lineObj = getLine(doc, line);
-            var lineLen = lineObj.text.length;
-            var start, end;
-            function coords(ch, bias) {
-                return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
-            }
-
-            iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) {
-                var leftPos = coords(from, "left"), rightPos, left, right;
-                if (from == to) {
-                    rightPos = leftPos;
-                    left = right = leftPos.left;
-                } else {
-                    rightPos = coords(to - 1, "right");
-                    if (dir == "rtl") {
-                        var tmp = leftPos;
-                        leftPos = rightPos;
-                        rightPos = tmp;
-                    }
-                    left = leftPos.left;
-                    right = rightPos.right;
-                }
-                if (fromArg == null && from == 0)
-                    left = leftSide;
-                if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
-                    add(left, leftPos.top, null, leftPos.bottom);
-                    left = leftSide;
-                    if (leftPos.bottom < rightPos.top)
-                        add(left, leftPos.bottom, null, rightPos.top);
-                }
-                if (toArg == null && to == lineLen)
-                    right = rightSide;
-                if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
-                    start = leftPos;
-                if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
-                    end = rightPos;
-                if (left < leftSide + 1)
-                    left = leftSide;
-                add(left, rightPos.top, right - left, rightPos.bottom);
-            });
-            return {start: start, end: end};
-        }
-
-        var sFrom = range.from(), sTo = range.to();
-        if (sFrom.line == sTo.line) {
-            drawForLine(sFrom.line, sFrom.ch, sTo.ch);
-        } else {
-            var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
-            var singleVLine = visualLine(fromLine) == visualLine(toLine);
-            var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
-            var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
-            if (singleVLine) {
-                if (leftEnd.top < rightStart.top - 2) {
-                    add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
-                    add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
-                } else {
-                    add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
-                }
-            }
-            if (leftEnd.bottom < rightStart.top)
-                add(leftSide, leftEnd.bottom, null, rightStart.top);
-        }
-
-        output.appendChild(fragment);
-    }
-
-    // Cursor-blinking
-    function restartBlink(cm) {
-        if (!cm.state.focused)
-            return;
-        var display = cm.display;
-        clearInterval(display.blinker);
-        var on = true;
-        display.cursorDiv.style.visibility = "";
-        if (cm.options.cursorBlinkRate > 0)
-            display.blinker = setInterval(function () {
-                display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
-            }, cm.options.cursorBlinkRate);
-    }
-
-    // HIGHLIGHT WORKER
-
-    function startWorker(cm, time) {
-        if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
-            cm.state.highlight.set(time, bind(highlightWorker, cm));
-    }
-
-    function highlightWorker(cm) {
-        var doc = cm.doc;
-        if (doc.frontier < doc.first)
-            doc.frontier = doc.first;
-        if (doc.frontier >= cm.display.viewTo)
-            return;
-        var end = +new Date + cm.options.workTime;
-        var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
-
-        runInOp(cm, function () {
-            doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
-                if (doc.frontier >= cm.display.viewFrom) { // Visible
-                    var oldStyles = line.styles;
-                    line.styles = highlightLine(cm, line, state, true);
-                    var ischange = !oldStyles || oldStyles.length != line.styles.length;
-                    for (var i = 0; !ischange && i < oldStyles.length; ++i)
-                        ischange = oldStyles[i] != line.styles[i];
-                    if (ischange)
-                        regLineChange(cm, doc.frontier, "text");
-                    line.stateAfter = copyState(doc.mode, state);
-                } else {
-                    processLine(cm, line.text, state);
-                    line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
-                }
-                ++doc.frontier;
-                if (+new Date > end) {
-                    startWorker(cm, cm.options.workDelay);
-                    return true;
-                }
-            });
-        });
-    }
-
-    // Finds the line to start with when starting a parse. Tries to
-    // find a line with a stateAfter, so that it can start with a
-    // valid state. If that fails, it returns the line with the
-    // smallest indentation, which tends to need the least context to
-    // parse correctly.
-    function findStartLine(cm, n, precise) {
-        var minindent, minline, doc = cm.doc;
-        var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
-        for (var search = n; search > lim; --search) {
-            if (search <= doc.first)
-                return doc.first;
-            var line = getLine(doc, search - 1);
-            if (line.stateAfter && (!precise || search <= doc.frontier))
-                return search;
-            var indented = countColumn(line.text, null, cm.options.tabSize);
-            if (minline == null || minindent > indented) {
-                minline = search - 1;
-                minindent = indented;
-            }
-        }
-        return minline;
-    }
-
-    function getStateBefore(cm, n, precise) {
-        var doc = cm.doc, display = cm.display;
-        if (!doc.mode.startState)
-            return true;
-        var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos - 1).stateAfter;
-        if (!state)
-            state = startState(doc.mode);
-        else
-            state = copyState(doc.mode, state);
-        doc.iter(pos, n, function (line) {
-            processLine(cm, line.text, state);
-            var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
-            line.stateAfter = save ? copyState(doc.mode, state) : null;
-            ++pos;
-        });
-        if (precise)
-            doc.frontier = pos;
-        return state;
-    }
-
-    // POSITION MEASUREMENT
-
-    function paddingTop(display) {
-        return display.lineSpace.offsetTop;
-    }
-    function paddingVert(display) {
-        return display.mover.offsetHeight - display.lineSpace.offsetHeight;
-    }
-    function paddingH(display) {
-        if (display.cachedPaddingH)
-            return display.cachedPaddingH;
-        var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
-        var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
-        return display.cachedPaddingH = {left: parseInt(style.paddingLeft),
-            right: parseInt(style.paddingRight)};
-    }
-
-    // Ensure the lineView.wrapping.heights array is populated. This is
-    // an array of bottom offsets for the lines that make up a drawn
-    // line. When lineWrapping is on, there might be more than one
-    // height.
-    function ensureLineHeights(cm, lineView, rect) {
-        var wrapping = cm.options.lineWrapping;
-        var curWidth = wrapping && cm.display.scroller.clientWidth;
-        if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
-            var heights = lineView.measure.heights = [];
-            if (wrapping) {
-                lineView.measure.width = curWidth;
-                var rects = lineView.text.firstChild.getClientRects();
-                for (var i = 0; i < rects.length - 1; i++) {
-                    var cur = rects[i], next = rects[i + 1];
-                    if (Math.abs(cur.bottom - next.bottom) > 2)
-                        heights.push((cur.bottom + next.top) / 2 - rect.top);
-                }
-            }
-            heights.push(rect.bottom - rect.top);
-        }
-    }
-
-    // Find a line map (mapping character offsets to text nodes) and a
-    // measurement cache for the given line number. (A line view might
-    // contain multiple lines when collapsed ranges are present.)
-    function mapFromLineView(lineView, line, lineN) {
-        if (lineView.line == line)
-            return {map: lineView.measure.map, cache: lineView.measure.cache};
-        for (var i = 0; i < lineView.rest.length; i++)
-            if (lineView.rest[i] == line)
-                return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
-        for (var i = 0; i < lineView.rest.length; i++)
-            if (lineNo(lineView.rest[i]) > lineN)
-                return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
-    }
-
-    // Render a line into the hidden node display.externalMeasured. Used
-    // when measurement is needed for a line that's not in the viewport.
-    function updateExternalMeasurement(cm, line) {
-        line = visualLine(line);
-        var lineN = lineNo(line);
-        var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
-        view.lineN = lineN;
-        var built = view.built = buildLineContent(cm, view);
-        view.text = built.pre;
-        removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
-        return view;
-    }
-
-    // Get a {top, bottom, left, right} box (in line-local coordinates)
-    // for a given character.
-    function measureChar(cm, line, ch, bias) {
-        return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
-    }
-
-    // Find a line view that corresponds to the given line number.
-    function findViewForLine(cm, lineN) {
-        if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
-            return cm.display.view[findViewIndex(cm, lineN)];
-        var ext = cm.display.externalMeasured;
-        if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
-            return ext;
-    }
-
-    // Measurement can be split in two steps, the set-up work that
-    // applies to the whole line, and the measurement of the actual
-    // character. Functions like coordsChar, that need to do a lot of
-    // measurements in a row, can thus ensure that the set-up work is
-    // only done once.
-    function prepareMeasureForLine(cm, line) {
-        var lineN = lineNo(line);
-        var view = findViewForLine(cm, lineN);
-        if (view && !view.text)
-            view = null;
-        else if (view && view.changes)
-            updateLineForChanges(cm, view, lineN, getDimensions(cm));
-        if (!view)
-            view = updateExternalMeasurement(cm, line);
-
-        var info = mapFromLineView(view, line, lineN);
-        return {
-            line: line, view: view, rect: null,
-            map: info.map, cache: info.cache, before: info.before,
-            hasHeights: false
-        };
-    }
-
-    // Given a prepared measurement object, measures the position of an
-    // actual character (or fetches it from the cache).
-    function measureCharPrepared(cm, prepared, ch, bias) {
-        if (prepared.before)
-            ch = -1;
-        var key = ch + (bias || ""), found;
-        if (prepared.cache.hasOwnProperty(key)) {
-            found = prepared.cache[key];
-        } else {
-            if (!prepared.rect)
-                prepared.rect = prepared.view.text.getBoundingClientRect();
-            if (!prepared.hasHeights) {
-                ensureLineHeights(cm, prepared.view, prepared.rect);
-                prepared.hasHeights = true;
-            }
-            found = measureCharInner(cm, prepared, ch, bias);
-            if (!found.bogus)
-                prepared.cache[key] = found;
-        }
-        return {left: found.left, right: found.right, top: found.top, bottom: found.bottom};
-    }
-
-    var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
-
-    function measureCharInner(cm, prepared, ch, bias) {
-        var map = prepared.map;
-
-        var node, start, end, collapse;
-        // First, search the line map for the text node corresponding to,
-        // or closest to, the target character.
-        for (var i = 0; i < map.length; i += 3) {
-            var mStart = map[i], mEnd = map[i + 1];
-            if (ch < mStart) {
-                start = 0;
-                end = 1;
-                collapse = "left";
-            } else if (ch < mEnd) {
-                start = ch - mStart;
-                end = start + 1;
-            } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
-                end = mEnd - mStart;
-                start = end - 1;
-                if (ch >= mEnd)
-                    collapse = "right";
-            }
-            if (start != null) {
-                node = map[i + 2];
-                if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
-                    collapse = bias;
-                if (bias == "left" && start == 0)
-                    while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
-                        node = map[(i -= 3) + 2];
-                        collapse = "left";
-                    }
-                if (bias == "right" && start == mEnd - mStart)
-                    while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
-                        node = map[(i += 3) + 2];
-                        collapse = "right";
-                    }
-                break;
-            }
-        }
-
-        var rect;
-        if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
-            while (start && isExtendingChar(prepared.line.text.charAt(mStart + start)))
-                --start;
-            while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end)))
-                ++end;
-            if (ie_upto8 && start == 0 && end == mEnd - mStart) {
-                rect = node.parentNode.getBoundingClientRect();
-            } else if (ie && cm.options.lineWrapping) {
-                var rects = range(node, start, end).getClientRects();
-                if (rects.length)
-                    rect = rects[bias == "right" ? rects.length - 1 : 0];
-                else
-                    rect = nullRect;
-            } else {
-                rect = range(node, start, end).getBoundingClientRect();
-            }
-        } else { // If it is a widget, simply get the box for the whole widget.
-            if (start > 0)
-                collapse = bias = "right";
-            var rects;
-            if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
-                rect = rects[bias == "right" ? rects.length - 1 : 0];
-            else
-                rect = node.getBoundingClientRect();
-        }
-        if (ie_upto8 && !start && (!rect || !rect.left && !rect.right)) {
-            var rSpan = node.parentNode.getClientRects()[0];
-            if (rSpan)
-                rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
-            else
-                rect = nullRect;
-        }
-
-        var top, bot = (rect.bottom + rect.top) / 2 - prepared.rect.top;
-        var heights = prepared.view.measure.heights;
-        for (var i = 0; i < heights.length - 1; i++)
-            if (bot < heights[i])
-                break;
-        top = i ? heights[i - 1] : 0;
-        bot = heights[i];
-        var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
-            right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
-            top: top, bottom: bot};
-        if (!rect.left && !rect.right)
-            result.bogus = true;
-        return result;
-    }
-
-    function clearLineMeasurementCacheFor(lineView) {
-        if (lineView.measure) {
-            lineView.measure.cache = {};
-            lineView.measure.heights = null;
-            if (lineView.rest)
-                for (var i = 0; i < lineView.rest.length; i++)
-                    lineView.measure.caches[i] = {};
-        }
-    }
-
-    function clearLineMeasurementCache(cm) {
-        cm.display.externalMeasure = null;
-        removeChildren(cm.display.lineMeasure);
-        for (var i = 0; i < cm.display.view.length; i++)
-            clearLineMeasurementCacheFor(cm.display.view[i]);
-    }
-
-    function clearCaches(cm) {
-        clearLineMeasurementCache(cm);
-        cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
-        if (!cm.options.lineWrapping)
-            cm.display.maxLineChanged = true;
-        cm.display.lineNumChars = null;
-    }
-
-    function pageScrollX() {
-        return window.pageXOffset || (document.documentElement || document.body).scrollLeft;
-    }
-    function pageScrollY() {
-        return window.pageYOffset || (document.documentElement || document.body).scrollTop;
-    }
-
-    // Converts a {top, bottom, left, right} box from line-local
-    // coordinates into another coordinate system. Context may be one of
-    // "line", "div" (display.lineDiv), "local"/null (editor), or "page".
-    function intoCoordSystem(cm, lineObj, rect, context) {
-        if (lineObj.widgets)
-            for (var i = 0; i < lineObj.widgets.length; ++i)
-                if (lineObj.widgets[i].above) {
-                    var size = widgetHeight(lineObj.widgets[i]);
-                    rect.top += size;
-                    rect.bottom += size;
-                }
-        if (context == "line")
-            return rect;
-        if (!context)
-            context = "local";
-        var yOff = heightAtLine(lineObj);
-        if (context == "local")
-            yOff += paddingTop(cm.display);
-        else
-            yOff -= cm.display.viewOffset;
-        if (context == "page" || context == "window") {
-            var lOff = cm.display.lineSpace.getBoundingClientRect();
-            yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
-            var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
-            rect.left += xOff;
-            rect.right += xOff;
-        }
-        rect.top += yOff;
-        rect.bottom += yOff;
-        return rect;
-    }
-
-    // Coverts a box from "div" coords to another coordinate system.
-    // Context may be "window", "page", "div", or "local"/null.
-    function fromCoordSystem(cm, coords, context) {
-        if (context == "div")
-            return coords;
-        var left = coords.left, top = coords.top;
-        // First move into "page" coordinate system
-        if (context == "page") {
-            left -= pageScrollX();
-            top -= pageScrollY();
-        } else if (context == "local" || !context) {
-            var localBox = cm.display.sizer.getBoundingClientRect();
-            left += localBox.left;
-            top += localBox.top;
-        }
-
-        var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
-        return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
-    }
-
-    function charCoords(cm, pos, context, lineObj, bias) {
-        if (!lineObj)
-            lineObj = getLine(cm.doc, pos.line);
-        return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
-    }
-
-    // Returns a box for a given cursor position, which may have an
-    // 'other' property containing the position of the secondary cursor
-    // on a bidi boundary.
-    function cursorCoords(cm, pos, context, lineObj, preparedMeasure) {
-        lineObj = lineObj || getLine(cm.doc, pos.line);
-        if (!preparedMeasure)
-            preparedMeasure = prepareMeasureForLine(cm, lineObj);
-        function get(ch, right) {
-            var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left");
-            if (right)
-                m.left = m.right;
-            else
-                m.right = m.left;
-            return intoCoordSystem(cm, lineObj, m, context);
-        }
-        function getBidi(ch, partPos) {
-            var part = order[partPos], right = part.level % 2;
-            if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
-                part = order[--partPos];
-                ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
-                right = true;
-            } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
-                part = order[++partPos];
-                ch = bidiLeft(part) - part.level % 2;
-                right = false;
-            }
-            if (right && ch == part.to && ch > part.from)
-                return get(ch - 1);
-            return get(ch, right);
-        }
-        var order = getOrder(lineObj), ch = pos.ch;
-        if (!order)
-            return get(ch);
-        var partPos = getBidiPartAt(order, ch);
-        var val = getBidi(ch, partPos);
-        if (bidiOther != null)
-            val.other = getBidi(ch, bidiOther);
-        return val;
-    }
-
-    // Used to cheaply estimate the coordinates for a position. Used for
-    // intermediate scroll updates.
-    function estimateCoords(cm, pos) {
-        var left = 0, pos = clipPos(cm.doc, pos);
-        if (!cm.options.lineWrapping)
-            left = charWidth(cm.display) * pos.ch;
-        var lineObj = getLine(cm.doc, pos.line);
-        var top = heightAtLine(lineObj) + paddingTop(cm.display);
-        return {left: left, right: left, top: top, bottom: top + lineObj.height};
-    }
-
-    // Positions returned by coordsChar contain some extra information.
-    // xRel is the relative x position of the input coordinates compared
-    // to the found position (so xRel > 0 means the coordinates are to
-    // the right of the character position, for example). When outside
-    // is true, that means the coordinates lie outside the line's
-    // vertical range.
-    function PosWithInfo(line, ch, outside, xRel) {
-        var pos = Pos(line, ch);
-        pos.xRel = xRel;
-        if (outside)
-            pos.outside = true;
-        return pos;
-    }
-
-    // Compute the character position closest to the given coordinates.
-    // Input must be lineSpace-local ("div" coordinate system).
-    function coordsChar(cm, x, y) {
-        var doc = cm.doc;
-        y += cm.display.viewOffset;
-        if (y < 0)
-            return PosWithInfo(doc.first, 0, true, -1);
-        var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
-        if (lineN > last)
-            return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
-        if (x < 0)
-            x = 0;
-
-        var lineObj = getLine(doc, lineN);
-        for (; ; ) {
-            var found = coordsCharInner(cm, lineObj, lineN, x, y);
-            var merged = collapsedSpanAtEnd(lineObj);
-            var mergedPos = merged && merged.find(0, true);
-            if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
-                lineN = lineNo(lineObj = mergedPos.to.line);
-            else
-                return found;
-        }
-    }
-
-    function coordsCharInner(cm, lineObj, lineNo, x, y) {
-        var innerOff = y - heightAtLine(lineObj);
-        var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
-        var preparedMeasure = prepareMeasureForLine(cm, lineObj);
-
-        function getX(ch) {
-            var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
-            wrongLine = true;
-            if (innerOff > sp.bottom)
-                return sp.left - adjust;
-            else if (innerOff < sp.top)
-                return sp.left + adjust;
-            else
-                wrongLine = false;
-            return sp.left;
-        }
-
-        var bidi = getOrder(lineObj), dist = lineObj.text.length;
-        var from = lineLeft(lineObj), to = lineRight(lineObj);
-        var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
-
-        if (x > toX)
-            return PosWithInfo(lineNo, to, toOutside, 1);
-        // Do a binary search between these bounds.
-        for (; ; ) {
-            if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
-                var ch = x < fromX || x - fromX <= toX - x ? from : to;
-                var xDiff = x - (ch == from ? fromX : toX);
-                while (isExtendingChar(lineObj.text.charAt(ch)))
-                    ++ch;
-                var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
-                        xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
-                return pos;
-            }
-            var step = Math.ceil(dist / 2), middle = from + step;
-            if (bidi) {
-                middle = from;
-                for (var i = 0; i < step; ++i)
-                    middle = moveVisually(lineObj, middle, 1);
-            }
-            var middleX = getX(middle);
-            if (middleX > x) {
-                to = middle;
-                toX = middleX;
-                if (toOutside = wrongLine)
-                    toX += 1000;
-                dist = step;
-            }
-            else {
-                from = middle;
-                fromX = middleX;
-                fromOutside = wrongLine;
-                dist -= step;
-            }
-        }
-    }
-
-    var measureText;
-    // Compute the default text height.
-    function textHeight(display) {
-        if (display.cachedTextHeight != null)
-            return display.cachedTextHeight;
-        if (measureText == null) {
-            measureText = elt("pre");
-            // Measure a bunch of lines, for browsers that compute
-            // fractional heights.
-            for (var i = 0; i < 49; ++i) {
-                measureText.appendChild(document.createTextNode("x"));
-                measureText.appendChild(elt("br"));
-            }
-            measureText.appendChild(document.createTextNode("x"));
-        }
-        removeChildrenAndAdd(display.measure, measureText);
-        var height = measureText.offsetHeight / 50;
-        if (height > 3)
-      

<TRUNCATED>

[19/28] incubator-nifi git commit: NIFI-27: - Latest version of slickgrid.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.grid.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.grid.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.grid.js
index b4a2d7d..c12bae9 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.grid.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/slick.grid.js
@@ -1,2832 +1,3422 @@
-/**
- * @license
- * (c) 2009-2012 Michael Leibman
- * michael{dot}leibman{at}gmail{dot}com
- * http://github.com/mleibman/slickgrid
- *
- * Distributed under MIT license.
- * All rights reserved.
- *
- * SlickGrid v2.0
- *
- * NOTES:
- *     Cell/row DOM manipulations are done directly bypassing jQuery's DOM manipulation methods.
- *     This increases the speed dramatically, but can only be done safely because there are no event handlers
- *     or data associated with any cell/row DOM nodes.  Cell editors must make sure they implement .destroy()
- *     and do proper cleanup.
- */
-
-// make sure required JavaScript modules are loaded
-if (typeof jQuery === "undefined") {
-    throw "SlickGrid requires jquery module to be loaded";
-}
-if (!jQuery.fn.drag) {
-    throw "SlickGrid requires jquery.event.drag module to be loaded";
-}
-if (typeof Slick === "undefined") {
-    throw "slick.core.js not loaded";
-}
-
-
-(function ($) {
-    // Slick.Grid
-    $.extend(true, window, {
-        Slick: {
-            Grid: SlickGrid
-        }
-    });
-
-    // shared across all grids on the page
-    var scrollbarDimensions;
-    var maxSupportedCssHeight;  // browser's breaking point
-
-    //////////////////////////////////////////////////////////////////////////////////////////////
-    // SlickGrid class implementation (available as Slick.Grid)
-
-    /**
-     * Creates a new instance of the grid.
-     * @class SlickGrid
-     * @constructor
-     * @param {Node}              container   Container node to create the grid in.
-     * @param {Array,Object}      data        An array of objects for databinding.
-     * @param {Array}             columns     An array of column definitions.
-     * @param {Object}            options     Grid options.
-     **/
-    function SlickGrid(container, data, columns, options) {
-        // settings
-        var defaults = {
-            explicitInitialization: false,
-            rowHeight: 25,
-            defaultColumnWidth: 80,
-            enableAddRow: false,
-            leaveSpaceForNewRows: false,
-            editable: false,
-            autoEdit: true,
-            enableCellNavigation: true,
-            enableColumnReorder: true,
-            asyncEditorLoading: false,
-            asyncEditorLoadDelay: 100,
-            forceFitColumns: false,
-            enableAsyncPostRender: false,
-            asyncPostRenderDelay: 60,
-            autoHeight: false,
-            editorLock: Slick.GlobalEditorLock,
-            showHeaderRow: false,
-            headerRowHeight: 25,
-            showTopPanel: false,
-            topPanelHeight: 25,
-            formatterFactory: null,
-            editorFactory: null,
-            cellFlashingCssClass: "flashing",
-            selectedCellCssClass: "selected",
-            multiSelect: true,
-            enableTextSelectionOnCells: false,
-            dataItemColumnValueExtractor: null,
-            fullWidthRows: false,
-            multiColumnSort: false,
-            defaultFormatter: defaultFormatter
-        };
-
-        var columnDefaults = {
-            name: "",
-            resizable: true,
-            sortable: false,
-            minWidth: 30,
-            rerenderOnResize: false,
-            headerCssClass: null
-        };
-
-        // scroller
-        var th;   // virtual height
-        var h;    // real scrollable height
-        var ph;   // page height
-        var n;    // number of pages
-        var cj;   // "jumpiness" coefficient
-
-        var page = 0;       // current page
-        var offset = 0;     // current page offset
-        var scrollDir = 1;
-
-        // private
-        var initialized = false;
-        var $container;
-        var uid = "slickgrid_" + Math.round(1000000 * Math.random());
-        var self = this;
-        var $focusSink;
-        var $headerScroller;
-        var $headers;
-        var $headerRow, $headerRowScroller;
-        var $topPanelScroller;
-        var $topPanel;
-        var $viewport;
-        var $canvas;
-        var $style;
-        var stylesheet, columnCssRulesL, columnCssRulesR;
-        var viewportH, viewportW;
-        var canvasWidth;
-        var viewportHasHScroll, viewportHasVScroll;
-        var headerColumnWidthDiff = 0, headerColumnHeightDiff = 0, // border+padding
-                cellWidthDiff = 0, cellHeightDiff = 0;
-        var absoluteColumnMinWidth;
-        var numberOfRows = 0;
-
-        var activePosX;
-        var activeRow, activeCell;
-        var activeCellNode = null;
-        var currentEditor = null;
-        var serializedEditorValue;
-        var editController;
-
-        var rowsCache = {};
-        var renderedRows = 0;
-        var numVisibleRows;
-        var prevScrollTop = 0;
-        var scrollTop = 0;
-        var lastRenderedScrollTop = 0;
-        var prevScrollLeft = 0;
-        var avgRowRenderTime = 10;
-
-        var selectionModel;
-        var selectedRows = [];
-
-        var plugins = [];
-        var cellCssClasses = {};
-
-        var columnsById = {};
-        var sortColumns = [];
-
-
-        // async call handles
-        var h_editorLoader = null;
-        var h_render = null;
-        var h_postrender = null;
-        var postProcessedRows = {};
-        var postProcessToRow = null;
-        var postProcessFromRow = null;
-
-        // perf counters
-        var counter_rows_rendered = 0;
-        var counter_rows_removed = 0;
-
-
-        //////////////////////////////////////////////////////////////////////////////////////////////
-        // Initialization
-
-        function init() {
-            $container = $(container);
-            if ($container.length < 1) {
-                throw new Error("SlickGrid requires a valid container, " + container + " does not exist in the DOM.");
-            }
-
-            // calculate these only once and share between grid instances
-            maxSupportedCssHeight = maxSupportedCssHeight || getMaxSupportedCssHeight();
-            scrollbarDimensions = scrollbarDimensions || measureScrollbar();
-
-            options = $.extend({}, defaults, options);
-            columnDefaults.width = options.defaultColumnWidth;
-
-            // validate loaded JavaScript modules against requested options
-            if (options.enableColumnReorder && !$.fn.sortable) {
-                throw new Error("SlickGrid's 'enableColumnReorder = true' option requires jquery-ui.sortable module to be loaded");
-            }
-
-            editController = {
-                "commitCurrentEdit": commitCurrentEdit,
-                "cancelCurrentEdit": cancelCurrentEdit
-            };
-
-            $container
-                    .empty()
-                    .css("overflow", "hidden")
-                    .css("outline", 0)
-                    .addClass(uid)
-                    .addClass("ui-widget");
-
-            // set up a positioning container if needed
-            if (!/relative|absolute|fixed/.test($container.css("position"))) {
-                $container.css("position", "relative");
-            }
-
-            $focusSink = $("<div tabIndex='0' hideFocus style='position:fixed;width:0;height:0;top:0;left:0;outline:0;'></div>").appendTo($container);
-
-            $headerScroller = $("<div class='slick-header ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
-            $headers = $("<div class='slick-header-columns' style='width:10000px; left:-1000px' />").appendTo($headerScroller);
-
-            $headerRowScroller = $("<div class='slick-headerrow ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
-            $headerRow = $("<div class='slick-headerrow-columns' />").appendTo($headerRowScroller);
-
-            $topPanelScroller = $("<div class='slick-top-panel-scroller ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
-            $topPanel = $("<div class='slick-top-panel' style='width:10000px' />").appendTo($topPanelScroller);
-
-            if (!options.showTopPanel) {
-                $topPanelScroller.hide();
-            }
-
-            if (!options.showHeaderRow) {
-                $headerRowScroller.hide();
-            }
-
-            $viewport = $("<div class='slick-viewport' style='width:100%;overflow:auto;outline:0;position:relative;;'>").appendTo($container);
-            $viewport.css("overflow-y", options.autoHeight ? "hidden" : "auto");
-
-            $canvas = $("<div class='grid-canvas' />").appendTo($viewport);
-
-            if (!options.explicitInitialization) {
-                finishInitialization();
-            }
-        }
-
-        function finishInitialization() {
-            if (!initialized) {
-                initialized = true;
-
-                viewportW = parseFloat($.css($container[0], "width", true));
-
-                // header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?)
-                // calculate the diff so we can set consistent sizes
-                measureCellPaddingAndBorder();
-
-                // for usability reasons, all text selection in SlickGrid is disabled
-                // with the exception of input and textarea elements (selection must
-                // be enabled there so that editors work as expected); note that
-                // selection in grid cells (grid body) is already unavailable in
-                // all browsers except IE
-                disableSelection($headers); // disable all text selection in header (including input and textarea)
-
-                if (!options.enableTextSelectionOnCells) {
-                    // disable text selection in grid cells except in input and textarea elements
-                    // (this is IE-specific, because selectstart event will only fire in IE)
-                    $viewport.bind("selectstart.ui", function (event) {
-                        return $(event.target).is("input,textarea");
-                    });
-                }
-
-                createColumnHeaders();
-                setupColumnSort();
-                createCssRules();
-                resizeCanvas();
-                bindAncestorScrollEvents();
-
-                $container
-                        .bind("resize.slickgrid", resizeCanvas);
-                $viewport
-                        .bind("scroll.slickgrid", handleScroll);
-                $headerScroller
-                        .bind("contextmenu.slickgrid", handleHeaderContextMenu)
-                        .bind("click.slickgrid", handleHeaderClick);
-                $focusSink
-                        .bind("keydown.slickgrid", handleKeyDown);
-                $canvas
-                        .bind("keydown.slickgrid", handleKeyDown)
-                        .bind("click.slickgrid", handleClick)
-                        .bind("dblclick.slickgrid", handleDblClick)
-                        .bind("contextmenu.slickgrid", handleContextMenu)
-                        .bind("draginit", handleDragInit)
-                        .bind("dragstart", handleDragStart)
-                        .bind("drag", handleDrag)
-                        .bind("dragend", handleDragEnd)
-                        .delegate(".slick-cell", "mouseenter", handleMouseEnter)
-                        .delegate(".slick-cell", "mouseleave", handleMouseLeave);
-            }
-        }
-
-        function registerPlugin(plugin) {
-            plugins.unshift(plugin);
-            plugin.init(self);
-        }
-
-        function unregisterPlugin(plugin) {
-            for (var i = plugins.length; i >= 0; i--) {
-                if (plugins[i] === plugin) {
-                    if (plugins[i].destroy) {
-                        plugins[i].destroy();
-                    }
-                    plugins.splice(i, 1);
-                    break;
-                }
-            }
-        }
-
-        function setSelectionModel(model) {
-            if (selectionModel) {
-                selectionModel.onSelectedRangesChanged.unsubscribe(handleSelectedRangesChanged);
-                if (selectionModel.destroy) {
-                    selectionModel.destroy();
-                }
-            }
-
-            selectionModel = model;
-            if (selectionModel) {
-                selectionModel.init(self);
-                selectionModel.onSelectedRangesChanged.subscribe(handleSelectedRangesChanged);
-            }
-        }
-
-        function getSelectionModel() {
-            return selectionModel;
-        }
-
-        function getCanvasNode() {
-            return $canvas[0];
-        }
-
-        function measureScrollbar() {
-            var $c = $("<div style='position:absolute; top:-10000px; left:-10000px; width:100px; height:100px; overflow:scroll;'></div>").appendTo("body");
-            var dim = {
-                width: $c.width() - $c[0].clientWidth,
-                height: $c.height() - $c[0].clientHeight
-            };
-            $c.remove();
-            return dim;
-        }
-
-        function getCanvasWidth() {
-            var availableWidth = viewportHasVScroll ? viewportW - scrollbarDimensions.width : viewportW;
-            var rowWidth = 0;
-            var i = columns.length;
-            while (i--) {
-                rowWidth += (columns[i].width || columnDefaults.width);
-            }
-            return options.fullWidthRows ? Math.max(rowWidth, availableWidth) : rowWidth;
-        }
-
-        function updateCanvasWidth(forceColumnWidthsUpdate) {
-            var oldCanvasWidth = canvasWidth;
-            canvasWidth = getCanvasWidth();
-
-            if (canvasWidth != oldCanvasWidth) {
-                $canvas.width(canvasWidth);
-                $headerRow.width(canvasWidth);
-                viewportHasHScroll = (canvasWidth > viewportW - scrollbarDimensions.width);
-            }
-
-            if (canvasWidth != oldCanvasWidth || forceColumnWidthsUpdate) {
-                applyColumnWidths();
-            }
-        }
-
-        function disableSelection($target) {
-            if ($target && $target.jquery) {
-                $target
-                        .attr("unselectable", "on")
-                        .css("MozUserSelect", "none")
-                        .bind("selectstart.ui", function () {
-                            return false;
-                        }); // from jquery:ui.core.js 1.7.2
-            }
-        }
-
-        function getMaxSupportedCssHeight() {
-            var increment = 1000000;
-            var supportedHeight = increment;
-            // FF reports the height back but still renders blank after ~6M px
-            var testUpTo = ($.browser.mozilla) ? 5000000 : 1000000000;
-            var div = $("<div style='display:none' />").appendTo(document.body);
-
-            while (supportedHeight <= testUpTo) {
-                div.css("height", supportedHeight + increment);
-                if (div.height() !== supportedHeight + increment) {
-                    break;
-                } else {
-                    supportedHeight += increment;
-                }
-            }
-
-            div.remove();
-            return supportedHeight;
-        }
-
-        // TODO:  this is static.  need to handle page mutation.
-        function bindAncestorScrollEvents() {
-            var elem = $canvas[0];
-            while ((elem = elem.parentNode) != document.body && elem != null) {
-                // bind to scroll containers only
-                if (elem == $viewport[0] || elem.scrollWidth != elem.clientWidth || elem.scrollHeight != elem.clientHeight) {
-                    $(elem).bind("scroll.slickgrid", handleActiveCellPositionChange);
-                }
-            }
-        }
-
-        function unbindAncestorScrollEvents() {
-            $canvas.parents().unbind("scroll.slickgrid");
-        }
-
-        function updateColumnHeader(columnId, title, toolTip) {
-            if (!initialized) {
-                return;
-            }
-            var idx = getColumnIndex(columnId);
-            var $header = $headers.children().eq(idx);
-            if ($header) {
-                columns[idx].name = title;
-                columns[idx].toolTip = toolTip;
-                $header
-                        .attr("title", toolTip || title || "")
-                        .children().eq(0).html(title);
-            }
-        }
-
-        function getHeaderRow() {
-            return $headerRow[0];
-        }
-
-        function getHeaderRowColumn(columnId) {
-            var idx = getColumnIndex(columnId);
-            var $header = $headerRow.children().eq(idx);
-            return $header && $header[0];
-        }
-
-        function createColumnHeaders() {
-            function hoverBegin() {
-                $(this).addClass("ui-state-hover");
-            }
-
-            function hoverEnd() {
-                $(this).removeClass("ui-state-hover");
-            }
-
-            $headers.empty();
-            $headerRow.empty();
-            columnsById = {};
-
-            for (var i = 0; i < columns.length; i++) {
-                var m = columns[i] = $.extend({}, columnDefaults, columns[i]);
-                columnsById[m.id] = i;
-
-                var header = $("<div class='ui-state-default slick-header-column' id='" + uid + m.id + "' />")
-                        .html("<span class='slick-column-name'>" + m.name + "</span>")
-                        .width(m.width - headerColumnWidthDiff)
-                        .attr("title", m.toolTip || m.name || "")
-                        .data("fieldId", m.id)
-                        .addClass(m.headerCssClass || "")
-                        .appendTo($headers);
-
-                if (options.enableColumnReorder || m.sortable) {
-                    header.hover(hoverBegin, hoverEnd);
-                }
-
-                if (m.sortable) {
-                    header.append("<span class='slick-sort-indicator' />");
-                }
-
-                if (options.showHeaderRow) {
-                    $("<div class='ui-state-default slick-headerrow-column l" + i + " r" + i + "'></div>")
-                            .appendTo($headerRow);
-                }
-            }
-
-            if (options.showHeaderRow) {
-                // add a spacer to let the container scroll beyond the header row columns width
-                $("<div style='display:block;height:1px;width:10000px;position:absolute;top:0;left:0;'></div>")
-                        .appendTo($headerRowScroller);
-            }
-
-            setSortColumns(sortColumns);
-            setupColumnResize();
-            if (options.enableColumnReorder) {
-                setupColumnReorder();
-            }
-        }
-
-        function setupColumnSort() {
-            $headers.click(function (e) {
-                // temporary workaround for a bug in jQuery 1.7.1 (http://bugs.jquery.com/ticket/11328)
-                e.metaKey = e.metaKey || e.ctrlKey;
-
-                if ($(e.target).hasClass("slick-resizable-handle")) {
-                    return;
-                }
-
-                var $col = $(e.target).closest(".slick-header-column");
-                if (!$col.length) {
-                    return;
-                }
-
-                var column = columns[getColumnIndex($col.data("fieldId"))];
-                if (column.sortable) {
-                    if (!getEditorLock().commitCurrentEdit()) {
-                        return;
-                    }
-
-                    var sortOpts = null;
-                    var i = 0;
-                    for (; i < sortColumns.length; i++) {
-                        if (sortColumns[i].columnId == column.id) {
-                            sortOpts = sortColumns[i];
-                            sortOpts.sortAsc = !sortOpts.sortAsc;
-                            break;
-                        }
-                    }
-
-                    if (e.metaKey && options.multiColumnSort) {
-                        if (sortOpts) {
-                            sortColumns.splice(i, 1);
-                        }
-                    }
-                    else {
-                        if ((!e.shiftKey && !e.metaKey) || !options.multiColumnSort) {
-                            sortColumns = [];
-                        }
-
-                        if (!sortOpts) {
-                            sortOpts = {columnId: column.id, sortAsc: true};
-                            sortColumns.push(sortOpts);
-                        } else if (sortColumns.length == 0) {
-                            sortColumns.push(sortOpts);
-                        }
-                    }
-
-                    setSortColumns(sortColumns);
-
-                    if (!options.multiColumnSort) {
-                        trigger(self.onSort, {
-                            multiColumnSort: false,
-                            sortCol: column,
-                            sortAsc: sortOpts.sortAsc}, e);
-                    } else {
-                        trigger(self.onSort, {
-                            multiColumnSort: true,
-                            sortCols: $.map(sortColumns, function (col) {
-                                return {sortCol: columns[getColumnIndex(col.columnId)], sortAsc: col.sortAsc};
-                            })}, e);
-                    }
-                }
-            });
-        }
-
-        function setupColumnReorder() {
-            $headers.sortable({
-                containment: "parent",
-                axis: "x",
-                cursor: "default",
-                tolerance: "intersection",
-                helper: "clone",
-                placeholder: "slick-sortable-placeholder ui-state-default slick-header-column",
-                forcePlaceholderSize: true,
-                start: function (e, ui) {
-                    $(ui.helper).addClass("slick-header-column-active");
-                },
-                beforeStop: function (e, ui) {
-                    $(ui.helper).removeClass("slick-header-column-active");
-                },
-                stop: function (e) {
-                    if (!getEditorLock().commitCurrentEdit()) {
-                        $(this).sortable("cancel");
-                        return;
-                    }
-
-                    var reorderedIds = $headers.sortable("toArray");
-                    var reorderedColumns = [];
-                    for (var i = 0; i < reorderedIds.length; i++) {
-                        reorderedColumns.push(columns[getColumnIndex(reorderedIds[i].replace(uid, ""))]);
-                    }
-                    setColumns(reorderedColumns);
-
-                    trigger(self.onColumnsReordered, {});
-                    e.stopPropagation();
-                    setupColumnResize();
-                }
-            });
-        }
-
-        function setupColumnResize() {
-            var $col, j, c, pageX, columnElements, minPageX, maxPageX, firstResizable, lastResizable;
-            columnElements = $headers.children();
-            columnElements.find(".slick-resizable-handle").remove();
-            columnElements.each(function (i, e) {
-                if (columns[i].resizable) {
-                    if (firstResizable === undefined) {
-                        firstResizable = i;
-                    }
-                    lastResizable = i;
-                }
-            });
-            if (firstResizable === undefined) {
-                return;
-            }
-            columnElements.each(function (i, e) {
-                if (i < firstResizable || (options.forceFitColumns && i >= lastResizable)) {
-                    return;
-                }
-                $col = $(e);
-                $("<div class='slick-resizable-handle' />")
-                        .appendTo(e)
-                        .bind("dragstart", function (e, dd) {
-                            if (!getEditorLock().commitCurrentEdit()) {
-                                return false;
-                            }
-                            pageX = e.pageX;
-                            $(this).parent().addClass("slick-header-column-active");
-                            var shrinkLeewayOnRight = null, stretchLeewayOnRight = null;
-                            // lock each column's width option to current width
-                            columnElements.each(function (i, e) {
-                                columns[i].previousWidth = $(e).outerWidth();
-                            });
-                            if (options.forceFitColumns) {
-                                shrinkLeewayOnRight = 0;
-                                stretchLeewayOnRight = 0;
-                                // colums on right affect maxPageX/minPageX
-                                for (j = i + 1; j < columnElements.length; j++) {
-                                    c = columns[j];
-                                    if (c.resizable) {
-                                        if (stretchLeewayOnRight !== null) {
-                                            if (c.maxWidth) {
-                                                stretchLeewayOnRight += c.maxWidth - c.previousWidth;
-                                            } else {
-                                                stretchLeewayOnRight = null;
-                                            }
-                                        }
-                                        shrinkLeewayOnRight += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
-                                    }
-                                }
-                            }
-                            var shrinkLeewayOnLeft = 0, stretchLeewayOnLeft = 0;
-                            for (j = 0; j <= i; j++) {
-                                // columns on left only affect minPageX
-                                c = columns[j];
-                                if (c.resizable) {
-                                    if (stretchLeewayOnLeft !== null) {
-                                        if (c.maxWidth) {
-                                            stretchLeewayOnLeft += c.maxWidth - c.previousWidth;
-                                        } else {
-                                            stretchLeewayOnLeft = null;
-                                        }
-                                    }
-                                    shrinkLeewayOnLeft += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
-                                }
-                            }
-                            if (shrinkLeewayOnRight === null) {
-                                shrinkLeewayOnRight = 100000;
-                            }
-                            if (shrinkLeewayOnLeft === null) {
-                                shrinkLeewayOnLeft = 100000;
-                            }
-                            if (stretchLeewayOnRight === null) {
-                                stretchLeewayOnRight = 100000;
-                            }
-                            if (stretchLeewayOnLeft === null) {
-                                stretchLeewayOnLeft = 100000;
-                            }
-                            maxPageX = pageX + Math.min(shrinkLeewayOnRight, stretchLeewayOnLeft);
-                            minPageX = pageX - Math.min(shrinkLeewayOnLeft, stretchLeewayOnRight);
-                        })
-                        .bind("drag", function (e, dd) {
-                            var actualMinWidth, d = Math.min(maxPageX, Math.max(minPageX, e.pageX)) - pageX, x;
-                            if (d < 0) { // shrink column
-                                x = d;
-                                for (j = i; j >= 0; j--) {
-                                    c = columns[j];
-                                    if (c.resizable) {
-                                        actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
-                                        if (x && c.previousWidth + x < actualMinWidth) {
-                                            x += c.previousWidth - actualMinWidth;
-                                            c.width = actualMinWidth;
-                                        } else {
-                                            c.width = c.previousWidth + x;
-                                            x = 0;
-                                        }
-                                    }
-                                }
-
-                                if (options.forceFitColumns) {
-                                    x = -d;
-                                    for (j = i + 1; j < columnElements.length; j++) {
-                                        c = columns[j];
-                                        if (c.resizable) {
-                                            if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
-                                                x -= c.maxWidth - c.previousWidth;
-                                                c.width = c.maxWidth;
-                                            } else {
-                                                c.width = c.previousWidth + x;
-                                                x = 0;
-                                            }
-                                        }
-                                    }
-                                }
-                            } else { // stretch column
-                                x = d;
-                                for (j = i; j >= 0; j--) {
-                                    c = columns[j];
-                                    if (c.resizable) {
-                                        if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
-                                            x -= c.maxWidth - c.previousWidth;
-                                            c.width = c.maxWidth;
-                                        } else {
-                                            c.width = c.previousWidth + x;
-                                            x = 0;
-                                        }
-                                    }
-                                }
-
-                                if (options.forceFitColumns) {
-                                    x = -d;
-                                    for (j = i + 1; j < columnElements.length; j++) {
-                                        c = columns[j];
-                                        if (c.resizable) {
-                                            actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
-                                            if (x && c.previousWidth + x < actualMinWidth) {
-                                                x += c.previousWidth - actualMinWidth;
-                                                c.width = actualMinWidth;
-                                            } else {
-                                                c.width = c.previousWidth + x;
-                                                x = 0;
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                            applyColumnHeaderWidths();
-                            if (options.syncColumnCellResize) {
-                                applyColumnWidths();
-                            }
-                        })
-                        .bind("dragend", function (e, dd) {
-                            var newWidth;
-                            $(this).parent().removeClass("slick-header-column-active");
-                            for (j = 0; j < columnElements.length; j++) {
-                                c = columns[j];
-                                newWidth = $(columnElements[j]).outerWidth();
-
-                                if (c.previousWidth !== newWidth && c.rerenderOnResize) {
-                                    invalidateAllRows();
-                                }
-                            }
-                            updateCanvasWidth(true);
-                            render();
-                            trigger(self.onColumnsResized, {});
-                        });
-            });
-        }
-
-        function getVBoxDelta($el) {
-            var p = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
-            var delta = 0;
-            $.each(p, function (n, val) {
-                delta += parseFloat($el.css(val)) || 0;
-            });
-            return delta;
-        }
-
-        function measureCellPaddingAndBorder() {
-            var el;
-            var h = ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"];
-            var v = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
-
-            el = $("<div class='ui-state-default slick-header-column' style='visibility:hidden'>-</div>").appendTo($headers);
-            headerColumnWidthDiff = headerColumnHeightDiff = 0;
-            $.each(h, function (n, val) {
-                headerColumnWidthDiff += parseFloat(el.css(val)) || 0;
-            });
-            $.each(v, function (n, val) {
-                headerColumnHeightDiff += parseFloat(el.css(val)) || 0;
-            });
-            el.remove();
-
-            var r = $("<div class='slick-row' />").appendTo($canvas);
-            el = $("<div class='slick-cell' id='' style='visibility:hidden'>-</div>").appendTo(r);
-            cellWidthDiff = cellHeightDiff = 0;
-            $.each(h, function (n, val) {
-                cellWidthDiff += parseFloat(el.css(val)) || 0;
-            });
-            $.each(v, function (n, val) {
-                cellHeightDiff += parseFloat(el.css(val)) || 0;
-            });
-            r.remove();
-
-            absoluteColumnMinWidth = Math.max(headerColumnWidthDiff, cellWidthDiff);
-        }
-
-        function createCssRules() {
-            $style = $("<style type='text/css' rel='stylesheet' />").appendTo($("head"));
-            var rowHeight = (options.rowHeight - cellHeightDiff);
-            var rules = [
-                "." + uid + " .slick-header-column { left: 1000px; }",
-                "." + uid + " .slick-top-panel { height:" + options.topPanelHeight + "px; }",
-                "." + uid + " .slick-headerrow-columns { height:" + options.headerRowHeight + "px; }",
-                "." + uid + " .slick-cell { height:" + rowHeight + "px; }",
-                "." + uid + " .slick-row { height:" + options.rowHeight + "px; }"
-            ];
-
-            for (var i = 0; i < columns.length; i++) {
-                rules.push("." + uid + " .l" + i + " { }");
-                rules.push("." + uid + " .r" + i + " { }");
-            }
-
-            if ($style[0].styleSheet) { // IE
-                $style[0].styleSheet.cssText = rules.join(" ");
-            } else {
-                $style[0].appendChild(document.createTextNode(rules.join(" ")));
-            }
-        }
-
-        function getColumnCssRules(idx) {
-            if (!stylesheet) {
-                var sheets = document.styleSheets;
-                for (var i = 0; i < sheets.length; i++) {
-                    if ((sheets[i].ownerNode || sheets[i].owningElement) == $style[0]) {
-                        stylesheet = sheets[i];
-                        break;
-                    }
-                }
-
-                if (!stylesheet) {
-                    throw new Error("Cannot find stylesheet.");
-                }
-
-                // find and cache column CSS rules
-                columnCssRulesL = [];
-                columnCssRulesR = [];
-                var cssRules = (stylesheet.cssRules || stylesheet.rules);
-                var matches, columnIdx;
-                for (var i = 0; i < cssRules.length; i++) {
-                    var selector = cssRules[i].selectorText;
-                    if (matches = /\.l\d+/.exec(selector)) {
-                        columnIdx = parseInt(matches[0].substr(2, matches[0].length - 2), 10);
-                        columnCssRulesL[columnIdx] = cssRules[i];
-                    } else if (matches = /\.r\d+/.exec(selector)) {
-                        columnIdx = parseInt(matches[0].substr(2, matches[0].length - 2), 10);
-                        columnCssRulesR[columnIdx] = cssRules[i];
-                    }
-                }
-            }
-
-            return {
-                "left": columnCssRulesL[idx],
-                "right": columnCssRulesR[idx]
-            };
-        }
-
-        function removeCssRules() {
-            $style.remove();
-            stylesheet = null;
-        }
-
-        function destroy() {
-            getEditorLock().cancelCurrentEdit();
-
-            trigger(self.onBeforeDestroy, {});
-
-            for (var i = 0; i < plugins.length; i++) {
-                unregisterPlugin(plugins[i]);
-            }
-
-            if (options.enableColumnReorder && $headers.sortable) {
-                $headers.sortable("destroy");
-            }
-
-            unbindAncestorScrollEvents();
-            $container.unbind(".slickgrid");
-            removeCssRules();
-
-            $canvas.unbind("draginit dragstart dragend drag");
-            $container.empty().removeClass(uid);
-        }
-
-
-        //////////////////////////////////////////////////////////////////////////////////////////////
-        // General
-
-        function trigger(evt, args, e) {
-            e = e || new Slick.EventData();
-            args = args || {};
-            args.grid = self;
-            return evt.notify(args, e, self);
-        }
-
-        function getEditorLock() {
-            return options.editorLock;
-        }
-
-        function getEditController() {
-            return editController;
-        }
-
-        function getColumnIndex(id) {
-            return columnsById[id];
-        }
-
-        function autosizeColumns() {
-            var i, c,
-                    widths = [],
-                    shrinkLeeway = 0,
-                    total = 0,
-                    prevTotal,
-                    availWidth = viewportHasVScroll ? viewportW - scrollbarDimensions.width : viewportW;
-
-            for (i = 0; i < columns.length; i++) {
-                c = columns[i];
-                widths.push(c.width);
-                total += c.width;
-                if (c.resizable) {
-                    shrinkLeeway += c.width - Math.max(c.minWidth, absoluteColumnMinWidth);
-                }
-            }
-
-            // shrink
-            prevTotal = total;
-            while (total > availWidth && shrinkLeeway) {
-                var shrinkProportion = (total - availWidth) / shrinkLeeway;
-                for (i = 0; i < columns.length && total > availWidth; i++) {
-                    c = columns[i];
-                    var width = widths[i];
-                    if (!c.resizable || width <= c.minWidth || width <= absoluteColumnMinWidth) {
-                        continue;
-                    }
-                    var absMinWidth = Math.max(c.minWidth, absoluteColumnMinWidth);
-                    var shrinkSize = Math.floor(shrinkProportion * (width - absMinWidth)) || 1;
-                    shrinkSize = Math.min(shrinkSize, width - absMinWidth);
-                    total -= shrinkSize;
-                    shrinkLeeway -= shrinkSize;
-                    widths[i] -= shrinkSize;
-                }
-                if (prevTotal == total) {  // avoid infinite loop
-                    break;
-                }
-                prevTotal = total;
-            }
-
-            // grow
-            prevTotal = total;
-            while (total < availWidth) {
-                var growProportion = availWidth / total;
-                for (i = 0; i < columns.length && total < availWidth; i++) {
-                    c = columns[i];
-                    if (!c.resizable || c.maxWidth <= c.width) {
-                        continue;
-                    }
-                    var growSize = Math.min(Math.floor(growProportion * c.width) - c.width, (c.maxWidth - c.width) || 1000000) || 1;
-                    total += growSize;
-                    widths[i] += growSize;
-                }
-                if (prevTotal == total) {  // avoid infinite loop
-                    break;
-                }
-                prevTotal = total;
-            }
-
-            var reRender = false;
-            for (i = 0; i < columns.length; i++) {
-                if (columns[i].rerenderOnResize && columns[i].width != widths[i]) {
-                    reRender = true;
-                }
-                columns[i].width = widths[i];
-            }
-
-            applyColumnHeaderWidths();
-            updateCanvasWidth(true);
-            if (reRender) {
-                invalidateAllRows();
-                render();
-            }
-        }
-
-        function applyColumnHeaderWidths() {
-            if (!initialized) {
-                return;
-            }
-            var h;
-            for (var i = 0, headers = $headers.children(), ii = headers.length; i < ii; i++) {
-                h = $(headers[i]);
-                if (h.width() !== columns[i].width - headerColumnWidthDiff) {
-                    h.width(columns[i].width - headerColumnWidthDiff);
-                }
-            }
-        }
-
-        function applyColumnWidths() {
-            var x = 0, w, rule;
-            for (var i = 0; i < columns.length; i++) {
-                w = columns[i].width;
-
-                rule = getColumnCssRules(i);
-                rule.left.style.left = x + "px";
-                rule.right.style.right = (canvasWidth - x - w) + "px";
-
-                x += columns[i].width;
-            }
-        }
-
-        function setSortColumn(columnId, ascending) {
-            setSortColumns([{columnId: columnId, sortAsc: ascending}]);
-        }
-
-        function setSortColumns(cols) {
-            sortColumns = cols;
-
-            var headerColumnEls = $headers.children();
-            headerColumnEls
-                    .removeClass("slick-header-column-sorted")
-                    .find(".slick-sort-indicator")
-                    .removeClass("slick-sort-indicator-asc slick-sort-indicator-desc");
-
-            $.each(sortColumns, function (i, col) {
-                if (col.sortAsc == null) {
-                    col.sortAsc = true;
-                }
-                var columnIndex = getColumnIndex(col.columnId);
-                if (columnIndex != null) {
-                    headerColumnEls.eq(columnIndex)
-                            .addClass("slick-header-column-sorted")
-                            .find(".slick-sort-indicator")
-                            .addClass(col.sortAsc ? "slick-sort-indicator-asc" : "slick-sort-indicator-desc");
-                }
-            });
-        }
-
-        function getSortColumns() {
-            return sortColumns;
-        }
-
-        function handleSelectedRangesChanged(e, ranges) {
-            selectedRows = [];
-            var hash = {};
-            for (var i = 0; i < ranges.length; i++) {
-                for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
-                    if (!hash[j]) {  // prevent duplicates
-                        selectedRows.push(j);
-                    }
-                    hash[j] = {};
-                    for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
-                        if (canCellBeSelected(j, k)) {
-                            hash[j][columns[k].id] = options.selectedCellCssClass;
-                        }
-                    }
-                }
-            }
-
-            setCellCssStyles(options.selectedCellCssClass, hash);
-
-            trigger(self.onSelectedRowsChanged, {rows: getSelectedRows()}, e);
-        }
-
-        function getColumns() {
-            return columns;
-        }
-
-        function setColumns(columnDefinitions) {
-            columns = columnDefinitions;
-            if (initialized) {
-                invalidateAllRows();
-                createColumnHeaders();
-                removeCssRules();
-                createCssRules();
-                resizeCanvas();
-                applyColumnWidths();
-                handleScroll();
-            }
-        }
-
-        function getOptions() {
-            return options;
-        }
-
-        function setOptions(args) {
-            if (!getEditorLock().commitCurrentEdit()) {
-                return;
-            }
-
-            makeActiveCellNormal();
-
-            if (options.enableAddRow !== args.enableAddRow) {
-                invalidateRow(getDataLength());
-            }
-
-            options = $.extend(options, args);
-
-            $viewport.css("overflow-y", options.autoHeight ? "hidden" : "auto");
-            render();
-        }
-
-        function setData(newData, scrollToTop) {
-            data = newData;
-            invalidateAllRows();
-            updateRowCount();
-            if (scrollToTop) {
-                scrollTo(0);
-            }
-        }
-
-        function getData() {
-            return data;
-        }
-
-        function getDataLength() {
-            if (data.getLength) {
-                return data.getLength();
-            } else {
-                return data.length;
-            }
-        }
-
-        function getDataItem(i) {
-            if (data.getItem) {
-                return data.getItem(i);
-            } else {
-                return data[i];
-            }
-        }
-
-        function getTopPanel() {
-            return $topPanel[0];
-        }
-
-        function showTopPanel() {
-            options.showTopPanel = true;
-            $topPanelScroller.slideDown("fast", resizeCanvas);
-        }
-
-        function hideTopPanel() {
-            options.showTopPanel = false;
-            $topPanelScroller.slideUp("fast", resizeCanvas);
-        }
-
-        function showHeaderRowColumns() {
-            options.showHeaderRow = true;
-            $headerRowScroller.slideDown("fast", resizeCanvas);
-        }
-
-        function hideHeaderRowColumns() {
-            options.showHeaderRow = false;
-            $headerRowScroller.slideUp("fast", resizeCanvas);
-        }
-
-        //////////////////////////////////////////////////////////////////////////////////////////////
-        // Rendering / Scrolling
-
-        function scrollTo(y) {
-            var oldOffset = offset;
-
-            page = Math.min(n - 1, Math.floor(y / ph));
-            offset = Math.round(page * cj);
-            var newScrollTop = y - offset;
-
-            if (offset != oldOffset) {
-                var range = getVisibleRange(newScrollTop);
-                cleanupRows(range.top, range.bottom);
-                updateRowPositions();
-            }
-
-            if (prevScrollTop != newScrollTop) {
-                scrollDir = (prevScrollTop + oldOffset < newScrollTop + offset) ? 1 : -1;
-                $viewport[0].scrollTop = (lastRenderedScrollTop = scrollTop = prevScrollTop = newScrollTop);
-
-                trigger(self.onViewportChanged, {});
-            }
-        }
-
-        function defaultFormatter(row, cell, value, columnDef, dataContext) {
-            if (value == null) {
-                return "";
-            } else {
-                return value.toString().replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-            }
-        }
-
-        function getFormatter(row, column) {
-            var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
-
-            // look up by id, then index
-            var columnOverrides = rowMetadata &&
-                    rowMetadata.columns &&
-                    (rowMetadata.columns[column.id] || rowMetadata.columns[getColumnIndex(column.id)]);
-
-            return (columnOverrides && columnOverrides.formatter) ||
-                    (rowMetadata && rowMetadata.formatter) ||
-                    column.formatter ||
-                    (options.formatterFactory && options.formatterFactory.getFormatter(column)) ||
-                    options.defaultFormatter;
-        }
-
-        function getEditor(row, cell) {
-            var column = columns[cell];
-            var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
-            var columnMetadata = rowMetadata && rowMetadata.columns;
-
-            if (columnMetadata && columnMetadata[column.id] && columnMetadata[column.id].editor !== undefined) {
-                return columnMetadata[column.id].editor;
-            }
-            if (columnMetadata && columnMetadata[cell] && columnMetadata[cell].editor !== undefined) {
-                return columnMetadata[cell].editor;
-            }
-
-            return column.editor || (options.editorFactory && options.editorFactory.getEditor(column));
-        }
-
-        function getDataItemValueForColumn(item, columnDef) {
-            if (options.dataItemColumnValueExtractor) {
-                return options.dataItemColumnValueExtractor(item, columnDef);
-            }
-            return item[columnDef.field];
-        }
-
-        function appendRowHtml(stringArray, row) {
-            var d = getDataItem(row);
-            var dataLoading = row < getDataLength() && !d;
-            var cellCss;
-            var rowCss = "slick-row " +
-                    (dataLoading ? " loading" : "") +
-                    (row % 2 == 1 ? " odd" : " even");
-
-            var metadata = data.getItemMetadata && data.getItemMetadata(row);
-
-            if (metadata && metadata.cssClasses) {
-                rowCss += " " + metadata.cssClasses;
-            }
-
-            stringArray.push("<div class='ui-widget-content " + rowCss + "' row='" + row + "' style='top:" + (options.rowHeight * row - offset) + "px'>");
-
-            var colspan, m;
-            for (var i = 0, cols = columns.length; i < cols; i++) {
-                m = columns[i];
-                colspan = getColspan(row, i);  // TODO:  don't calc unless we have to
-                cellCss = "slick-cell l" + i + " r" + Math.min(columns.length - 1, i + colspan - 1) + (m.cssClass ? " " + m.cssClass : "");
-                if (row === activeRow && i === activeCell) {
-                    cellCss += (" active");
-                }
-
-                // TODO:  merge them together in the setter
-                for (var key in cellCssClasses) {
-                    if (cellCssClasses[key][row] && cellCssClasses[key][row][m.id]) {
-                        cellCss += (" " + cellCssClasses[key][row][m.id]);
-                    }
-                }
-
-                stringArray.push("<div class='" + cellCss + "'>");
-
-                // if there is a corresponding row (if not, this is the Add New row or this data hasn't been loaded yet)
-                if (d) {
-                    stringArray.push(getFormatter(row, m)(row, i, getDataItemValueForColumn(d, m), m, d));
-                }
-
-                stringArray.push("</div>");
-
-                if (colspan) {
-                    i += (colspan - 1);
-                }
-            }
-
-            stringArray.push("</div>");
-        }
-
-        function cleanupRows(rangeToKeep) {
-            for (var i in rowsCache) {
-                if (((i = parseInt(i, 10)) !== activeRow) && (i < rangeToKeep.top || i > rangeToKeep.bottom)) {
-                    removeRowFromCache(i);
-                }
-            }
-        }
-
-        function invalidate() {
-            updateRowCount();
-            invalidateAllRows();
-            render();
-        }
-
-        function invalidateAllRows() {
-            if (currentEditor) {
-                makeActiveCellNormal();
-            }
-            for (var row in rowsCache) {
-                removeRowFromCache(row);
-            }
-        }
-
-        function removeRowFromCache(row) {
-            var node = rowsCache[row];
-            if (!node) {
-                return;
-            }
-            $canvas[0].removeChild(node);
-            delete rowsCache[row];
-            delete postProcessedRows[row];
-            renderedRows--;
-            counter_rows_removed++;
-        }
-
-        function invalidateRows(rows) {
-            var i, rl;
-            if (!rows || !rows.length) {
-                return;
-            }
-            scrollDir = 0;
-            for (i = 0, rl = rows.length; i < rl; i++) {
-                if (currentEditor && activeRow === rows[i]) {
-                    makeActiveCellNormal();
-                }
-                if (rowsCache[rows[i]]) {
-                    removeRowFromCache(rows[i]);
-                }
-            }
-        }
-
-        function invalidateRow(row) {
-            invalidateRows([row]);
-        }
-
-        function updateCell(row, cell) {
-            var cellNode = getCellNode(row, cell);
-            if (!cellNode) {
-                return;
-            }
-
-            var m = columns[cell], d = getDataItem(row);
-            if (currentEditor && activeRow === row && activeCell === cell) {
-                currentEditor.loadValue(d);
-            } else {
-                cellNode.innerHTML = d ? getFormatter(row, m)(row, cell, getDataItemValueForColumn(d, m), m, d) : "";
-                invalidatePostProcessingResults(row);
-            }
-        }
-
-        function updateRow(row) {
-            if (!rowsCache[row]) {
-                return;
-            }
-
-            var columnIndex = 0
-            $(rowsCache[row]).children().each(function (i) {
-                var m = columns[columnIndex], d = getDataItem(row);
-                if (row === activeRow && i === activeCell && currentEditor) {
-                    currentEditor.loadValue(getDataItem(activeRow));
-                } else if (d) {
-                    this.innerHTML = getFormatter(row, m)(row, columnIndex, getDataItemValueForColumn(d, m), m, getDataItem(row));
-                } else {
-                    this.innerHTML = "";
-                }
-
-                columnIndex += getColspan(row, i);
-            });
-
-            invalidatePostProcessingResults(row);
-        }
-
-        function getViewportHeight() {
-            return parseFloat($.css($container[0], "height", true)) -
-                    parseFloat($.css($headerScroller[0], "height")) - getVBoxDelta($headerScroller) -
-                    (options.showTopPanel ? options.topPanelHeight + getVBoxDelta($topPanelScroller) : 0) -
-                    (options.showHeaderRow ? options.headerRowHeight + getVBoxDelta($headerRowScroller) : 0);
-        }
-
-        function resizeCanvas() {
-            if (!initialized) {
-                return;
-            }
-            if (options.autoHeight) {
-                viewportH = options.rowHeight * (getDataLength() + (options.enableAddRow ? 1 : 0) + (options.leaveSpaceForNewRows ? numVisibleRows - 1 : 0));
-            } else {
-                viewportH = getViewportHeight();
-            }
-
-            numVisibleRows = Math.ceil(viewportH / options.rowHeight);
-            viewportW = parseFloat($.css($container[0], "width", true));
-            $viewport.height(viewportH);
-
-            if (options.forceFitColumns) {
-                autosizeColumns();
-            }
-
-            updateRowCount();
-            render();
-        }
-
-        function updateRowCount() {
-            if (!initialized) {
-                return;
-            }
-            numberOfRows = getDataLength() +
-                    (options.enableAddRow ? 1 : 0) +
-                    (options.leaveSpaceForNewRows ? numVisibleRows - 1 : 0);
-
-            var oldViewportHasVScroll = viewportHasVScroll;
-            // with autoHeight, we do not need to accommodate the vertical scroll bar
-            viewportHasVScroll = !options.autoHeight && (numberOfRows * options.rowHeight > viewportH);
-
-            // remove the rows that are now outside of the data range
-            // this helps avoid redundant calls to .removeRow() when the size of the data decreased by thousands of rows
-            var l = options.enableAddRow ? getDataLength() : getDataLength() - 1;
-            for (var i in rowsCache) {
-                if (i >= l) {
-                    removeRowFromCache(i);
-                }
-            }
-
-            var oldH = h;
-            th = Math.max(options.rowHeight * numberOfRows, viewportH - scrollbarDimensions.height);
-            if (th < maxSupportedCssHeight) {
-                // just one page
-                h = ph = th;
-                n = 1;
-                cj = 0;
-            } else {
-                // break into pages
-                h = maxSupportedCssHeight;
-                ph = h / 100;
-                n = Math.floor(th / ph);
-                cj = (th - h) / (n - 1);
-            }
-
-            if (h !== oldH) {
-                $canvas.css("height", h);
-                scrollTop = $viewport[0].scrollTop;
-            }
-
-            var oldScrollTopInRange = (scrollTop + offset <= th - viewportH);
-
-            if (th == 0 || scrollTop == 0) {
-                page = offset = 0;
-            } else if (oldScrollTopInRange) {
-                // maintain virtual position
-                scrollTo(scrollTop + offset);
-            } else {
-                // scroll to bottom
-                scrollTo(th - viewportH);
-            }
-
-            if (h != oldH && options.autoHeight) {
-                resizeCanvas();
-            }
-
-            if (options.forceFitColumns && oldViewportHasVScroll != viewportHasVScroll) {
-                autosizeColumns();
-            }
-            updateCanvasWidth(false);
-        }
-
-        function getVisibleRange(viewportTop) {
-            if (viewportTop == null) {
-                viewportTop = scrollTop;
-            }
-
-            return {
-                top: Math.floor((viewportTop + offset) / options.rowHeight),
-                bottom: Math.ceil((viewportTop + offset + viewportH) / options.rowHeight)
-            };
-        }
-
-        function getRenderedRange(viewportTop) {
-            var range = getVisibleRange(viewportTop);
-            var buffer = Math.round(viewportH / options.rowHeight);
-            var minBuffer = 3;
-
-            if (scrollDir == -1) {
-                range.top -= buffer;
-                range.bottom += minBuffer;
-            } else if (scrollDir == 1) {
-                range.top -= minBuffer;
-                range.bottom += buffer;
-            } else {
-                range.top -= minBuffer;
-                range.bottom += minBuffer;
-            }
-
-            range.top = Math.max(0, range.top);
-            range.bottom = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1, range.bottom);
-
-            return range;
-        }
-
-        function renderRows(range) {
-            var i, l,
-                    parentNode = $canvas[0],
-                    rowsBefore = renderedRows,
-                    stringArray = [],
-                    rows = [],
-                    startTimestamp = new Date(),
-                    needToReselectCell = false;
-
-            for (i = range.top; i <= range.bottom; i++) {
-                if (rowsCache[i]) {
-                    continue;
-                }
-                renderedRows++;
-                rows.push(i);
-                appendRowHtml(stringArray, i);
-                if (activeCellNode && activeRow === i) {
-                    needToReselectCell = true;
-                }
-                counter_rows_rendered++;
-            }
-
-            if (!rows.length) {
-                return;
-            }
-
-            var x = document.createElement("div");
-            x.innerHTML = stringArray.join("");
-
-            for (i = 0, l = x.childNodes.length; i < l; i++) {
-                rowsCache[rows[i]] = parentNode.appendChild(x.firstChild);
-            }
-
-            if (needToReselectCell) {
-                activeCellNode = getCellNode(activeRow, activeCell);
-            }
-
-            if (renderedRows - rowsBefore > 5) {
-                avgRowRenderTime = (new Date() - startTimestamp) / (renderedRows - rowsBefore);
-            }
-        }
-
-        function startPostProcessing() {
-            if (!options.enableAsyncPostRender) {
-                return;
-            }
-            clearTimeout(h_postrender);
-            h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
-        }
-
-        function invalidatePostProcessingResults(row) {
-            delete postProcessedRows[row];
-            postProcessFromRow = Math.min(postProcessFromRow, row);
-            postProcessToRow = Math.max(postProcessToRow, row);
-            startPostProcessing();
-        }
-
-        function updateRowPositions() {
-            for (var row in rowsCache) {
-                rowsCache[row].style.top = (row * options.rowHeight - offset) + "px";
-            }
-        }
-
-        function render() {
-            if (!initialized) {
-                return;
-            }
-            var visible = getVisibleRange();
-            var rendered = getRenderedRange();
-
-            // remove rows no longer in the viewport
-            cleanupRows(rendered);
-
-            // add new rows
-            renderRows(rendered);
-
-            postProcessFromRow = visible.top;
-            postProcessToRow = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1, visible.bottom);
-            startPostProcessing();
-
-            lastRenderedScrollTop = scrollTop;
-            h_render = null;
-        }
-
-        function handleScroll() {
-            scrollTop = $viewport[0].scrollTop;
-            var scrollLeft = $viewport[0].scrollLeft;
-            var scrollDist = Math.abs(scrollTop - prevScrollTop);
-
-            if (scrollLeft !== prevScrollLeft) {
-                prevScrollLeft = scrollLeft;
-                $headerScroller[0].scrollLeft = scrollLeft;
-                $topPanelScroller[0].scrollLeft = scrollLeft;
-                $headerRowScroller[0].scrollLeft = scrollLeft;
-            }
-
-            if (scrollDist) {
-                scrollDir = prevScrollTop < scrollTop ? 1 : -1;
-                prevScrollTop = scrollTop;
-
-                // switch virtual pages if needed
-                if (scrollDist < viewportH) {
-                    scrollTo(scrollTop + offset);
-                } else {
-                    var oldOffset = offset;
-                    page = Math.min(n - 1, Math.floor(scrollTop * ((th - viewportH) / (h - viewportH)) * (1 / ph)));
-                    offset = Math.round(page * cj);
-                    if (oldOffset != offset) {
-                        invalidateAllRows();
-                    }
-                }
-
-                if (h_render) {
-                    clearTimeout(h_render);
-                }
-
-                if (Math.abs(lastRenderedScrollTop - scrollTop) < viewportH) {
-                    render();
-                } else {
-                    h_render = setTimeout(render, 50);
-                }
-
-                trigger(self.onViewportChanged, {});
-            }
-
-            trigger(self.onScroll, {scrollLeft: scrollLeft, scrollTop: scrollTop});
-        }
-
-        function asyncPostProcessRows() {
-            while (postProcessFromRow <= postProcessToRow) {
-                var row = (scrollDir >= 0) ? postProcessFromRow++ : postProcessToRow--;
-                var rowNode = rowsCache[row];
-                if (!rowNode || postProcessedRows[row] || row >= getDataLength()) {
-                    continue;
-                }
-
-                var d = getDataItem(row), cellNodes = rowNode.childNodes;
-                for (var i = 0, j = 0, l = columns.length; i < l; ++i) {
-                    var m = columns[i];
-                    if (m.asyncPostRender) {
-                        m.asyncPostRender(cellNodes[j], postProcessFromRow, d, m);
-                    }
-                    ++j;
-                }
-
-                postProcessedRows[row] = true;
-                h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
-                return;
-            }
-        }
-
-        function updateCellCssStylesOnRenderedRows(addedHash, removedHash) {
-            var node, columnId, addedRowHash, removedRowHash;
-            for (var row in rowsCache) {
-                removedRowHash = removedHash && removedHash[row];
-                addedRowHash = addedHash && addedHash[row];
-
-                if (removedRowHash) {
-                    for (columnId in removedRowHash) {
-                        if (!addedRowHash || removedRowHash[columnId] != addedRowHash[columnId]) {
-                            node = getCellNode(row, getColumnIndex(columnId));
-                            if (node) {
-                                $(node).removeClass(removedRowHash[columnId]);
-                            }
-                        }
-                    }
-                }
-
-                if (addedRowHash) {
-                    for (columnId in addedRowHash) {
-                        if (!removedRowHash || removedRowHash[columnId] != addedRowHash[columnId]) {
-                            node = getCellNode(row, getColumnIndex(columnId));
-                            if (node) {
-                                $(node).addClass(addedRowHash[columnId]);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        function addCellCssStyles(key, hash) {
-            if (cellCssClasses[key]) {
-                throw "addCellCssStyles: cell CSS hash with key '" + key + "' already exists.";
-            }
-
-            cellCssClasses[key] = hash;
-            updateCellCssStylesOnRenderedRows(hash, null);
-
-            trigger(self.onCellCssStylesChanged, {"key": key, "hash": hash});
-        }
-
-        function removeCellCssStyles(key) {
-            if (!cellCssClasses[key]) {
-                return;
-            }
-
-            updateCellCssStylesOnRenderedRows(null, cellCssClasses[key]);
-            delete cellCssClasses[key];
-
-            trigger(self.onCellCssStylesChanged, {"key": key, "hash": null});
-        }
-
-        function setCellCssStyles(key, hash) {
-            var prevHash = cellCssClasses[key];
-
-            cellCssClasses[key] = hash;
-            updateCellCssStylesOnRenderedRows(hash, prevHash);
-
-            trigger(self.onCellCssStylesChanged, {"key": key, "hash": hash});
-        }
-
-        function getCellCssStyles(key) {
-            return cellCssClasses[key];
-        }
-
-        function flashCell(row, cell, speed) {
-            speed = speed || 100;
-            if (rowsCache[row]) {
-                var $cell = $(getCellNode(row, cell));
-
-                function toggleCellClass(times) {
-                    if (!times) {
-                        return;
-                    }
-                    setTimeout(function () {
-                        $cell.queue(function () {
-                            $cell.toggleClass(options.cellFlashingCssClass).dequeue();
-                            toggleCellClass(times - 1);
-                        });
-                    },
-                            speed);
-                }
-
-                toggleCellClass(4);
-            }
-        }
-
-        //////////////////////////////////////////////////////////////////////////////////////////////
-        // Interactivity
-
-        function handleDragInit(e, dd) {
-            var cell = getCellFromEvent(e);
-            if (!cell || !cellExists(cell.row, cell.cell)) {
-                return false;
-            }
-
-            retval = trigger(self.onDragInit, dd, e);
-            if (e.isImmediatePropagationStopped()) {
-                return retval;
-            }
-
-            // if nobody claims to be handling drag'n'drop by stopping immediate propagation,
-            // cancel out of it
-            return false;
-        }
-
-        function handleDragStart(e, dd) {
-            var cell = getCellFromEvent(e);
-            if (!cell || !cellExists(cell.row, cell.cell)) {
-                return false;
-            }
-
-            var retval = trigger(self.onDragStart, dd, e);
-            if (e.isImmediatePropagationStopped()) {
-                return retval;
-            }
-
-            return false;
-        }
-
-        function handleDrag(e, dd) {
-            return trigger(self.onDrag, dd, e);
-        }
-
-        function handleDragEnd(e, dd) {
-            trigger(self.onDragEnd, dd, e);
-        }
-
-        function handleKeyDown(e) {
-            trigger(self.onKeyDown, {row: activeRow, cell: activeCell}, e);
-            var handled = e.isImmediatePropagationStopped();
-
-            if (!handled) {
-                if (!e.shiftKey && !e.altKey && !e.ctrlKey) {
-                    if (e.which == 27) {
-                        if (!getEditorLock().isActive()) {
-                            return; // no editing mode to cancel, allow bubbling and default processing (exit without cancelling the event)
-                        }
-                        cancelEditAndSetFocus();
-                    } else if (e.which == 37) {
-                        navigateLeft();
-                    } else if (e.which == 39) {
-                        navigateRight();
-                    } else if (e.which == 38) {
-                        navigateUp();
-                    } else if (e.which == 40) {
-                        navigateDown();
-                    } else if (e.which == 9) {
-                        navigateNext();
-                    } else if (e.which == 13) {
-                        if (options.editable) {
-                            if (currentEditor) {
-                                // adding new row
-                                if (activeRow === getDataLength()) {
-                                    navigateDown();
-                                }
-                                else {
-                                    commitEditAndSetFocus();
-                                }
-                            } else {
-                                if (getEditorLock().commitCurrentEdit()) {
-                                    makeActiveCellEditable();
-                                }
-                            }
-                        }
-                    } else {
-                        return;
-                    }
-                } else if (e.which == 9 && e.shiftKey && !e.ctrlKey && !e.altKey) {
-                    navigatePrev();
-                } else {
-                    return;
-                }
-            }
-
-            // the event has been handled so don't let parent element (bubbling/propagation) or browser (default) handle it
-            e.stopPropagation();
-            e.preventDefault();
-            try {
-                e.originalEvent.keyCode = 0; // prevent default behaviour for special keys in IE browsers (F3, F5, etc.)
-            }
-            // ignore exceptions - setting the original event's keycode throws access denied exception for "Ctrl"
-            // (hitting control key only, nothing else), "Shift" (maybe others)
-            catch (error) {
-            }
-        }
-
-        function handleClick(e) {
-            if (!currentEditor) {
-                setFocus();
-            }
-
-            var cell = getCellFromEvent(e);
-            if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
-                return;
-            }
-
-            trigger(self.onClick, {row: cell.row, cell: cell.cell}, e);
-            if (e.isImmediatePropagationStopped()) {
-                return;
-            }
-
-            if (canCellBeActive(cell.row, cell.cell)) {
-                if (!getEditorLock().isActive() || getEditorLock().commitCurrentEdit()) {
-                    scrollRowIntoView(cell.row, false);
-                    setActiveCellInternal(getCellNode(cell.row, cell.cell), (cell.row === getDataLength()) || options.autoEdit);
-                }
-            }
-        }
-
-        function handleContextMenu(e) {
-            var $cell = $(e.target).closest(".slick-cell", $canvas);
-            if ($cell.length === 0) {
-                return;
-            }
-
-            // are we editing this cell?
-            if (activeCellNode === $cell[0] && currentEditor !== null) {
-                return;
-            }
-
-            trigger(self.onContextMenu, {}, e);
-        }
-
-        function handleDblClick(e) {
-            var cell = getCellFromEvent(e);
-            if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
-                return;
-            }
-
-            trigger(self.onDblClick, {row: cell.row, cell: cell.cell}, e);
-            if (e.isImmediatePropagationStopped()) {
-                return;
-            }
-
-            if (options.editable) {
-                gotoCell(cell.row, cell.cell, true);
-            }
-        }
-
-        function handleHeaderContextMenu(e) {
-            var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
-            var column = $header && columns[self.getColumnIndex($header.data("fieldId"))];
-            trigger(self.onHeaderContextMenu, {column: column}, e);
-        }
-
-        function handleHeaderClick(e) {
-            var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
-            var column = $header && columns[self.getColumnIndex($header.data("fieldId"))];
-            if (column) {
-                trigger(self.onHeaderClick, {column: column}, e);
-            }
-        }
-
-        function handleMouseEnter(e) {
-            trigger(self.onMouseEnter, {}, e);
-        }
-
-        function handleMouseLeave(e) {
-            trigger(self.onMouseLeave, {}, e);
-        }
-
-        function cellExists(row, cell) {
-            return !(row < 0 || row >= getDataLength() || cell < 0 || cell >= columns.length);
-        }
-
-        function getCellFromPoint(x, y) {
-            var row = Math.floor((y + offset) / options.rowHeight);
-            var cell = 0;
-
-            var w = 0;
-            for (var i = 0; i < columns.length && w < x; i++) {
-                w += columns[i].width;
-                cell++;
-            }
-
-            if (cell < 0) {
-                cell = 0;
-            }
-
-            return {row: row, cell: cell - 1};
-        }
-
-        function getCellFromNode(node) {
-            // read column number from .l<columnNumber> CSS class
-            var cls = /l\d+/.exec(node.className);
-            if (!cls) {
-                throw "getCellFromNode: cannot get cell - " + node.className;
-            }
-            return parseInt(cls[0].substr(1, cls[0].length - 1), 10);
-        }
-
-        function getCellFromEvent(e) {
-            var $cell = $(e.target).closest(".slick-cell", $canvas);
-            if (!$cell.length) {
-                return null;
-            }
-
-            return {
-                row: $cell.parent().attr("row") | 0,
-                cell: getCellFromNode($cell[0])
-            };
-        }
-
-        function getCellNodeBox(row, cell) {
-            if (!cellExists(row, cell)) {
-                return null;
-            }
-
-            var y1 = row * options.rowHeight - offset;
-            var y2 = y1 + options.rowHeight - 1;
-            var x1 = 0;
-            for (var i = 0; i < cell; i++) {
-                x1 += columns[i].width;
-            }
-            var x2 = x1 + columns[cell].width;
-
-            return {
-                top: y1,
-                left: x1,
-                bottom: y2,
-                right: x2
-            };
-        }
-
-        //////////////////////////////////////////////////////////////////////////////////////////////
-        // Cell switching
-
-        function resetActiveCell() {
-            setActiveCellInternal(null, false);
-        }
-
-        function setFocus() {
-            $focusSink[0].focus();
-        }
-
-        function scrollActiveCellIntoView() {
-            if (activeCellNode) {
-                var left = $(activeCellNode).position().left,
-                        right = left + $(activeCellNode).outerWidth(),
-                        scrollLeft = $viewport.scrollLeft(),
-                        scrollRight = scrollLeft + $viewport.width();
-
-                if (left < scrollLeft) {
-                    $viewport.scrollLeft(left);
-                } else if (right > scrollRight) {
-                    $viewport.scrollLeft(Math.min(left, right - $viewport[0].clientWidth));
-                }
-            }
-        }
-
-        function setActiveCellInternal(newCell, editMode) {
-            if (activeCellNode !== null) {
-                makeActiveCellNormal();
-                $(activeCellNode).removeClass("active");
-            }
-
-            var activeCellChanged = (activeCellNode !== newCell);
-            activeCellNode = newCell;
-
-            if (activeCellNode != null) {
-                activeRow = parseInt($(activeCellNode).parent().attr("row"));
-                activeCell = activePosX = getCellFromNode(activeCellNode);
-
-                $(activeCellNode).addClass("active");
-
-                if (options.editable && editMode && isCellPotentiallyEditable(activeRow, activeCell)) {
-                    clearTimeout(h_editorLoader);
-
-                    if (options.asyncEditorLoading) {
-                        h_editorLoader = setTimeout(function () {
-                            makeActiveCellEditable();
-                        }, options.asyncEditorLoadDelay);
-                    } else {
-                        makeActiveCellEditable();
-                    }
-                } else {
-                    setFocus();
-                }
-            } else {
-                activeRow = activeCell = null;
-            }
-
-            if (activeCellChanged) {
-                scrollActiveCellIntoView();
-                trigger(self.onActiveCellChanged, getActiveCell());
-            }
-        }
-
-        function clearTextSelection() {
-            if (document.selection && document.selection.empty) {
-                document.selection.empty();
-            } else if (window.getSelection) {
-                var sel = window.getSelection();
-                if (sel && sel.removeAllRanges) {
-                    sel.removeAllRanges();
-                }
-            }
-        }
-
-        function isCellPotentiallyEditable(row, cell) {
-            // is the data for this row loaded?
-            if (row < getDataLength() && !getDataItem(row)) {
-                return false;
-            }
-
-            // are we in the Add New row?  can we create new from this cell?
-            if (columns[cell].cannotTriggerInsert && row >= getDataLength()) {
-                return false;
-            }
-
-            // does this cell have an editor?
-            if (!getEditor(row, cell)) {
-                return false;
-            }
-
-            return true;
-        }
-
-        function makeActiveCellNormal() {
-            if (!currentEditor) {
-                return;
-            }
-            trigger(self.onBeforeCellEditorDestroy, {editor: currentEditor});
-            currentEditor.destroy();
-            currentEditor = null;
-
-            if (activeCellNode) {
-                var d = getDataItem(activeRow);
-                $(activeCellNode).removeClass("editable invalid");
-                if (d) {
-                    var column = columns[activeCell];
-                    var formatter = getFormatter(activeRow, column);
-                    activeCellNode.innerHTML = formatter(activeRow, activeCell, getDataItemValueForColumn(d, column), column, getDataItem(activeRow));
-                    invalidatePostProcessingResults(activeRow);
-                }
-            }
-
-            // if there previously was text selected on a page (such as selected text in the edit cell just removed),
-            // IE can't set focus to anything else correctly
-            if ($.browser.msie) {
-                clearTextSelection();
-            }
-
-            getEditorLock().deactivate(editController);
-        }
-
-        function makeActiveCellEditable(editor) {
-            if (!activeCellNode) {
-                return;
-            }
-            if (!options.editable) {
-                throw "Grid : makeActiveCellEditable : should never get called when options.editable is false";
-            }
-
-            // cancel pending async call if there is one
-            clearTimeout(h_editorLoader);
-
-            if (!isCellPotentiallyEditable(activeRow, activeCell)) {
-                return;
-            }
-
-            var columnDef = columns[activeCell];
-            var item = getDataItem(activeRow);
-
-            if (trigger(self.onBeforeEditCell, {row: activeRow, cell: activeCell, item: item, column: columnDef}) === false) {
-                setFocus();
-                return;
-            }
-
-            getEditorLock().activate(editController);
-            $(activeCellNode).addClass("editable");
-
-            // don't clear the cell if a custom editor is passed through
-            if (!editor) {
-                activeCellNode.innerHTML = "";
-            }
-
-            currentEditor = new (editor || getEditor(activeRow, activeCell))({
-                grid: self,
-                gridPosition: absBox($container[0]),
-                position: absBox(activeCellNode),
-                container: activeCellNode,
-                column: columnDef,
-                item: item || {},
-                commitChanges: commitEditAndSetFocus,
-                cancelChanges: cancelEditAndSetFocus
-            });
-
-            if (item) {
-                currentEditor.loadValue(item);
-            }
-
-            serializedEditorValue = currentEditor.serializeValue();
-
-            if (currentEditor.position) {
-                handleActiveCellPositionChange();
-            }
-        }
-
-        function commitEditAndSetFocus() {
-            // if the commit fails, it would do so due to a validation error
-            // if so, do not steal the focus from the editor
-            if (getEditorLock().commitCurrentEdit()) {
-                setFocus();
-                if (options.autoEdit) {
-                    navigateDown();
-                }
-            }
-        }
-
-        function cancelEditAndSetFocus() {
-            if (getEditorLock().cancelCurrentEdit()) {
-                setFocus();
-            }
-        }
-
-        function absBox(elem) {
-            var box = {
-                top: elem.offsetTop,
-                left: elem.offsetLeft,
-                bottom: 0,
-                right: 0,
-                width: $(elem).outerWidth(),
-                height: $(elem).outerHeight(),
-                visible: true};
-            box.bottom = box.top + box.height;
-            box.right = box.left + box.width;
-
-            // walk up the tree
-            var offsetParent = elem.offsetParent;
-            while ((elem = elem.parentNode) != document.body) {
-                if (box.visible && elem.scrollHeight != elem.offsetHeight && $(elem).css("overflowY") != "visible") {
-                    box.visible = box.bottom > elem.scrollTop && box.top < elem.scrollTop + elem.clientHeight;
-                }
-
-                if (box.visible && elem.scrollWidth != elem.offsetWidth && $(elem).css("overflowX") != "visible") {
-                    box.visible = box.right > elem.scrollLeft && box.left < elem.scrollLeft + elem.clientWidth;
-                }
-
-                box.left -= elem.scrollLeft;
-                box.top -= elem.scrollTop;
-
-                if (elem === offsetParent) {
-                    box.left += elem.offsetLeft;
-                    box.top += elem.offsetTop;
-                    offsetParent = elem.offsetParent;
-                }
-
-                box.bottom = box.top + box.height;
-                box.right = box.left + box.width;
-            }
-
-            return box;
-        }
-
-        function getActiveCellPosition() {
-            return absBox(activeCellNode);
-        }
-
-        function getGridPosition() {
-            return absBox($container[0])
-        }
-
-        function handleActiveCellPositionChange() {
-            if (!activeCellNode) {
-                return;
-            }
-
-            trigger(self.onActiveCellPositionChanged, {});
-
-            if (currentEditor) {
-                var cellBox = getActiveCellPosition();
-                if (currentEditor.show && currentEditor.hide) {
-                    if (!cellBox.visible) {
-                        currentEditor.hide();
-                    } else {
-                        currentEditor.show();
-                    }
-                }
-
-                if (currentEditor.position) {
-                    currentEditor.position(cellBox);
-                }
-            }
-        }
-
-        function getCellEditor() {
-            return currentEditor;
-        }
-
-        function getActiveCell() {
-            if (!activeCellNode) {
-                return null;
-            } else {
-                return {row: activeRow, cell: activeCell};
-            }
-        }
-
-        function getActiveCellNode() {
-            return activeCellNode;
-        }
-
-        function scrollRowIntoView(row, doPaging) {
-            var rowAtTop = row * options.rowHeight;
-            var rowAtBottom = (row + 1) * options.rowHeight - viewportH + (viewportHasHScroll ? scrollbarDimensions.height : 0);
-
-            // need to page down?
-            if ((row + 1) * options.rowHeight > scrollTop + viewportH + offset) {
-                scrollTo(doPaging ? rowAtTop : rowAtBottom);
-                render();
-            }
-            // or page up?
-            else if (row * options.rowHeight < scrollTop + offset) {
-                scrollTo(doPaging ? rowAtBottom : rowAtTop);
-                render();
-            }
-        }
-
-        function getColspan(row, cell) {
-            var metadata = data.getItemMetadata && data.getItemMetadata(row);
-            if (!metadata || !metadata.columns) {
-                return 1;
-            }
-
-            var columnData = metadata.columns[columns[cell].id] || metadata.columns[cell];
-            var colspan = (columnData && columnData.colspan);
-            if (colspan === "*") {
-                colspan = columns.length - cell;
-            }
-            return (colspan || 1);
-        }
-
-        function findFirstFocusableCell(row) {
-            var cell = 0;
-            while (cell < columns.length) {
-                if (canCellBeActive(row, cell)) {
-                    return cell;
-                }
-                cell += getColspan(row, cell);
-            }
-            return null;
-        }
-
-        function findLastFocusableCell(row) {
-            var cell = 0;
-            var lastFocusableCell = null;
-            while (cell < columns.length) {
-                if (canCellBeActive(row, cell)) {
-                    lastFocusableCell = cell;
-                }
-                cell += getColspan(row, cell);
-            }
-            return lastFocusableCell;
-        }
-
-        function gotoRight(row, cell, posX) {
-            if (cell >= columns.length) {
-                return null;
-            }
-
-            do {
-                cell += getColspan(row, cell);
-            }
-            while (cell < columns.length && !canCellBeActive(row, cell));
-
-            if (cell < columns.length) {
-                return {
-                    "row": row,
-                    "cell": cell,
-                    "posX": cell
-                };
-            }
-            return null;
-        }
-
-        function gotoLeft(row, cell, posX) {
-            if (cell <= 0) {
-                return null;
-            }
-
-            var firstFocusableCell

<TRUNCATED>

[13/28] incubator-nifi git commit: NIFI-39: Implemented loadLibrary

Posted by mc...@apache.org.
NIFI-39: Implemented loadLibrary


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/f60a97b0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/f60a97b0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/f60a97b0

Branch: refs/heads/nifi-27
Commit: f60a97b0262fdd9d753130eb81b48e9326eda3dc
Parents: f63cd9a
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 12:17:55 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 12:17:55 2014 -0500

----------------------------------------------------------------------
 .../org/apache/nifi/nar/NarClassLoader.java     | 22 ++++++++++++++++++++
 1 file changed, 22 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/f60a97b0/nar-bundles/framework-bundle/framework/nar/src/main/java/org/apache/nifi/nar/NarClassLoader.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/nar/src/main/java/org/apache/nifi/nar/NarClassLoader.java b/nar-bundles/framework-bundle/framework/nar/src/main/java/org/apache/nifi/nar/NarClassLoader.java
index 5b0ca89..b3b7e7f 100644
--- a/nar-bundles/framework-bundle/framework/nar/src/main/java/org/apache/nifi/nar/NarClassLoader.java
+++ b/nar-bundles/framework-bundle/framework/nar/src/main/java/org/apache/nifi/nar/NarClassLoader.java
@@ -199,6 +199,28 @@ public class NarClassLoader extends URLClassLoader {
     }
 
     @Override
+    protected String findLibrary(final String libname) {
+        File dependencies = new File(narWorkingDirectory, "META-INF/dependencies");
+        if (!dependencies.isDirectory()) {
+            LOGGER.warn(narWorkingDirectory + " does not contain META-INF/dependencies!");
+        }
+        
+        final File nativeDir = new File(dependencies, "native");
+        final File soFile = new File(nativeDir, libname + ".so");
+        if ( soFile.exists() ) {
+            return soFile.getAbsolutePath();
+        } else {
+            final File dllFile = new File(nativeDir, libname + ".dll");
+            if ( dllFile.exists() ) {
+                return dllFile.getAbsolutePath();
+            }
+        }
+        
+        // not found in the nar. try system native dir
+        return null;
+    }
+    
+    @Override
     public String toString() {
         return NarClassLoader.class.getName() + "[" + narWorkingDirectory.getPath() + "]";
     }


[28/28] incubator-nifi git commit: Merge branch 'nifi-27' of https://git-wip-us.apache.org/repos/asf/incubator-nifi into nifi-27

Posted by mc...@apache.org.
Merge branch 'nifi-27' of https://git-wip-us.apache.org/repos/asf/incubator-nifi into nifi-27


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/2f2474ef
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/2f2474ef
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/2f2474ef

Branch: refs/heads/nifi-27
Commit: 2f2474efbc20f07a5ee2ce10ce48954f4854146e
Parents: 9180b7d fef8071
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Dec 10 12:58:18 2014 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Wed Dec 10 12:58:18 2014 -0500

----------------------------------------------------------------------

----------------------------------------------------------------------



[03/28] incubator-nifi git commit: NIFI-145

Posted by mc...@apache.org.
NIFI-145


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/64657049
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/64657049
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/64657049

Branch: refs/heads/nifi-27
Commit: 646570490c530d0c076c9bd9b7d1170946a9dae8
Parents: cb63c66
Author: Mark Payne <ma...@hotmail.com>
Authored: Tue Dec 9 12:18:35 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Tue Dec 9 12:18:35 2014 -0500

----------------------------------------------------------------------
 .../java/org/apache/nifi/BootstrapListener.java | 229 ++++++++++++++++
 .../src/main/java/org/apache/nifi/NiFi.java     |  25 ++
 nifi-bootstrap/pom.xml                          |  17 +-
 .../apache/nifi/bootstrap/BootstrapCodec.java   |  89 ++++++
 .../org/apache/nifi/bootstrap/NiFiListener.java | 116 ++++++++
 .../java/org/apache/nifi/bootstrap/RunNiFi.java | 270 +++++++++++++++++--
 .../org/apache/nifi/bootstrap/ShutdownHook.java |  59 +++-
 .../exception/InvalidCommandException.java      |  37 +++
 8 files changed, 824 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java
new file mode 100644
index 0000000..3bcbeb3
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/BootstrapListener.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BootstrapListener {
+	private static final Logger logger = LoggerFactory.getLogger(BootstrapListener.class);
+	
+	private final NiFi nifi;
+	private final int bootstrapPort;
+
+	private Listener listener;
+	private ServerSocket serverSocket;
+	
+	
+	public BootstrapListener(final NiFi nifi, final int port) {
+		this.nifi = nifi;
+		this.bootstrapPort = port;
+	}
+	
+	public void start() throws IOException {
+		logger.debug("Starting Bootstrap Listener to communicate with Bootstrap Port {}", bootstrapPort);
+		
+		serverSocket = new ServerSocket();
+		serverSocket.bind(new InetSocketAddress("localhost", 0));
+		
+		final int localPort = serverSocket.getLocalPort();
+		logger.info("Started Bootstrap Listener, Listening for incoming requests on port {}", localPort);
+		
+		listener = new Listener(serverSocket);
+		final Thread listenThread = new Thread(listener);
+		listenThread.setName("Listen to Bootstrap");
+		listenThread.start();
+		
+		logger.debug("Notifying Bootstrap that local port is {}", localPort);
+		try (final Socket socket = new Socket()) {
+			socket.setSoTimeout(60000);
+			socket.connect(new InetSocketAddress("localhost", bootstrapPort));
+			socket.setSoTimeout(60000);
+			
+			final OutputStream out = socket.getOutputStream();
+			out.write(("PORT " + localPort + "\n").getBytes(StandardCharsets.UTF_8));
+			out.flush();
+			
+			logger.debug("Awaiting response from Bootstrap...");
+			final BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+			final String response = reader.readLine();
+			if ("OK".equals(response)) {
+				logger.info("Successfully initiated communication with Bootstrap");
+			} else {
+				logger.error("Failed to communicate with Bootstrap. Bootstrap may be unable to issue or receive commands from NiFi");
+			}
+		}
+	}
+	
+	
+	public void stop() {
+		if (listener != null) {
+			listener.stop();
+		}
+	}
+	
+	private class Listener implements Runnable {
+		private final ServerSocket serverSocket;
+		private final ExecutorService executor;
+		private volatile boolean stopped = false;
+		
+		public Listener(final ServerSocket serverSocket) {
+			this.serverSocket = serverSocket;
+			this.executor = Executors.newFixedThreadPool(2);
+		}
+		
+		public void stop() {
+			stopped = true;
+			
+			executor.shutdownNow();
+			
+			try {
+				serverSocket.close();
+			} catch (final IOException ioe) {
+				// nothing to really do here. we could log this, but it would just become
+				// confusing in the logs, as we're shutting down and there's no real benefit
+			}
+		}
+		
+		@Override
+		public void run() {
+			while (!serverSocket.isClosed()) {
+				try {
+					if ( stopped ) {
+						return;
+					}
+					
+					final Socket socket;
+					try {
+						socket = serverSocket.accept();
+					} catch (final IOException ioe) {
+						if ( stopped ) {
+							return;
+						}
+						
+						throw ioe;
+					}
+					
+					executor.submit(new Runnable() {
+						@Override
+						public void run() {
+							try {
+								final BootstrapRequest request = readRequest(socket.getInputStream());
+								final BootstrapRequest.RequestType requestType = request.getRequestType();
+								
+								switch (requestType) {
+									case PING:
+										logger.debug("Received PING request from Bootstrap; responding");
+										echoPing(socket.getOutputStream());
+										logger.debug("Responded to PING request from Bootstrap");
+										break;
+									case SHUTDOWN:
+										logger.info("Received SHUTDOWN request from Bootstrap");
+										echoShutdown(socket.getOutputStream());
+										nifi.shutdownHook();
+										return;
+								}
+							} catch (final Throwable t) {
+								logger.error("Failed to process request from Bootstrap due to " + t.toString(), t);
+							} finally {
+								try {
+									socket.close();
+								} catch (final IOException ioe) {
+									logger.warn("Failed to close socket to Bootstrap due to {}", ioe.toString());
+								}
+							}
+						}
+					});
+				} catch (final Throwable t) {
+					logger.error("Failed to process request from Bootstrap due to " + t.toString(), t);
+				}
+			}
+		}
+	}
+	
+	
+	private void echoPing(final OutputStream out) throws IOException {
+		out.write("PING\n".getBytes(StandardCharsets.UTF_8));
+		out.flush();
+	}
+	
+	private void echoShutdown(final OutputStream out) throws IOException {
+		out.write("SHUTDOWN\n".getBytes(StandardCharsets.UTF_8));
+		out.flush();
+	}
+	
+	private BootstrapRequest readRequest(final InputStream in) throws IOException {
+		final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+		
+		final String line = reader.readLine();
+		final String[] splits = line.split(" ");
+		if ( splits.length < 0 ) {
+			throw new IOException("Received invalid command from NiFi: " + line);
+		}
+		
+		final String requestType = splits[0];
+		final String[] args;
+		if ( splits.length == 1 ) {
+			args = new String[0];
+		} else {
+			args = Arrays.copyOfRange(splits, 1, splits.length);
+		}
+		
+		try {
+			return new BootstrapRequest(requestType, args);
+		} catch (final Exception e) {
+			throw new IOException("Received invalid request from bootstrap; request type = " + requestType);
+		}
+	}
+	
+	
+	private static class BootstrapRequest {
+		public static enum RequestType {
+			SHUTDOWN,
+			PING;
+		}
+		
+		private final RequestType requestType;
+		private final String[] args;
+		
+		public BootstrapRequest(final String request, final String[] args) {
+			this.requestType = RequestType.valueOf(request);
+			this.args = args;
+		}
+		
+		public RequestType getRequestType() {
+			return requestType;
+		}
+		
+		public String[] getArgs() {
+			return args;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
index 5fd1a13..bf50a21 100644
--- a/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
+++ b/nar-bundles/framework-bundle/framework/runtime/src/main/java/org/apache/nifi/NiFi.java
@@ -45,6 +45,9 @@ public class NiFi {
 
     private static final Logger logger = LoggerFactory.getLogger(NiFi.class);
     private final NiFiServer nifiServer;
+    private final BootstrapListener bootstrapListener;
+    
+    public static final String BOOTSTRAP_PORT_PROPERTY = "nifi.bootstrap.listen.port";
 
     public NiFi(final NiFiProperties properties) throws ClassNotFoundException, IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
         Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@@ -65,6 +68,25 @@ public class NiFi {
             }
         }));
 
+        final String bootstrapPort = System.getProperty(BOOTSTRAP_PORT_PROPERTY);
+        if ( bootstrapPort != null ) {
+        	try {
+        		final int port = Integer.parseInt(bootstrapPort);
+        		
+        		if (port < 1 || port > 65535) {
+        			throw new RuntimeException("Failed to start NiFi because system property '" + BOOTSTRAP_PORT_PROPERTY + "' is not a valid integer in the range 1 - 65535");
+        		}
+        		
+        		bootstrapListener = new BootstrapListener(this, port);
+        		bootstrapListener.start();
+        	} catch (final NumberFormatException nfe) {
+        		throw new RuntimeException("Failed to start NiFi because system property '" + BOOTSTRAP_PORT_PROPERTY + "' is not a valid integer in the range 1 - 65535");
+        	}
+        } else {
+        	logger.info("NiFi started without Bootstrap Port information provided; will not listen for requests from Bootstrap");
+        	bootstrapListener = null;
+        }
+        
         // delete the web working dir - if the application does not start successfully
         // the web app directories might be in an invalid state. when this happens
         // jetty will not attempt to re-extract the war into the directory. by removing
@@ -115,6 +137,9 @@ public class NiFi {
             if (nifiServer != null) {
                 nifiServer.stop();
             }
+            if (bootstrapListener != null) {
+            	bootstrapListener.stop();
+            }
             logger.info("Jetty web server shutdown completed (nicely or otherwise).");
         } catch (final Throwable t) {
             logger.warn("Problem occured ensuring Jetty web server was properly terminated due to " + t);

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nifi-bootstrap/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/pom.xml b/nifi-bootstrap/pom.xml
index b620c84..a992018 100644
--- a/nifi-bootstrap/pom.xml
+++ b/nifi-bootstrap/pom.xml
@@ -1,5 +1,18 @@
-<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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
+	<!--
+      Licensed to the Apache Software Foundation (ASF) under one or more
+      contributor license agreements.  See the NOTICE file distributed with
+      this work for additional information regarding copyright ownership.
+      The ASF licenses this file to You under the Apache License, Version 2.0
+      (the "License"); you may not use this file except in compliance with
+      the License.  You may obtain a copy of the License at
+          http://www.apache.org/licenses/LICENSE-2.0
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    -->
 	<modelVersion>4.0.0</modelVersion>
 
 	<parent>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/BootstrapCodec.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/BootstrapCodec.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/BootstrapCodec.java
new file mode 100644
index 0000000..8138c02
--- /dev/null
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/BootstrapCodec.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.bootstrap;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Arrays;
+
+import org.apache.nifi.bootstrap.exception.InvalidCommandException;
+
+public class BootstrapCodec {
+	private final RunNiFi runner;
+	private final BufferedReader reader;
+	private final BufferedWriter writer;
+	
+	public BootstrapCodec(final RunNiFi runner, final InputStream in, final OutputStream out) {
+		this.runner = runner;
+		this.reader = new BufferedReader(new InputStreamReader(in));
+		this.writer = new BufferedWriter(new OutputStreamWriter(out));
+	}
+	
+	public void communicate() throws IOException {
+		final String line = reader.readLine();
+		final String[] splits = line.split(" ");
+		if ( splits.length < 0 ) {
+			throw new IOException("Received invalid command from NiFi: " + line);
+		}
+		
+		final String cmd = splits[0];
+		final String[] args;
+		if ( splits.length == 1 ) {
+			args = new String[0];
+		} else {
+			args = Arrays.copyOfRange(splits, 1, splits.length);
+		}
+		
+		try {
+			processRequest(cmd, args);
+		} catch (final InvalidCommandException ice) {
+			throw new IOException("Received invalid command from NiFi: " + line + " : " + ice.getMessage() == null ? "" : "Details: " + ice.toString());
+		}
+	}
+
+	private void processRequest(final String cmd, final String[] args) throws InvalidCommandException, IOException {
+		switch (cmd) {
+			case "PORT": {
+				if ( args.length != 1 ) {
+					throw new InvalidCommandException();
+				}
+				
+				final int port;
+				try {
+					port = Integer.parseInt( args[0] );
+				} catch (final NumberFormatException nfe) {
+					throw new InvalidCommandException("Invalid Port number; should be integer between 1 and 65535");
+				}
+				
+				if ( port < 1 || port > 65535 ) {
+					throw new InvalidCommandException("Invalid Port number; should be integer between 1 and 65535");
+				}
+				
+				runner.setNiFiCommandControlPort(port);
+				writer.write("OK");
+				writer.newLine();
+				writer.flush();
+			}
+			break;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NiFiListener.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NiFiListener.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NiFiListener.java
new file mode 100644
index 0000000..c831351
--- /dev/null
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NiFiListener.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.bootstrap;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class NiFiListener {
+	private ServerSocket serverSocket;
+	private volatile Listener listener;
+	
+	int start(final RunNiFi runner) throws IOException {
+		serverSocket = new ServerSocket();
+		serverSocket.bind(new InetSocketAddress("localhost", 0));
+		
+		final int localPort = serverSocket.getLocalPort();
+		listener = new Listener(serverSocket, runner);
+		final Thread listenThread = new Thread(listener);
+		listenThread.setName("Listen to NiFi");
+		listenThread.start();
+		return localPort;
+	}
+	
+	public void stop() throws IOException {
+		final Listener listener = this.listener;
+		if ( listener == null ) {
+			return;
+		}
+		
+		listener.stop();
+	}
+	
+	private class Listener implements Runnable {
+		private final ServerSocket serverSocket;
+		private final ExecutorService executor;
+		private final RunNiFi runner;
+		private volatile boolean stopped = false;
+		
+		public Listener(final ServerSocket serverSocket, final RunNiFi runner) {
+			this.serverSocket = serverSocket;
+			this.executor = Executors.newFixedThreadPool(2);
+			this.runner = runner;
+		}
+		
+		public void stop() throws IOException {
+			stopped = true;
+			
+			executor.shutdown();
+			try {
+				executor.awaitTermination(3, TimeUnit.SECONDS);
+			} catch (final InterruptedException ie) {
+			}
+			
+			serverSocket.close();
+		}
+		
+		@Override
+		public void run() {
+			while (!serverSocket.isClosed()) {
+				try {
+					if ( stopped ) {
+						return;
+					}
+					
+					final Socket socket;
+					try {
+						socket = serverSocket.accept();
+					} catch (final IOException ioe) {
+						if ( stopped ) {
+							return;
+						}
+						
+						throw ioe;
+					}
+					
+					
+					executor.submit(new Runnable() {
+						@Override
+						public void run() {
+							try {
+								final BootstrapCodec codec = new BootstrapCodec(runner, socket.getInputStream(), socket.getOutputStream());
+								codec.communicate();
+								socket.close();
+							} catch (final Throwable t) {
+								System.out.println("Failed to communicate with NiFi due to " + t);
+								t.printStackTrace();
+							}
+						}
+					});
+				} catch (final Throwable t) {
+					System.err.println("Failed to receive information from NiFi due to " + t);
+					t.printStackTrace();
+				}
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
index afa1f47..ea3e566 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
@@ -1,16 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package org.apache.nifi.bootstrap;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 
 /**
@@ -18,7 +47,6 @@ import java.util.Properties;
  * 
  * This class looks for the bootstrap.conf file by looking in the following places (in order):
  * <ol>
- * 	<li>First argument to the program</li>
  *  <li>Java System Property named {@code org.apache.nifi.bootstrap.config.file}</li>
  *  <li>${NIFI_HOME}/./conf/bootstrap.conf, where ${NIFI_HOME} references an environment variable {@code NIFI_HOME}</li>
  *  <li>./conf/bootstrap.conf, where {@code .} represents the working directory.
@@ -29,12 +57,57 @@ import java.util.Properties;
 public class RunNiFi {
 	public static final String DEFAULT_CONFIG_FILE = "./conf/boostrap.conf";
 	public static final String DEFAULT_NIFI_PROPS_FILE = "./conf/nifi.properties";
+
+	public static final int MAX_RESTART_ATTEMPTS = 5;
+	public static final int STARTUP_WAIT_SECONDS = 60;
+	
+	public static final String SHUTDOWN_CMD = "SHUTDOWN";
+	public static final String PING_CMD = "PING";
+	
+	private volatile boolean autoRestartNiFi = true;
+	private volatile int ccPort = -1;
+	
+	private final Lock lock = new ReentrantLock();
+	private final Condition startupCondition = lock.newCondition();
+	
+	private final File bootstrapConfigFile;
+	
+	public RunNiFi(final File bootstrapConfigFile) {
+		this.bootstrapConfigFile = bootstrapConfigFile;
+	}
+	
+	private static void printUsage() {
+		System.out.println("Usage:");
+		System.out.println();
+		System.out.println("java org.apache.nifi.bootstrap.RunNiFi <command>");
+		System.out.println();
+		System.out.println("Valid commands include:");
+		System.out.println("");
+		System.out.println("Start : Start a new instance of Apache NiFi");
+		System.out.println("Stop : Stop a running instance of Apache NiFi");
+		System.out.println("Status : Determine if there is a running instance of Apache NiFi");
+		System.out.println();
+	}
 	
-	@SuppressWarnings({ "rawtypes", "unchecked" })
 	public static void main(final String[] args) throws IOException, InterruptedException {
-		final ProcessBuilder builder = new ProcessBuilder();
-
-		String configFilename = (args.length > 0) ? args[0] : System.getProperty("org.apache.nifi.boostrap.config.file");
+		if ( args.length != 1 ) {
+			printUsage();
+			return;
+		}
+		
+		switch (args[0].toLowerCase()) {
+			case "start":
+			case "stop":
+			case "status":
+				break;
+			default:
+				System.out.println("Invalid argument: " + args[0]);
+				System.out.println();
+				printUsage();
+				return;
+		}
+		
+		String configFilename = System.getProperty("org.apache.nifi.boostrap.config.file");
 		
 		if ( configFilename == null ) {
 			final String nifiHome = System.getenv("NIFI_HOME");
@@ -50,12 +123,122 @@ public class RunNiFi {
 		}
 		
 		final File configFile = new File(configFilename);
-		if ( !configFile.exists() ) {
+		
+		final RunNiFi runNiFi = new RunNiFi(configFile);
+		
+		switch (args[0].toLowerCase()) {
+			case "start":
+				runNiFi.start();
+				break;
+			case "stop":
+				runNiFi.stop();
+				break;
+			case "status":
+				runNiFi.status();
+				break;
+		}
+	}
+	
+	
+	public File getStatusFile() {
+		final File rootDir = bootstrapConfigFile.getParentFile();
+		final File statusFile = new File(rootDir, "nifi.port");
+		return statusFile;
+	}
+
+	private Integer getCurrentPort() throws IOException {
+		try {
+			final File statusFile = getStatusFile();
+			final byte[] info = Files.readAllBytes(statusFile.toPath());
+			final String text = new String(info);
+			
+			final int port = Integer.parseInt(text);
+			
+			try (final Socket socket = new Socket("localhost", port)) {
+				final OutputStream out = socket.getOutputStream();
+				out.write((PING_CMD + "\n").getBytes(StandardCharsets.UTF_8));
+				out.flush();
+				
+				final InputStream in = socket.getInputStream();
+				final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+				final String response = reader.readLine();
+				if ( response.equals(PING_CMD) ) {
+					return port;
+				}
+			} catch (final IOException ioe) {
+				System.out.println("Found NiFi instance info at " + statusFile + " but information appears to be stale. Removing file.");
+				if ( !statusFile.delete() ) {
+					System.err.println("Unable to remove status file");
+				}
+				
+				throw ioe;
+			}
+		} catch (final Exception e) {
+			return null;
+		}
+		
+		return null;
+	}
+	
+	
+	public void status() throws IOException {
+		final Integer port = getCurrentPort();
+		if ( port == null ) {
+			System.out.println("Apache NiFi does not appear to be running");
+		} else {
+			System.out.println("Apache NiFi is currently running, listening on port " + port);
+		}
+		return;
+	}
+	
+	
+	public void stop() throws IOException {
+		final Integer port = getCurrentPort();
+		if ( port == null ) {
+			System.out.println("Apache NiFi is not currently running");
+			return;
+		}
+		
+		try (final Socket socket = new Socket()) {
+			socket.setSoTimeout(60000);
+			socket.connect(new InetSocketAddress("localhost", port));
+			socket.setSoTimeout(60000);
+			
+			final OutputStream out = socket.getOutputStream();
+			out.write((SHUTDOWN_CMD + "\n").getBytes(StandardCharsets.UTF_8));
+			out.flush();
+			
+			final InputStream in = socket.getInputStream();
+			final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+			final String response = reader.readLine();
+			if ( SHUTDOWN_CMD.equals(response) ) {
+				System.out.println("Apache NiFi has accepted the Shutdown Command and is shutting down now");
+			} else {
+				System.err.println("When sending SHUTDOWN command to NiFi, got unexpected response " + response);
+			}
+		} catch (final IOException ioe) {
+			System.err.println("Failed to communicate with Apache NiFi");
+			return;
+		}
+	}
+	
+	
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public void start() throws IOException, InterruptedException {
+		final Integer port = getCurrentPort();
+		if ( port != null ) {
+			System.out.println("Apache NiFi is already running, listening on port " + port);
+			return;
+		}
+		
+		final ProcessBuilder builder = new ProcessBuilder();
+
+		if ( !bootstrapConfigFile.exists() ) {
 			throw new FileNotFoundException(DEFAULT_CONFIG_FILE);
 		}
 		
 		final Properties properties = new Properties();
-		try (final FileInputStream fis = new FileInputStream(configFile)) {
+		try (final FileInputStream fis = new FileInputStream(bootstrapConfigFile)) {
 			properties.load(fis);
 		}
 		
@@ -136,32 +319,67 @@ public class RunNiFi {
 			javaCmd = "java";
 		}
 		
+		final NiFiListener listener = new NiFiListener();
+		final int listenPort = listener.start(this);
+		
 		final List<String> cmd = new ArrayList<>();
 		cmd.add(javaCmd);
 		cmd.add("-classpath");
 		cmd.add(classPath);
 		cmd.addAll(javaAdditionalArgs);
 		cmd.add("-Dnifi.properties.file.path=" + nifiPropsFilename);
+		cmd.add("-Dnifi.bootstrap.listen.port=" + listenPort);
 		cmd.add("org.apache.nifi.NiFi");
 		
-		builder.command(cmd).inheritIO();
+		builder.command(cmd);
 		
 		final StringBuilder cmdBuilder = new StringBuilder();
 		for ( final String s : cmd ) {
 			cmdBuilder.append(s).append(" ");
 		}
+
 		System.out.println("Starting Apache NiFi...");
 		System.out.println("Working Directory: " + workingDir.getAbsolutePath());
 		System.out.println("Command: " + cmdBuilder.toString());
-
-		final Process proc = builder.start();
-		Runtime.getRuntime().addShutdownHook(new ShutdownHook(proc));
-		final int statusCode = proc.waitFor();
-		System.out.println("Apache NiFi exited with Status Code " + statusCode);
+		
+		builder.start();
+		boolean started = waitForStart();
+		
+		if ( started ) {
+			System.out.println("Successfully started Apache NiFi");
+		} else {
+			System.err.println("Apache NiFi does not appear to have started");
+		}
+		
+		listener.stop();
 	}
 	
 	
-	private static File getFile(final String filename, final File workingDir) {
+	private boolean waitForStart() {
+		lock.lock();
+		try {
+			final long startTime = System.nanoTime();
+			
+			while ( ccPort < 1 ) {
+				try {
+					startupCondition.await(1, TimeUnit.SECONDS);
+				} catch (final InterruptedException ie) {
+					return false;
+				}
+				
+				final long waitNanos = System.nanoTime() - startTime;
+				final long waitSeconds = TimeUnit.NANOSECONDS.toSeconds(waitNanos);
+				if (waitSeconds > STARTUP_WAIT_SECONDS) {
+					return false;
+				}
+			}
+		} finally {
+			lock.unlock();
+		}
+		return true;
+	}
+	
+	private File getFile(final String filename, final File workingDir) {
 		File libDir = new File(filename);
 		if ( !libDir.isAbsolute() ) {
 			libDir = new File(workingDir, filename);
@@ -170,7 +388,29 @@ public class RunNiFi {
 		return libDir;
 	}
 	
-	private static String replaceNull(final String value, final String replacement) {
+	private String replaceNull(final String value, final String replacement) {
 		return (value == null) ? replacement : value;
 	}
+	
+	void setAutoRestartNiFi(final boolean restart) {
+		this.autoRestartNiFi = restart;
+	}
+	
+	void setNiFiCommandControlPort(final int port) {
+		this.ccPort = port;
+
+		final File statusFile = getStatusFile();
+		try (final FileOutputStream fos = new FileOutputStream(statusFile)) {
+			fos.write(String.valueOf(port).getBytes(StandardCharsets.UTF_8));
+			fos.getFD().sync();
+		} catch (final IOException ioe) {
+			System.err.println("Apache NiFi has started but failed to persist NiFi Port information to " + statusFile.getAbsolutePath() + " due to " + ioe);
+		}
+		
+		System.out.println("Apache NiFi now running and listening for requests on port " + port);
+	}
+	
+	int getNiFiCommandControlPort() {
+		return this.ccPort;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
index 55e1f45..142d984 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
@@ -1,14 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package org.apache.nifi.bootstrap;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+
 public class ShutdownHook extends Thread {
 	private final Process nifiProcess;
+	private final RunNiFi runner;
+	
+	public static final int WAIT_SECONDS = 10;
 	
-	public ShutdownHook(final Process nifiProcess) {
+	public ShutdownHook(final Process nifiProcess, final RunNiFi runner) {
 		this.nifiProcess = nifiProcess;
+		this.runner = runner;
 	}
 	
 	@Override
 	public void run() {
+		runner.setAutoRestartNiFi(false);
+		final int ccPort = runner.getNiFiCommandControlPort();
+		if ( ccPort > 0 ) {
+			System.out.println("Initiating Shutdown of NiFi...");
+			
+			try {
+				final Socket socket = new Socket("localhost", ccPort);
+				final OutputStream out = socket.getOutputStream();
+				out.write("SHUTDOWN\n".getBytes(StandardCharsets.UTF_8));
+				out.flush();
+				
+				socket.close();
+			} catch (final IOException ioe) {
+				System.out.println("Failed to Shutdown NiFi due to " + ioe);
+			}
+		}
+		
+		try {
+			nifiProcess.waitFor(WAIT_SECONDS, TimeUnit.SECONDS);
+		} catch (final InterruptedException ie) {
+		}
+
+		if ( nifiProcess.isAlive() ) {
+			System.out.println("NiFi has not finished shutting down after " + WAIT_SECONDS + " seconds. Killing process.");
+		}
 		nifiProcess.destroy();
+		
+		final File statusFile = runner.getStatusFile();
+		if ( !statusFile.delete() ) {
+			System.err.println("Failed to delete status file " + statusFile.getAbsolutePath());
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/64657049/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/exception/InvalidCommandException.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/exception/InvalidCommandException.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/exception/InvalidCommandException.java
new file mode 100644
index 0000000..962aa1c
--- /dev/null
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/exception/InvalidCommandException.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.bootstrap.exception;
+
+public class InvalidCommandException extends Exception {
+	private static final long serialVersionUID = 1L;
+
+	public InvalidCommandException() {
+		super();
+	}
+	
+	public InvalidCommandException(final String message) {
+		super(message);
+	}
+	
+	public InvalidCommandException(final Throwable t) {
+		super(t);
+	}
+	
+	public InvalidCommandException(final String message, final Throwable t) {
+		super(message, t);
+	}
+}


[26/28] incubator-nifi git commit: NIFI-27: - Latest version of codemirror.

Posted by mc...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/9180b7d4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror-compressed.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror-compressed.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror-compressed.js
new file mode 100644
index 0000000..11b3fbc
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/codemirror/lib/codemirror-compressed.js
@@ -0,0 +1,16 @@
+/* CodeMirror - Minified & Bundled
+   Generated on 12/10/2014 with http://codemirror.net/doc/compress.html
+   Version: 4.8
+
+   CodeMirror Library:
+   - codemirror.js
+   Add-ons:
+   - matchbrackets.js
+   - show-hint.js
+ */
+
+!function(a){if("object"==typeof exports&&"object"==typeof module)module.exports=a();else{if("function"==typeof define&&define.amd)return define([],a);this.CodeMirror=a()}}(function(){"use strict";function w(a,b){if(!(this instanceof w))return new w(a,b);this.options=b=b?Qg(b):{},Qg(ie,b,!1),J(b);var c=b.value;"string"==typeof c&&(c=new Lf(c,b.mode)),this.doc=c;var f=this.display=new x(a,c);f.wrapper.CodeMirror=this,F(this),D(this),b.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),b.autofocus&&!o&&_c(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,draggingText:!1,highlight:new Gg,keySeq:null},d&&11>e&&setTimeout(Rg($c,this,!0),20),cd(this),ih(),Ac(this),this.curOp.forceUpdate=!0,Pf(this,c),b.autofocus&&!o||bh()==f.input?setTimeout(Rg(Hd,this),20):Id(this);for(var g in je)je.hasOwnProperty(g)&&je[g](this,b[g],le);P(this);for(var h=0;h<pe.length;++h)pe[h](this);Cc(this)}function x(a,b){var c
 =this,g=c.input=Yg("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em; outline: none");f?g.style.width="1000px":g.setAttribute("wrap","off"),n&&(g.style.border="1px solid black"),g.setAttribute("autocorrect","off"),g.setAttribute("autocapitalize","off"),g.setAttribute("spellcheck","false"),c.inputDiv=Yg("div",[g],null,"overflow: hidden; position: relative; width: 3px; height: 0px;"),c.scrollbarH=Yg("div",[Yg("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar"),c.scrollbarV=Yg("div",[Yg("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),c.scrollbarFiller=Yg("div",null,"CodeMirror-scrollbar-filler"),c.gutterFiller=Yg("div",null,"CodeMirror-gutter-filler"),c.lineDiv=Yg("div",null,"CodeMirror-code"),c.selectionDiv=Yg("div",null,null,"position: relative; z-index: 1"),c.cursorDiv=Yg("div",null,"CodeMirror-cursors"),c.measure=Yg("div",null,"CodeMirror-measure"),c.lineMeasure=Yg("div",null,"CodeMirror-measure"),c.lineSpace=Yg("div",[
 c.measure,c.lineMeasure,c.selectionDiv,c.cursorDiv,c.lineDiv],null,"position: relative; outline: none"),c.mover=Yg("div",[Yg("div",[c.lineSpace],"CodeMirror-lines")],null,"position: relative"),c.sizer=Yg("div",[c.mover],"CodeMirror-sizer"),c.heightForcer=Yg("div",null,null,"position: absolute; height: "+Bg+"px; width: 1px;"),c.gutters=Yg("div",null,"CodeMirror-gutters"),c.lineGutter=null,c.scroller=Yg("div",[c.sizer,c.heightForcer,c.gutters],"CodeMirror-scroll"),c.scroller.setAttribute("tabIndex","-1"),c.wrapper=Yg("div",[c.inputDiv,c.scrollbarH,c.scrollbarV,c.scrollbarFiller,c.gutterFiller,c.scroller],"CodeMirror"),d&&8>e&&(c.gutters.style.zIndex=-1,c.scroller.style.paddingRight=0),n&&(g.style.width="0px"),f||(c.scroller.draggable=!0),k&&(c.inputDiv.style.height="1px",c.inputDiv.style.position="absolute"),d&&8>e&&(c.scrollbarH.style.minHeight=c.scrollbarV.style.minWidth="18px"),a&&(a.appendChild?a.appendChild(c.wrapper):a(c.wrapper)),c.viewFrom=c.viewTo=b.first,c.view=[],c.external
 Measured=null,c.viewOffset=0,c.lastWrapHeight=c.lastWrapWidth=0,c.updateLineNumbers=null,c.lineNumWidth=c.lineNumInnerWidth=c.lineNumChars=null,c.prevInput="",c.alignWidgets=!1,c.pollingFast=!1,c.poll=new Gg,c.cachedCharWidth=c.cachedTextHeight=c.cachedPaddingH=null,c.inaccurateSelection=!1,c.maxLine=null,c.maxLineLength=0,c.maxLineChanged=!1,c.wheelDX=c.wheelDY=c.wheelStartX=c.wheelStartY=null,c.shift=!1,c.selForContextMenu=null}function y(a){a.doc.mode=w.getMode(a.options,a.doc.modeOption),z(a)}function z(a){a.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),a.doc.frontier=a.doc.first,Tb(a,100),a.state.modeGen++,a.curOp&&Pc(a)}function A(a){a.options.lineWrapping?(eh(a.display.wrapper,"CodeMirror-wrap"),a.display.sizer.style.minWidth=""):(dh(a.display.wrapper,"CodeMirror-wrap"),I(a)),C(a),Pc(a),kc(a),setTimeout(function(){M(a)},100)}function B(a){var b=wc(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/xc(a.displ
 ay)-3);return function(e){if(ef(a.doc,e))return 0;var f=0;if(e.widgets)for(var g=0;g<e.widgets.length;g++)e.widgets[g].height&&(f+=e.widgets[g].height);return c?f+(Math.ceil(e.text.length/d)||1)*b:f+b}}function C(a){var b=a.doc,c=B(a);b.iter(function(a){var b=c(a);b!=a.height&&Tf(a,b)})}function D(a){a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+a.options.theme.replace(/(^|\s)\s*/g," cm-s-"),kc(a)}function E(a){F(a),Pc(a),setTimeout(function(){O(a)},20)}function F(a){var b=a.display.gutters,c=a.options.gutters;$g(b);for(var d=0;d<c.length;++d){var e=c[d],f=b.appendChild(Yg("div",null,"CodeMirror-gutter "+e));"CodeMirror-linenumbers"==e&&(a.display.lineGutter=f,f.style.width=(a.display.lineNumWidth||1)+"px")}b.style.display=d?"":"none",G(a)}function G(a){var b=a.display.gutters.offsetWidth;a.display.sizer.style.marginLeft=b+"px",a.display.scrollbarH.style.left=a.options.fixedGutter?b+"px":0}function H(a){if(0==a.height)return 0;for(var c,b=a.text.
 length,d=a;c=Ze(d);){var e=c.find(0,!0);d=e.from.line,b+=e.from.ch-e.to.ch}for(d=a;c=$e(d);){var e=c.find(0,!0);b-=d.text.length-e.from.ch,d=e.to.line,b+=d.text.length-e.to.ch}return b}function I(a){var b=a.display,c=a.doc;b.maxLine=Qf(c,c.first),b.maxLineLength=H(b.maxLine),b.maxLineChanged=!0,c.iter(function(a){var c=H(a);c>b.maxLineLength&&(b.maxLineLength=c,b.maxLine=a)})}function J(a){var b=Ng(a.gutters,"CodeMirror-linenumbers");-1==b&&a.lineNumbers?a.gutters=a.gutters.concat(["CodeMirror-linenumbers"]):b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function K(a){return a.display.scroller.clientHeight-a.display.wrapper.clientHeight<Bg-3}function L(a){var b=a.display.scroller;return{clientHeight:b.clientHeight,barHeight:a.display.scrollbarV.clientHeight,scrollWidth:b.scrollWidth,clientWidth:b.clientWidth,hScrollbarTakesSpace:K(a),barWidth:a.display.scrollbarH.clientWidth,docHeight:Math.round(a.doc.height+Yb(a.display))}}function M(a,b){b||(b=L(a));var
  c=a.display,d=mh(c.measure),e=b.docHeight+Bg,f=b.scrollWidth>b.clientWidth;f&&b.scrollWidth<=b.clientWidth+1&&d>0&&!b.hScrollbarTakesSpace&&(f=!1);var g=e>b.clientHeight;if(g?(c.scrollbarV.style.display="block",c.scrollbarV.style.bottom=f?d+"px":"0",c.scrollbarV.firstChild.style.height=Math.max(0,e-b.clientHeight+(b.barHeight||c.scrollbarV.clientHeight))+"px"):(c.scrollbarV.style.display="",c.scrollbarV.firstChild.style.height="0"),f?(c.scrollbarH.style.display="block",c.scrollbarH.style.right=g?d+"px":"0",c.scrollbarH.firstChild.style.width=b.scrollWidth-b.clientWidth+(b.barWidth||c.scrollbarH.clientWidth)+"px"):(c.scrollbarH.style.display="",c.scrollbarH.firstChild.style.width="0"),f&&g?(c.scrollbarFiller.style.display="block",c.scrollbarFiller.style.height=c.scrollbarFiller.style.width=d+"px"):c.scrollbarFiller.style.display="",f&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(c.gutterFiller.style.display="block",c.gutterFiller.style.height=d+"px",c.gutterFiller.st
 yle.width=c.gutters.offsetWidth+"px"):c.gutterFiller.style.display="",!a.state.checkedOverlayScrollbar&&b.clientHeight>0){if(0===d){var h=p&&!l?"12px":"18px";c.scrollbarV.style.minWidth=c.scrollbarH.style.minHeight=h;var i=function(b){pg(b)!=c.scrollbarV&&pg(b)!=c.scrollbarH&&Kc(a,gd)(b)};rg(c.scrollbarV,"mousedown",i),rg(c.scrollbarH,"mousedown",i)}a.state.checkedOverlayScrollbar=!0}}function N(a,b,c){var d=c&&null!=c.top?Math.max(0,c.top):a.scroller.scrollTop;d=Math.floor(d-Xb(a));var e=c&&null!=c.bottom?c.bottom:d+a.wrapper.clientHeight,f=Vf(b,d),g=Vf(b,e);if(c&&c.ensure){var h=c.ensure.from.line,i=c.ensure.to.line;if(f>h)return{from:h,to:Vf(b,Wf(Qf(b,h))+a.wrapper.clientHeight)};if(Math.min(i,b.lastLine())>=g)return{from:Vf(b,Wf(Qf(b,i))-a.wrapper.clientHeight),to:i}}return{from:f,to:Math.max(g,f+1)}}function O(a){var b=a.display,c=b.view;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var d=R(b)-b.scroller.scrollLeft+a.doc.scrollLeft,e=b.gutters.offsetWidth,
 f=d+"px",g=0;g<c.length;g++)if(!c[g].hidden){a.options.fixedGutter&&c[g].gutter&&(c[g].gutter.style.left=f);var h=c[g].alignable;if(h)for(var i=0;i<h.length;i++)h[i].style.left=f}a.options.fixedGutter&&(b.gutters.style.left=d+e+"px")}}function P(a){if(!a.options.lineNumbers)return!1;var b=a.doc,c=Q(a.options,b.first+b.size-1),d=a.display;if(c.length!=d.lineNumChars){var e=d.measure.appendChild(Yg("div",[Yg("div",c)],"CodeMirror-linenumber CodeMirror-gutter-elt")),f=e.firstChild.offsetWidth,g=e.offsetWidth-f;return d.lineGutter.style.width="",d.lineNumInnerWidth=Math.max(f,d.lineGutter.offsetWidth-g),d.lineNumWidth=d.lineNumInnerWidth+g,d.lineNumChars=d.lineNumInnerWidth?c.length:-1,d.lineGutter.style.width=d.lineNumWidth+"px",G(a),!0}return!1}function Q(a,b){return String(a.lineNumberFormatter(b+a.firstLineNumber))}function R(a){return a.scroller.getBoundingClientRect().left-a.sizer.getBoundingClientRect().left}function S(a,b,c){var d=a.display;this.viewport=b,this.visible=N(d,a.doc
 ,b),this.editorIsHidden=!d.wrapper.offsetWidth,this.wrapperHeight=d.wrapper.clientHeight,this.wrapperWidth=d.wrapper.clientWidth,this.oldViewFrom=d.viewFrom,this.oldViewTo=d.viewTo,this.oldScrollerWidth=d.scroller.clientWidth,this.force=c,this.dims=$(a)}function T(a,b){var c=a.display,d=a.doc;if(b.editorIsHidden)return Rc(a),!1;if(!b.force&&b.visible.from>=c.viewFrom&&b.visible.to<=c.viewTo&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo)&&0==Vc(a))return!1;P(a)&&(Rc(a),b.dims=$(a));var e=d.first+d.size,f=Math.max(b.visible.from-a.options.viewportMargin,d.first),g=Math.min(e,b.visible.to+a.options.viewportMargin);c.viewFrom<f&&f-c.viewFrom<20&&(f=Math.max(d.first,c.viewFrom)),c.viewTo>g&&c.viewTo-g<20&&(g=Math.min(e,c.viewTo)),v&&(f=cf(a.doc,f),g=df(a.doc,g));var h=f!=c.viewFrom||g!=c.viewTo||c.lastWrapHeight!=b.wrapperHeight||c.lastWrapWidth!=b.wrapperWidth;Uc(a,f,g),c.viewOffset=Wf(Qf(a.doc,c.viewFrom)),a.display.mover.style.top=c.viewOffset+"px";var i=Vc(a);if(!h&&0==i
 &&!b.force&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo))return!1;var j=bh();return i>4&&(c.lineDiv.style.display="none"),_(a,c.updateLineNumbers,b.dims),i>4&&(c.lineDiv.style.display=""),j&&bh()!=j&&j.offsetHeight&&j.focus(),$g(c.cursorDiv),$g(c.selectionDiv),h&&(c.lastWrapHeight=b.wrapperHeight,c.lastWrapWidth=b.wrapperWidth,Tb(a,400)),c.updateLineNumbers=null,!0}function U(a,b){for(var c=b.force,d=b.viewport,e=!0;;e=!1){if(e&&a.options.lineWrapping&&b.oldScrollerWidth!=a.display.scroller.clientWidth)c=!0;else if(c=!1,d&&null!=d.top&&(d={top:Math.min(a.doc.height+Yb(a.display)-Bg-a.display.scroller.clientHeight,d.top)}),b.visible=N(a.display,a.doc,d),b.visible.from>=a.display.viewFrom&&b.visible.to<=a.display.viewTo)break;if(!T(a,b))break;Y(a);var f=L(a);Pb(a),W(a,f),M(a,f)}vg(a,"update",a),(a.display.viewFrom!=b.oldViewFrom||a.display.viewTo!=b.oldViewTo)&&vg(a,"viewportChange",a,a.display.viewFrom,a.display.viewTo)}function V(a,b){var c=new S(a,b);if(T(a,c)){Y(a),U
 (a,c);var d=L(a);Pb(a),W(a,d),M(a,d)}}function W(a,b){a.display.sizer.style.minHeight=a.display.heightForcer.style.top=b.docHeight+"px",a.display.gutters.style.height=Math.max(b.docHeight,b.clientHeight-Bg)+"px"}function X(a,b){a.display.sizer.offsetWidth+a.display.gutters.offsetWidth<a.display.scroller.clientWidth-1&&(a.display.sizer.style.minHeight=a.display.heightForcer.style.top="0px",a.display.gutters.style.height=b.docHeight+"px")}function Y(a){for(var b=a.display,c=b.lineDiv.offsetTop,f=0;f<b.view.length;f++){var h,g=b.view[f];if(!g.hidden){if(d&&8>e){var i=g.node.offsetTop+g.node.offsetHeight;h=i-c,c=i}else{var j=g.node.getBoundingClientRect();h=j.bottom-j.top}var k=g.line.height-h;if(2>h&&(h=wc(b)),(k>.001||-.001>k)&&(Tf(g.line,h),Z(g.line),g.rest))for(var l=0;l<g.rest.length;l++)Z(g.rest[l])}}}function Z(a){if(a.widgets)for(var b=0;b<a.widgets.length;++b)a.widgets[b].height=a.widgets[b].node.offsetHeight}function $(a){for(var b=a.display,c={},d={},e=b.gutters.clientLeft,f=
 b.gutters.firstChild,g=0;f;f=f.nextSibling,++g)c[a.options.gutters[g]]=f.offsetLeft+f.clientLeft+e,d[a.options.gutters[g]]=f.clientWidth;return{fixedPos:R(b),gutterTotalWidth:b.gutters.offsetWidth,gutterLeft:c,gutterWidth:d,wrapperWidth:b.wrapper.clientWidth}}function _(a,b,c){function i(b){var c=b.nextSibling;return f&&p&&a.display.currentWheelTarget==b?b.style.display="none":b.parentNode.removeChild(b),c}for(var d=a.display,e=a.options.lineNumbers,g=d.lineDiv,h=g.firstChild,j=d.view,k=d.viewFrom,l=0;l<j.length;l++){var m=j[l];if(m.hidden);else if(m.node){for(;h!=m.node;)h=i(h);var o=e&&null!=b&&k>=b&&m.lineNumber;m.changes&&(Ng(m.changes,"gutter")>-1&&(o=!1),ab(a,m,k,c)),o&&($g(m.lineNumber),m.lineNumber.appendChild(document.createTextNode(Q(a.options,k)))),h=m.node.nextSibling}else{var n=ib(a,m,k,c);g.insertBefore(n,h)}k+=m.size}for(;h;)h=i(h)}function ab(a,b,c,d){for(var e=0;e<b.changes.length;e++){var f=b.changes[e];"text"==f?eb(a,b):"gutter"==f?gb(a,b,c,d):"class"==f?fb(b):"wi
 dget"==f&&hb(b,d)}b.changes=null}function bb(a){return a.node==a.text&&(a.node=Yg("div",null,null,"position: relative"),a.text.parentNode&&a.text.parentNode.replaceChild(a.node,a.text),a.node.appendChild(a.text),d&&8>e&&(a.node.style.zIndex=2)),a.node}function cb(a){var b=a.bgClass?a.bgClass+" "+(a.line.bgClass||""):a.line.bgClass;if(b&&(b+=" CodeMirror-linebackground"),a.background)b?a.background.className=b:(a.background.parentNode.removeChild(a.background),a.background=null);else if(b){var c=bb(a);a.background=c.insertBefore(Yg("div",null,b),c.firstChild)}}function db(a,b){var c=a.display.externalMeasured;return c&&c.line==b.line?(a.display.externalMeasured=null,b.measure=c.measure,c.built):zf(a,b)}function eb(a,b){var c=b.text.className,d=db(a,b);b.text==b.node&&(b.node=d.pre),b.text.parentNode.replaceChild(d.pre,b.text),b.text=d.pre,d.bgClass!=b.bgClass||d.textClass!=b.textClass?(b.bgClass=d.bgClass,b.textClass=d.textClass,fb(b)):c&&(b.text.className=c)}function fb(a){cb(a),a.l
 ine.wrapClass?bb(a).className=a.line.wrapClass:a.node!=a.text&&(a.node.className="");var b=a.textClass?a.textClass+" "+(a.line.textClass||""):a.line.textClass;a.text.className=b||""}function gb(a,b,c,d){b.gutter&&(b.node.removeChild(b.gutter),b.gutter=null);var e=b.line.gutterMarkers;if(a.options.lineNumbers||e){var f=bb(b),g=b.gutter=f.insertBefore(Yg("div",null,"CodeMirror-gutter-wrapper","left: "+(a.options.fixedGutter?d.fixedPos:-d.gutterTotalWidth)+"px; width: "+d.gutterTotalWidth+"px"),b.text);if(b.line.gutterClass&&(g.className+=" "+b.line.gutterClass),!a.options.lineNumbers||e&&e["CodeMirror-linenumbers"]||(b.lineNumber=g.appendChild(Yg("div",Q(a.options,c),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+d.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+a.display.lineNumInnerWidth+"px"))),e)for(var h=0;h<a.options.gutters.length;++h){var i=a.options.gutters[h],j=e.hasOwnProperty(i)&&e[i];j&&g.appendChild(Yg("div",[j],"CodeMirror-gutter-elt","left: "+d.gutterLeft[i]
 +"px; width: "+d.gutterWidth[i]+"px"))}}}function hb(a,b){a.alignable&&(a.alignable=null);for(var d,c=a.node.firstChild;c;c=d){var d=c.nextSibling;"CodeMirror-linewidget"==c.className&&a.node.removeChild(c)}jb(a,b)}function ib(a,b,c,d){var e=db(a,b);return b.text=b.node=e.pre,e.bgClass&&(b.bgClass=e.bgClass),e.textClass&&(b.textClass=e.textClass),fb(b),gb(a,b,c,d),jb(b,d),b.node}function jb(a,b){if(kb(a.line,a,b,!0),a.rest)for(var c=0;c<a.rest.length;c++)kb(a.rest[c],a,b,!1)}function kb(a,b,c,d){if(a.widgets)for(var e=bb(b),f=0,g=a.widgets;f<g.length;++f){var h=g[f],i=Yg("div",[h.node],"CodeMirror-linewidget");h.handleMouseEvents||(i.ignoreEvents=!0),lb(h,i,b,c),d&&h.above?e.insertBefore(i,b.gutter||b.text):e.appendChild(i),vg(h,"redraw")}}function lb(a,b,c,d){if(a.noHScroll){(c.alignable||(c.alignable=[])).push(b);var e=d.wrapperWidth;b.style.left=d.fixedPos+"px",a.coverGutter||(e-=d.gutterTotalWidth,b.style.paddingLeft=d.gutterTotalWidth+"px"),b.style.width=e+"px"}a.coverGutter&&(
 b.style.zIndex=5,b.style.position="relative",a.noHScroll||(b.style.marginLeft=-d.gutterTotalWidth+"px"))}function ob(a){return mb(a.line,a.ch)}function pb(a,b){return nb(a,b)<0?b:a}function qb(a,b){return nb(a,b)<0?a:b}function rb(a,b){this.ranges=a,this.primIndex=b}function sb(a,b){this.anchor=a,this.head=b}function tb(a,b){var c=a[b];a.sort(function(a,b){return nb(a.from(),b.from())}),b=Ng(a,c);for(var d=1;d<a.length;d++){var e=a[d],f=a[d-1];if(nb(f.to(),e.from())>=0){var g=qb(f.from(),e.from()),h=pb(f.to(),e.to()),i=f.empty()?e.from()==e.head:f.from()==f.head;b>=d&&--b,a.splice(--d,2,new sb(i?h:g,i?g:h))}}return new rb(a,b)}function ub(a,b){return new rb([new sb(a,b||a)],0)}function vb(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function wb(a,b){if(b.line<a.first)return mb(a.first,0);var c=a.first+a.size-1;return b.line>c?mb(c,Qf(a,c).text.length):xb(b,Qf(a,b.line).text.length)}function xb(a,b){var c=a.ch;return null==c||c>b?mb(a.line,b):0>c?mb(a.line,0):a}function
  yb(a,b){return b>=a.first&&b<a.first+a.size}function zb(a,b){for(var c=[],d=0;d<b.length;d++)c[d]=wb(a,b[d]);return c}function Ab(a,b,c,d){if(a.cm&&a.cm.display.shift||a.extend){var e=b.anchor;if(d){var f=nb(c,e)<0;f!=nb(d,e)<0?(e=c,c=d):f!=nb(c,d)<0&&(c=d)}return new sb(e,c)}return new sb(d||c,c)}function Bb(a,b,c,d){Hb(a,new rb([Ab(a,a.sel.primary(),b,c)],0),d)}function Cb(a,b,c){for(var d=[],e=0;e<a.sel.ranges.length;e++)d[e]=Ab(a,a.sel.ranges[e],b[e],null);var f=tb(d,a.sel.primIndex);Hb(a,f,c)}function Db(a,b,c,d){var e=a.sel.ranges.slice(0);e[b]=c,Hb(a,tb(e,a.sel.primIndex),d)}function Eb(a,b,c,d){Hb(a,ub(b,c),d)}function Fb(a,b){var c={ranges:b.ranges,update:function(b){this.ranges=[];for(var c=0;c<b.length;c++)this.ranges[c]=new sb(wb(a,b[c].anchor),wb(a,b[c].head))}};return tg(a,"beforeSelectionChange",a,c),a.cm&&tg(a.cm,"beforeSelectionChange",a.cm,c),c.ranges!=b.ranges?tb(c.ranges,c.ranges.length-1):b}function Gb(a,b,c){var d=a.history.done,e=Lg(d);e&&e.ranges?(d[d.length
 -1]=b,Ib(a,b,c)):Hb(a,b,c)}function Hb(a,b,c){Ib(a,b,c),cg(a,a.sel,a.cm?a.cm.curOp.id:0/0,c)}function Ib(a,b,c){(zg(a,"beforeSelectionChange")||a.cm&&zg(a.cm,"beforeSelectionChange"))&&(b=Fb(a,b));var d=c&&c.bias||(nb(b.primary().head,a.sel.primary().head)<0?-1:1);Jb(a,Lb(a,b,d,!0)),c&&c.scroll===!1||!a.cm||be(a.cm)}function Jb(a,b){b.equals(a.sel)||(a.sel=b,a.cm&&(a.cm.curOp.updateInput=a.cm.curOp.selectionChanged=!0,yg(a.cm)),vg(a,"cursorActivity",a))}function Kb(a){Jb(a,Lb(a,a.sel,null,!1),Dg)}function Lb(a,b,c,d){for(var e,f=0;f<b.ranges.length;f++){var g=b.ranges[f],h=Mb(a,g.anchor,c,d),i=Mb(a,g.head,c,d);(e||h!=g.anchor||i!=g.head)&&(e||(e=b.ranges.slice(0,f)),e[f]=new sb(h,i))}return e?tb(e,b.primIndex):b}function Mb(a,b,c,d){var e=!1,f=b,g=c||1;a.cantEdit=!1;a:for(;;){var h=Qf(a,f.line);if(h.markedSpans)for(var i=0;i<h.markedSpans.length;++i){var j=h.markedSpans[i],k=j.marker;if((null==j.from||(k.inclusiveLeft?j.from<=f.ch:j.from<f.ch))&&(null==j.to||(k.inclusiveRight?j.to>=
 f.ch:j.to>f.ch))){if(d&&(tg(k,"beforeCursorEnter"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find(0>g?-1:1);if(0==nb(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?wb(a,mb(l.line-1)):null:l.ch>h.text.length&&(l=l.line<a.first+a.size-1?mb(l.line+1,0):null),!l)){if(e)return d?(a.cantEdit=!0,mb(a.first,0)):Mb(a,b,c,!0);e=!0,l=b,g=-g}f=l;continue a}}return f}}function Nb(a){for(var b=a.display,c=a.doc,d={},e=d.cursors=document.createDocumentFragment(),f=d.selection=document.createDocumentFragment(),g=0;g<c.sel.ranges.length;g++){var h=c.sel.ranges[g],i=h.empty();(i||a.options.showCursorWhenSelecting)&&Qb(a,h,e),i||Rb(a,h,f)}if(a.options.moveInputWithCursor){var j=qc(a,c.sel.primary().head,"div"),k=b.wrapper.getBoundingClientRect(),l=b.lineDiv.getBoundingClientRect();d.teTop=Math.max(0,Math.min(b.wrapper.clientHeight-10,j.top+l.top-k.top)),d.teLeft=Math.max(0,Math.min(b.wrapper.clientWidth-10,j.left+l.left-k.left))}return d}function Ob(a,b){_g(a.dis
 play.cursorDiv,b.cursors),_g(a.display.selectionDiv,b.selection),null!=b.teTop&&(a.display.inputDiv.style.top=b.teTop+"px",a.display.inputDiv.style.left=b.teLeft+"px")}function Pb(a){Ob(a,Nb(a))}function Qb(a,b,c){var d=qc(a,b.head,"div",null,null,!a.options.singleCursorHeightPerLine),e=c.appendChild(Yg("div","\xa0","CodeMirror-cursor"));if(e.style.left=d.left+"px",e.style.top=d.top+"px",e.style.height=Math.max(0,d.bottom-d.top)*a.options.cursorHeight+"px",d.other){var f=c.appendChild(Yg("div","\xa0","CodeMirror-cursor CodeMirror-secondarycursor"));f.style.display="",f.style.left=d.other.left+"px",f.style.top=d.other.top+"px",f.style.height=.85*(d.other.bottom-d.other.top)+"px"}}function Rb(a,b,c){function j(a,b,c,d){0>b&&(b=0),b=Math.round(b),d=Math.round(d),f.appendChild(Yg("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px; top: "+b+"px; width: "+(null==c?i-a:c)+"px; height: "+(d-b)+"px"))}function k(b,c,d){function m(c,d){return pc(a,mb(b,c),"div",f,d)}var k,l,f
 =Qf(e,b),g=f.text.length;return xh(Xf(f),c||0,null==d?g:d,function(a,b,e){var n,o,p,f=m(a,"left");if(a==b)n=f,o=p=f.left;else{if(n=m(b-1,"right"),"rtl"==e){var q=f;f=n,n=q}o=f.left,p=n.right}null==c&&0==a&&(o=h),n.top-f.top>3&&(j(o,f.top,null,f.bottom),o=h,f.bottom<n.top&&j(o,f.bottom,null,n.top)),null==d&&b==g&&(p=i),(!k||f.top<k.top||f.top==k.top&&f.left<k.left)&&(k=f),(!l||n.bottom>l.bottom||n.bottom==l.bottom&&n.right>l.right)&&(l=n),h+1>o&&(o=h),j(o,n.top,p-o,n.bottom)}),{start:k,end:l}}var d=a.display,e=a.doc,f=document.createDocumentFragment(),g=Zb(a.display),h=g.left,i=d.lineSpace.offsetWidth-g.right,l=b.from(),m=b.to();if(l.line==m.line)k(l.line,l.ch,m.ch);else{var n=Qf(e,l.line),o=Qf(e,m.line),p=af(n)==af(o),q=k(l.line,l.ch,p?n.text.length+1:null).end,r=k(m.line,p?0:null,m.ch).start;p&&(q.top<r.top-2?(j(q.right,q.top,null,q.bottom),j(h,r.top,r.left,r.bottom)):j(q.right,q.top,r.left-q.right,q.bottom)),q.bottom<r.top&&j(h,q.bottom,null,r.top)}c.appendChild(f)}function Sb(a){
 if(a.state.focused){var b=a.display;clearInterval(b.blinker);var c=!0;b.cursorDiv.style.visibility="",a.options.cursorBlinkRate>0?b.blinker=setInterval(function(){b.cursorDiv.style.visibility=(c=!c)?"":"hidden"},a.options.cursorBlinkRate):a.options.cursorBlinkRate<0&&(b.cursorDiv.style.visibility="hidden")}}function Tb(a,b){a.doc.mode.startState&&a.doc.frontier<a.display.viewTo&&a.state.highlight.set(b,Rg(Ub,a))}function Ub(a){var b=a.doc;if(b.frontier<b.first&&(b.frontier=b.first),!(b.frontier>=a.display.viewTo)){var c=+new Date+a.options.workTime,d=re(b.mode,Wb(a,b.frontier)),e=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.viewTo+500),function(f){if(b.frontier>=a.display.viewFrom){var g=f.styles,h=tf(a,f,d,!0);f.styles=h.styles;var i=f.styleClasses,j=h.classes;j?f.styleClasses=j:i&&(f.styleClasses=null);for(var k=!g||g.length!=f.styles.length||i!=j&&(!i||!j||i.bgClass!=j.bgClass||i.textClass!=j.textClass),l=0;!k&&l<g.length;++l)k=g[l]!=f.styles[l];k&&e.push(b.frontier),f.
 stateAfter=re(b.mode,d)}else vf(a,f.text,d),f.stateAfter=0==b.frontier%5?re(b.mode,d):null;return++b.frontier,+new Date>c?(Tb(a,a.options.workDelay),!0):void 0}),e.length&&Jc(a,function(){for(var b=0;b<e.length;b++)Qc(a,e[b],"text")})}}function Vb(a,b,c){for(var d,e,f=a.doc,g=c?-1:b-(a.doc.mode.innerMode?1e3:100),h=b;h>g;--h){if(h<=f.first)return f.first;var i=Qf(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=Hg(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function Wb(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=Vb(a,b,c),g=f>d.first&&Qf(d,f-1).stateAfter;return g=g?re(d.mode,g):se(d.mode),d.iter(f,b,function(c){vf(a,c.text,g);var h=f==b-1||0==f%5||f>=e.viewFrom&&f<e.viewTo;c.stateAfter=h?re(d.mode,g):null,++f}),c&&(d.frontier=f),g}function Xb(a){return a.lineSpace.offsetTop}function Yb(a){return a.mover.offsetHeight-a.lineSpace.offsetHeight}function Zb(a){if(a.cachedPaddingH)return a.cachedPaddingH;var b=_g(a.measure,Yg("pre
 ","x")),c=window.getComputedStyle?window.getComputedStyle(b):b.currentStyle,d={left:parseInt(c.paddingLeft),right:parseInt(c.paddingRight)};return isNaN(d.left)||isNaN(d.right)||(a.cachedPaddingH=d),d}function $b(a,b,c){var d=a.options.lineWrapping,e=d&&a.display.scroller.clientWidth;if(!b.measure.heights||d&&b.measure.width!=e){var f=b.measure.heights=[];if(d){b.measure.width=e;for(var g=b.text.firstChild.getClientRects(),h=0;h<g.length-1;h++){var i=g[h],j=g[h+1];Math.abs(i.bottom-j.bottom)>2&&f.push((i.bottom+j.top)/2-c.top)}}f.push(c.bottom-c.top)}}function _b(a,b,c){if(a.line==b)return{map:a.measure.map,cache:a.measure.cache};for(var d=0;d<a.rest.length;d++)if(a.rest[d]==b)return{map:a.measure.maps[d],cache:a.measure.caches[d]};for(var d=0;d<a.rest.length;d++)if(Uf(a.rest[d])>c)return{map:a.measure.maps[d],cache:a.measure.caches[d],before:!0}}function ac(a,b){b=af(b);var c=Uf(b),d=a.display.externalMeasured=new Nc(a.doc,b,c);d.lineN=c;var e=d.built=zf(a,d);return d.text=e.pre,_g
 (a.display.lineMeasure,e.pre),d}function bc(a,b,c,d){return ec(a,dc(a,b),c,d)}function cc(a,b){if(b>=a.display.viewFrom&&b<a.display.viewTo)return a.display.view[Sc(a,b)];var c=a.display.externalMeasured;return c&&b>=c.lineN&&b<c.lineN+c.size?c:void 0}function dc(a,b){var c=Uf(b),d=cc(a,c);d&&!d.text?d=null:d&&d.changes&&ab(a,d,c,$(a)),d||(d=ac(a,b));var e=_b(d,b,c);return{line:b,view:d,rect:null,map:e.map,cache:e.cache,before:e.before,hasHeights:!1}}function ec(a,b,c,d,e){b.before&&(c=-1);var g,f=c+(d||"");return b.cache.hasOwnProperty(f)?g=b.cache[f]:(b.rect||(b.rect=b.view.text.getBoundingClientRect()),b.hasHeights||($b(a,b.view,b.rect),b.hasHeights=!0),g=gc(a,b,c,d),g.bogus||(b.cache[f]=g)),{left:g.left,right:g.right,top:e?g.rtop:g.top,bottom:e?g.rbottom:g.bottom}}function gc(a,b,c,f){for(var h,i,j,k,g=b.map,l=0;l<g.length;l+=3){var m=g[l],n=g[l+1];if(m>c?(i=0,j=1,k="left"):n>c?(i=c-m,j=i+1):(l==g.length-3||c==n&&g[l+3]>c)&&(j=n-m,i=j-1,c>=n&&(k="right")),null!=i){if(h=g[l+2],m=
 =n&&f==(h.insertLeft?"left":"right")&&(k=f),"left"==f&&0==i)for(;l&&g[l-2]==g[l-3]&&g[l-1].insertLeft;)h=g[(l-=3)+2],k="left";if("right"==f&&i==n-m)for(;l<g.length-3&&g[l+3]==g[l+4]&&!g[l+5].insertLeft;)h=g[(l+=3)+2],k="right";break}}var o;if(3==h.nodeType){for(var l=0;4>l;l++){for(;i&&Xg(b.line.text.charAt(m+i));)--i;for(;n>m+j&&Xg(b.line.text.charAt(m+j));)++j;if(d&&9>e&&0==i&&j==n-m)o=h.parentNode.getBoundingClientRect();else if(d&&a.options.lineWrapping){var p=Zg(h,i,j).getClientRects();o=p.length?p["right"==f?p.length-1:0]:fc}else o=Zg(h,i,j).getBoundingClientRect()||fc;if(o.left||o.right||0==i)break;j=i,i-=1,k="right"}d&&11>e&&(o=hc(a.display.measure,o))}else{i>0&&(k=f="right");var p;o=a.options.lineWrapping&&(p=h.getClientRects()).length>1?p["right"==f?p.length-1:0]:h.getBoundingClientRect()}if(d&&9>e&&!i&&(!o||!o.left&&!o.right)){var q=h.parentNode.getClientRects()[0];o=q?{left:q.left,right:q.left+xc(a.display),top:q.top,bottom:q.bottom}:fc}for(var r=o.top-b.rect.top,s=o.bot
 tom-b.rect.top,t=(r+s)/2,u=b.view.measure.heights,l=0;l<u.length-1&&!(t<u[l]);l++);var v=l?u[l-1]:0,w=u[l],x={left:("right"==k?o.right:o.left)-b.rect.left,right:("left"==k?o.left:o.right)-b.rect.left,top:v,bottom:w};return o.left||o.right||(x.bogus=!0),a.options.singleCursorHeightPerLine||(x.rtop=r,x.rbottom=s),x}function hc(a,b){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!vh(a))return b;var c=screen.logicalXDPI/screen.deviceXDPI,d=screen.logicalYDPI/screen.deviceYDPI;return{left:b.left*c,right:b.right*c,top:b.top*d,bottom:b.bottom*d}}function ic(a){if(a.measure&&(a.measure.cache={},a.measure.heights=null,a.rest))for(var b=0;b<a.rest.length;b++)a.measure.caches[b]={}}function jc(a){a.display.externalMeasure=null,$g(a.display.lineMeasure);for(var b=0;b<a.display.view.length;b++)ic(a.display.view[b])}function kc(a){jc(a),a.display.cachedCharWidth=a.display.cachedTextHeight=a.display.cachedPaddingH=null,a.options.lineWrapping||(a.display.maxLine
 Changed=!0),a.display.lineNumChars=null}function lc(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function mc(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function nc(a,b,c,d){if(b.widgets)for(var e=0;e<b.widgets.length;++e)if(b.widgets[e].above){var f=jf(b.widgets[e]);c.top+=f,c.bottom+=f}if("line"==d)return c;d||(d="local");var g=Wf(b);if("local"==d?g+=Xb(a.display):g-=a.display.viewOffset,"page"==d||"window"==d){var h=a.display.lineSpace.getBoundingClientRect();g+=h.top+("window"==d?0:mc());var i=h.left+("window"==d?0:lc());c.left+=i,c.right+=i}return c.top+=g,c.bottom+=g,c}function oc(a,b,c){if("div"==c)return b;var d=b.left,e=b.top;if("page"==c)d-=lc(),e-=mc();else if("local"==c||!c){var f=a.display.sizer.getBoundingClientRect();d+=f.left,e+=f.top}var g=a.display.lineSpace.getBoundingClientRect();return{left:d-g.left,top:e-g.top}}function pc(a,b,c,d,e){return d||(d=Qf(a.doc,b.line)),nc(a,d,bc(a,d,b.ch,e),c)
 }function qc(a,b,c,d,e,f){function g(b,g){var h=ec(a,e,b,g?"right":"left",f);return g?h.left=h.right:h.right=h.left,nc(a,d,h,c)}function h(a,b){var c=i[b],d=c.level%2;return a==yh(c)&&b&&c.level<i[b-1].level?(c=i[--b],a=zh(c)-(c.level%2?0:1),d=!0):a==zh(c)&&b<i.length-1&&c.level<i[b+1].level&&(c=i[++b],a=yh(c)-c.level%2,d=!1),d&&a==c.to&&a>c.from?g(a-1):g(a,d)}d=d||Qf(a.doc,b.line),e||(e=dc(a,d));var i=Xf(d),j=b.ch;if(!i)return g(j);var k=Hh(i,j),l=h(j,k);return null!=Gh&&(l.other=h(j,Gh)),l}function rc(a,b){var c=0,b=wb(a.doc,b);a.options.lineWrapping||(c=xc(a.display)*b.ch);var d=Qf(a.doc,b.line),e=Wf(d)+Xb(a.display);return{left:c,right:c,top:e,bottom:e+d.height}}function sc(a,b,c,d){var e=mb(a,b);return e.xRel=d,c&&(e.outside=!0),e}function tc(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return sc(d.first,0,!0,-1);var e=Vf(d,c),f=d.first+d.size-1;if(e>f)return sc(d.first+d.size-1,Qf(d,f).text.length,!0,1);0>b&&(b=0);for(var g=Qf(d,e);;){var h=uc(a,g,e,b,c),i=$e(g),j=i&&i.fi
 nd(0,!0);if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=Uf(g=j.to.line)}}function uc(a,b,c,d,e){function j(d){var e=qc(a,mb(c,d),"line",b,i);return g=!0,f>e.bottom?e.left-h:f<e.top?e.left+h:(g=!1,e.left)}var f=e-Wf(b),g=!1,h=2*a.display.wrapper.clientWidth,i=dc(a,b),k=Xf(b),l=b.text.length,m=Ah(b),n=Bh(b),o=j(m),p=g,q=j(n),r=g;if(d>q)return sc(c,n,r,1);for(;;){if(k?n==m||n==Jh(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);Xg(b.text.charAt(s));)++s;var u=sc(c,s,s==m?p:r,-1>t?-1:t>1?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=Jh(b,w,1)}var y=j(w);y>d?(n=w,q=y,(r=g)&&(q+=1e3),l=v):(m=w,o=y,p=g,l-=v)}}function wc(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==vc){vc=Yg("pre");for(var b=0;49>b;++b)vc.appendChild(document.createTextNode("x")),vc.appendChild(Yg("br"));vc.appendChild(document.createTextNode("x"))}_g(a.measure,vc);var c=vc.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),$g(a.measure),c||1}function
  xc(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=Yg("span","xxxxxxxxxx"),c=Yg("pre",[b]);_g(a.measure,c);var d=b.getBoundingClientRect(),e=(d.right-d.left)/10;return e>2&&(a.cachedCharWidth=e),e||10}function Ac(a){a.curOp={cm:a,viewChanged:!1,startHeight:a.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,id:++zc},yc?yc.ops.push(a.curOp):a.curOp.ownsGroup=yc={ops:[a.curOp],delayedCallbacks:[]}}function Bc(a){var b=a.delayedCallbacks,c=0;do{for(;c<b.length;c++)b[c]();for(var d=0;d<a.ops.length;d++){var e=a.ops[d];if(e.cursorActivityHandlers)for(;e.cursorActivityCalled<e.cursorActivityHandlers.length;)e.cursorActivityHandlers[e.cursorActivityCalled++](e.cm)}}while(c<b.length)}function Cc(a){var b=a.curOp,c=b.ownsGroup;if(c)try{Bc(c)}finally{yc=null;for(var d=0;d<c.ops.length;d++)c.ops[d].cm.curOp=null;Dc(c)}}function
  Dc(a){for(var b=a.ops,c=0;c<b.length;c++)Ec(b[c]);for(var c=0;c<b.length;c++)Fc(b[c]);for(var c=0;c<b.length;c++)Gc(b[c]);
+for(var c=0;c<b.length;c++)Hc(b[c]);for(var c=0;c<b.length;c++)Ic(b[c])}function Ec(a){var b=a.cm,c=b.display;a.updateMaxLine&&I(b),a.mustUpdate=a.viewChanged||a.forceUpdate||null!=a.scrollTop||a.scrollToPos&&(a.scrollToPos.from.line<c.viewFrom||a.scrollToPos.to.line>=c.viewTo)||c.maxLineChanged&&b.options.lineWrapping,a.update=a.mustUpdate&&new S(b,a.mustUpdate&&{top:a.scrollTop,ensure:a.scrollToPos},a.forceUpdate)}function Fc(a){a.updatedDisplay=a.mustUpdate&&T(a.cm,a.update)}function Gc(a){var b=a.cm,c=b.display;a.updatedDisplay&&Y(b),a.barMeasure=L(b),c.maxLineChanged&&!b.options.lineWrapping&&(a.adjustWidthTo=bc(b,c.maxLine,c.maxLine.text.length).left+3,a.maxScrollLeft=Math.max(0,c.sizer.offsetLeft+a.adjustWidthTo+Bg-c.scroller.clientWidth)),(a.updatedDisplay||a.selectionChanged)&&(a.newSelectionNodes=Nb(b))}function Hc(a){var b=a.cm;null!=a.adjustWidthTo&&(b.display.sizer.style.minWidth=a.adjustWidthTo+"px",a.maxScrollLeft<b.doc.scrollLeft&&sd(b,Math.min(b.display.scroller.scr
 ollLeft,a.maxScrollLeft),!0),b.display.maxLineChanged=!1),a.newSelectionNodes&&Ob(b,a.newSelectionNodes),a.updatedDisplay&&W(b,a.barMeasure),(a.updatedDisplay||a.startHeight!=b.doc.height)&&M(b,a.barMeasure),a.selectionChanged&&Sb(b),b.state.focused&&a.updateInput&&$c(b,a.typing)}function Ic(a){var b=a.cm,c=b.display,d=b.doc;if(null!=a.adjustWidthTo&&Math.abs(a.barMeasure.scrollWidth-b.display.scroller.scrollWidth)>1&&M(b),a.updatedDisplay&&U(b,a.update),null==c.wheelStartX||null==a.scrollTop&&null==a.scrollLeft&&!a.scrollToPos||(c.wheelStartX=c.wheelStartY=null),null!=a.scrollTop&&(c.scroller.scrollTop!=a.scrollTop||a.forceScroll)){var e=Math.max(0,Math.min(c.scroller.scrollHeight-c.scroller.clientHeight,a.scrollTop));c.scroller.scrollTop=c.scrollbarV.scrollTop=d.scrollTop=e}if(null!=a.scrollLeft&&(c.scroller.scrollLeft!=a.scrollLeft||a.forceScroll)){var g=Math.max(0,Math.min(c.scroller.scrollWidth-c.scroller.clientWidth,a.scrollLeft));c.scroller.scrollLeft=c.scrollbarH.scrollLeft=
 d.scrollLeft=g,O(b)}if(a.scrollToPos){var h=Zd(b,wb(d,a.scrollToPos.from),wb(d,a.scrollToPos.to),a.scrollToPos.margin);a.scrollToPos.isCursor&&b.state.focused&&Yd(b,h)}var i=a.maybeHiddenMarkers,j=a.maybeUnhiddenMarkers;if(i)for(var k=0;k<i.length;++k)i[k].lines.length||tg(i[k],"hide");if(j)for(var k=0;k<j.length;++k)j[k].lines.length&&tg(j[k],"unhide");c.wrapper.offsetHeight&&(d.scrollTop=b.display.scroller.scrollTop),a.updatedDisplay&&f&&(b.options.lineWrapping&&X(b,a.barMeasure),a.barMeasure.scrollWidth>a.barMeasure.clientWidth&&a.barMeasure.scrollWidth<a.barMeasure.clientWidth+1&&!K(b)&&M(b)),a.changeObjs&&tg(b,"changes",b,a.changeObjs)}function Jc(a,b){if(a.curOp)return b();Ac(a);try{return b()}finally{Cc(a)}}function Kc(a,b){return function(){if(a.curOp)return b.apply(a,arguments);Ac(a);try{return b.apply(a,arguments)}finally{Cc(a)}}}function Lc(a){return function(){if(this.curOp)return a.apply(this,arguments);Ac(this);try{return a.apply(this,arguments)}finally{Cc(this)}}}func
 tion Mc(a){return function(){var b=this.cm;if(!b||b.curOp)return a.apply(this,arguments);Ac(b);try{return a.apply(this,arguments)}finally{Cc(b)}}}function Nc(a,b,c){this.line=b,this.rest=bf(b),this.size=this.rest?Uf(Lg(this.rest))-c+1:1,this.node=this.text=null,this.hidden=ef(a,b)}function Oc(a,b,c){for(var e,d=[],f=b;c>f;f=e){var g=new Nc(a.doc,Qf(a.doc,f),f);e=f+g.size,d.push(g)}return d}function Pc(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),d||(d=0);var e=a.display;if(d&&c<e.viewTo&&(null==e.updateLineNumbers||e.updateLineNumbers>b)&&(e.updateLineNumbers=b),a.curOp.viewChanged=!0,b>=e.viewTo)v&&cf(a.doc,b)<e.viewTo&&Rc(a);else if(c<=e.viewFrom)v&&df(a.doc,c+d)>e.viewFrom?Rc(a):(e.viewFrom+=d,e.viewTo+=d);else if(b<=e.viewFrom&&c>=e.viewTo)Rc(a);else if(b<=e.viewFrom){var f=Tc(a,c,c+d,1);f?(e.view=e.view.slice(f.index),e.viewFrom=f.lineN,e.viewTo+=d):Rc(a)}else if(c>=e.viewTo){var f=Tc(a,b,b,-1);f?(e.view=e.view.slice(0,f.index),e.viewTo=f.lineN):Rc(a)}e
 lse{var g=Tc(a,b,b,-1),h=Tc(a,c,c+d,1);g&&h?(e.view=e.view.slice(0,g.index).concat(Oc(a,g.lineN,h.lineN)).concat(e.view.slice(h.index)),e.viewTo+=d):Rc(a)}var i=e.externalMeasured;i&&(c<i.lineN?i.lineN+=d:b<i.lineN+i.size&&(e.externalMeasured=null))}function Qc(a,b,c){a.curOp.viewChanged=!0;var d=a.display,e=a.display.externalMeasured;if(e&&b>=e.lineN&&b<e.lineN+e.size&&(d.externalMeasured=null),!(b<d.viewFrom||b>=d.viewTo)){var f=d.view[Sc(a,b)];if(null!=f.node){var g=f.changes||(f.changes=[]);-1==Ng(g,c)&&g.push(c)}}}function Rc(a){a.display.viewFrom=a.display.viewTo=a.doc.first,a.display.view=[],a.display.viewOffset=0}function Sc(a,b){if(b>=a.display.viewTo)return null;if(b-=a.display.viewFrom,0>b)return null;for(var c=a.display.view,d=0;d<c.length;d++)if(b-=c[d].size,0>b)return d}function Tc(a,b,c,d){var f,e=Sc(a,b),g=a.display.view;if(!v||c==a.doc.first+a.doc.size)return{index:e,lineN:c};for(var h=0,i=a.display.viewFrom;e>h;h++)i+=g[h].size;if(i!=b){if(d>0){if(e==g.length-1)ret
 urn null;f=i+g[e].size-b,e++}else f=i-b;b+=f,c+=f}for(;cf(a.doc,c)!=c;){if(e==(0>d?0:g.length-1))return null;c+=d*g[e-(0>d?1:0)].size,e+=d}return{index:e,lineN:c}}function Uc(a,b,c){var d=a.display,e=d.view;0==e.length||b>=d.viewTo||c<=d.viewFrom?(d.view=Oc(a,b,c),d.viewFrom=b):(d.viewFrom>b?d.view=Oc(a,b,d.viewFrom).concat(d.view):d.viewFrom<b&&(d.view=d.view.slice(Sc(a,b))),d.viewFrom=b,d.viewTo<c?d.view=d.view.concat(Oc(a,d.viewTo,c)):d.viewTo>c&&(d.view=d.view.slice(0,Sc(a,c)))),d.viewTo=c}function Vc(a){for(var b=a.display.view,c=0,d=0;d<b.length;d++){var e=b[d];e.hidden||e.node&&!e.changes||++c}return c}function Wc(a){a.display.pollingFast||a.display.poll.set(a.options.pollInterval,function(){Zc(a),a.state.focused&&Wc(a)})}function Xc(a){function c(){var d=Zc(a);d||b?(a.display.pollingFast=!1,Wc(a)):(b=!0,a.display.poll.set(60,c))}var b=!1;a.display.pollingFast=!0,a.display.poll.set(20,c)}function Zc(a){var b=a.display.input,c=a.display.prevInput,f=a.doc;if(!a.state.focused||s
 h(b)&&!c||bd(a)||a.options.disableInput||a.state.keySeq)return!1;a.state.pasteIncoming&&a.state.fakedLastChar&&(b.value=b.value.substring(0,b.value.length-1),a.state.fakedLastChar=!1);var g=b.value;if(g==c&&!a.somethingSelected())return!1;if(d&&e>=9&&a.display.inputHasSelection===g||p&&/[\uf700-\uf7ff]/.test(g))return $c(a),!1;var h=!a.curOp;h&&Ac(a),a.display.shift=!1,8203!=g.charCodeAt(0)||f.sel!=a.display.selForContextMenu||c||(c="\u200b");for(var i=0,j=Math.min(c.length,g.length);j>i&&c.charCodeAt(i)==g.charCodeAt(i);)++i;var k=g.slice(i),l=rh(k),m=null;a.state.pasteIncoming&&f.sel.ranges.length>1&&(Yc&&Yc.join("\n")==k?m=0==f.sel.ranges.length%Yc.length&&Og(Yc,rh):l.length==f.sel.ranges.length&&(m=Og(l,function(a){return[a]})));for(var n=f.sel.ranges.length-1;n>=0;n--){var o=f.sel.ranges[n],q=o.from(),r=o.to();i<c.length?q=mb(q.line,q.ch-(c.length-i)):a.state.overwrite&&o.empty()&&!a.state.pasteIncoming&&(r=mb(r.line,Math.min(Qf(f,r.line).text.length,r.ch+Lg(l).length)));var s=
 a.curOp.updateInput,t={from:q,to:r,text:m?m[n%m.length]:l,origin:a.state.pasteIncoming?"paste":a.state.cutIncoming?"cut":"+input"};if(Rd(a.doc,t),vg(a,"inputRead",a,t),k&&!a.state.pasteIncoming&&a.options.electricChars&&a.options.smartIndent&&o.head.ch<100&&(!n||f.sel.ranges[n-1].head.line!=o.head.line)){var u=a.getModeAt(o.head),v=Ld(t);if(u.electricChars){for(var w=0;w<u.electricChars.length;w++)if(k.indexOf(u.electricChars.charAt(w))>-1){de(a,v.line,"smart");break}}else u.electricInput&&u.electricInput.test(Qf(f,v.line).text.slice(0,v.ch))&&de(a,v.line,"smart")}}return be(a),a.curOp.updateInput=s,a.curOp.typing=!0,g.length>1e3||g.indexOf("\n")>-1?b.value=a.display.prevInput="":a.display.prevInput=g,h&&Cc(a),a.state.pasteIncoming=a.state.cutIncoming=!1,!0}function $c(a,b){var c,f,g=a.doc;if(a.somethingSelected()){a.display.prevInput="";var h=g.sel.primary();c=th&&(h.to().line-h.from().line>100||(f=a.getSelection()).length>1e3);var i=c?"-":f||a.getSelection();a.display.input.value=
 i,a.state.focused&&Mg(a.display.input),d&&e>=9&&(a.display.inputHasSelection=i)}else b||(a.display.prevInput=a.display.input.value="",d&&e>=9&&(a.display.inputHasSelection=null));a.display.inaccurateSelection=c}function _c(a){"nocursor"==a.options.readOnly||o&&bh()==a.display.input||a.display.input.focus()}function ad(a){a.state.focused||(_c(a),Hd(a))}function bd(a){return a.options.readOnly||a.doc.cantEdit}function cd(a){function c(){a.state.focused&&setTimeout(Rg(_c,a),0)}function g(b){xg(a,b)||og(b)}function h(c){if(a.somethingSelected())Yc=a.getSelections(),b.inaccurateSelection&&(b.prevInput="",b.inaccurateSelection=!1,b.input.value=Yc.join("\n"),Mg(b.input));else{for(var d=[],e=[],f=0;f<a.doc.sel.ranges.length;f++){var g=a.doc.sel.ranges[f].head.line,h={anchor:mb(g,0),head:mb(g+1,0)};e.push(h),d.push(a.getRange(h.anchor,h.head))}"cut"==c.type?a.setSelections(e,null,Dg):(b.prevInput="",b.input.value=d.join("\n"),Mg(b.input)),Yc=d}"cut"==c.type&&(a.state.cutIncoming=!0)}var b=a.
 display;rg(b.scroller,"mousedown",Kc(a,gd)),d&&11>e?rg(b.scroller,"dblclick",Kc(a,function(b){if(!xg(a,b)){var c=fd(a,b);if(c&&!nd(a,b)&&!ed(a.display,b)){lg(b);var d=a.findWordAt(c);Bb(a.doc,d.anchor,d.head)}}})):rg(b.scroller,"dblclick",function(b){xg(a,b)||lg(b)}),rg(b.lineSpace,"selectstart",function(a){ed(b,a)||lg(a)}),t||rg(b.scroller,"contextmenu",function(b){Jd(a,b)}),rg(b.scroller,"scroll",function(){b.scroller.clientHeight&&(rd(a,b.scroller.scrollTop),sd(a,b.scroller.scrollLeft,!0),tg(a,"scroll",a))}),rg(b.scrollbarV,"scroll",function(){b.scroller.clientHeight&&rd(a,b.scrollbarV.scrollTop)}),rg(b.scrollbarH,"scroll",function(){b.scroller.clientHeight&&sd(a,b.scrollbarH.scrollLeft)}),rg(b.scroller,"mousewheel",function(b){vd(a,b)}),rg(b.scroller,"DOMMouseScroll",function(b){vd(a,b)}),rg(b.scrollbarH,"mousedown",c),rg(b.scrollbarV,"mousedown",c),rg(b.wrapper,"scroll",function(){b.wrapper.scrollTop=b.wrapper.scrollLeft=0}),rg(b.input,"keyup",function(b){Fd.call(a,b)}),rg(b.in
 put,"input",function(){d&&e>=9&&a.display.inputHasSelection&&(a.display.inputHasSelection=null),Xc(a)}),rg(b.input,"keydown",Kc(a,Dd)),rg(b.input,"keypress",Kc(a,Gd)),rg(b.input,"focus",Rg(Hd,a)),rg(b.input,"blur",Rg(Id,a)),a.options.dragDrop&&(rg(b.scroller,"dragstart",function(b){qd(a,b)}),rg(b.scroller,"dragenter",g),rg(b.scroller,"dragover",g),rg(b.scroller,"drop",Kc(a,pd))),rg(b.scroller,"paste",function(c){ed(b,c)||(a.state.pasteIncoming=!0,_c(a),Xc(a))}),rg(b.input,"paste",function(){if(f&&!a.state.fakedLastChar&&!(new Date-a.state.lastMiddleDown<200)){var c=b.input.selectionStart,d=b.input.selectionEnd;b.input.value+="$",b.input.selectionEnd=d,b.input.selectionStart=c,a.state.fakedLastChar=!0}a.state.pasteIncoming=!0,Xc(a)}),rg(b.input,"cut",h),rg(b.input,"copy",h),k&&rg(b.sizer,"mouseup",function(){bh()==b.input&&b.input.blur(),_c(a)})}function dd(a){var b=a.display;(b.lastWrapHeight!=b.wrapper.clientHeight||b.lastWrapWidth!=b.wrapper.clientWidth)&&(b.cachedCharWidth=b.cach
 edTextHeight=b.cachedPaddingH=null,a.setSize())}function ed(a,b){for(var c=pg(b);c!=a.wrapper;c=c.parentNode)if(!c||c.ignoreEvents||c.parentNode==a.sizer&&c!=a.mover)return!0}function fd(a,b,c,d){var e=a.display;if(!c){var f=pg(b);if(f==e.scrollbarH||f==e.scrollbarV||f==e.scrollbarFiller||f==e.gutterFiller)return null}var g,h,i=e.lineSpace.getBoundingClientRect();try{g=b.clientX-i.left,h=b.clientY-i.top}catch(b){return null}var k,j=tc(a,g,h);if(d&&1==j.xRel&&(k=Qf(a.doc,j.line).text).length==j.ch){var l=Hg(k,k.length,a.options.tabSize)-k.length;j=mb(j.line,Math.max(0,Math.round((g-Zb(a.display).left)/xc(a.display))-l))}return j}function gd(a){if(!xg(this,a)){var b=this,c=b.display;if(c.shift=a.shiftKey,ed(c,a))return f||(c.scroller.draggable=!1,setTimeout(function(){c.scroller.draggable=!0},100)),void 0;if(!nd(b,a)){var d=fd(b,a);switch(window.focus(),qg(a)){case 1:d?jd(b,a,d):pg(a)==c.scroller&&lg(a);break;case 2:f&&(b.state.lastMiddleDown=+new Date),d&&Bb(b.doc,d),setTimeout(Rg(_c
 ,b),20),lg(a);break;case 3:t&&Jd(b,a)}}}}function jd(a,b,c){setTimeout(Rg(ad,a),0);var e,d=+new Date;id&&id.time>d-400&&0==nb(id.pos,c)?e="triple":hd&&hd.time>d-400&&0==nb(hd.pos,c)?(e="double",id={time:d,pos:c}):(e="single",hd={time:d,pos:c});var f=a.doc.sel,g=p?b.metaKey:b.ctrlKey;a.options.dragDrop&&kh&&!bd(a)&&"single"==e&&f.contains(c)>-1&&f.somethingSelected()?kd(a,b,c,g):ld(a,b,c,e,g)}function kd(a,b,c,g){var h=a.display,i=Kc(a,function(j){f&&(h.scroller.draggable=!1),a.state.draggingText=!1,sg(document,"mouseup",i),sg(h.scroller,"drop",i),Math.abs(b.clientX-j.clientX)+Math.abs(b.clientY-j.clientY)<10&&(lg(j),g||Bb(a.doc,c),_c(a),d&&9==e&&setTimeout(function(){document.body.focus(),_c(a)},20))});f&&(h.scroller.draggable=!0),a.state.draggingText=i,h.scroller.dragDrop&&h.scroller.dragDrop(),rg(document,"mouseup",i),rg(h.scroller,"drop",i)}function ld(a,b,c,d,e){function n(b){if(0!=nb(m,b))if(m=b,"rect"==d){for(var e=[],f=a.options.tabSize,k=Hg(Qf(g,c.line).text,c.ch,f),l=Hg(Qf(
 g,b.line).text,b.ch,f),n=Math.min(k,l),o=Math.max(k,l),p=Math.min(c.line,b.line),q=Math.min(a.lastLine(),Math.max(c.line,b.line));q>=p;p++){var r=Qf(g,p).text,s=Ig(r,n,f);n==o?e.push(new sb(mb(p,s),mb(p,s))):r.length>s&&e.push(new sb(mb(p,s),mb(p,Ig(r,o,f))))}e.length||e.push(new sb(c,c)),Hb(g,tb(j.ranges.slice(0,i).concat(e),i),{origin:"*mouse",scroll:!1}),a.scrollIntoView(b)}else{var t=h,u=t.anchor,v=b;if("single"!=d){if("double"==d)var w=a.findWordAt(b);else var w=new sb(mb(b.line,0),wb(g,mb(b.line+1,0)));nb(w.anchor,u)>0?(v=w.head,u=qb(t.from(),w.anchor)):(v=w.anchor,u=pb(t.to(),w.head))}var e=j.ranges.slice(0);e[i]=new sb(wb(g,u),v),Hb(g,tb(e,i),Eg)}}function q(b){var c=++p,e=fd(a,b,!0,"rect"==d);if(e)if(0!=nb(e,m)){ad(a),n(e);var h=N(f,g);(e.line>=h.to||e.line<h.from)&&setTimeout(Kc(a,function(){p==c&&q(b)}),150)}else{var i=b.clientY<o.top?-20:b.clientY>o.bottom?20:0;i&&setTimeout(Kc(a,function(){p==c&&(f.scroller.scrollTop+=i,q(b))}),50)}}function r(b){p=1/0,lg(b),_c(a),sg(do
 cument,"mousemove",s),sg(document,"mouseup",t),g.history.lastSelOrigin=null}var f=a.display,g=a.doc;lg(b);var h,i,j=g.sel;if(e&&!b.shiftKey?(i=g.sel.contains(c),h=i>-1?g.sel.ranges[i]:new sb(c,c)):h=g.sel.primary(),b.altKey)d="rect",e||(h=new sb(c,c)),c=fd(a,b,!0,!0),i=-1;else if("double"==d){var k=a.findWordAt(c);h=a.display.shift||g.extend?Ab(g,h,k.anchor,k.head):k}else if("triple"==d){var l=new sb(mb(c.line,0),wb(g,mb(c.line+1,0)));h=a.display.shift||g.extend?Ab(g,h,l.anchor,l.head):l}else h=Ab(g,h,c);e?i>-1?Db(g,i,h,Eg):(i=g.sel.ranges.length,Hb(g,tb(g.sel.ranges.concat([h]),i),{scroll:!1,origin:"*mouse"})):(i=0,Hb(g,new rb([h],0),Eg),j=g.sel);var m=c,o=f.wrapper.getBoundingClientRect(),p=0,s=Kc(a,function(a){qg(a)?q(a):r(a)}),t=Kc(a,r);rg(document,"mousemove",s),rg(document,"mouseup",t)}function md(a,b,c,d,e){try{var f=b.clientX,g=b.clientY}catch(b){return!1}if(f>=Math.floor(a.display.gutters.getBoundingClientRect().right))return!1;d&&lg(b);var h=a.display,i=h.lineDiv.getBoundi
 ngClientRect();if(g>i.bottom||!zg(a,c))return ng(b);g-=i.top-h.viewOffset;for(var j=0;j<a.options.gutters.length;++j){var k=h.gutters.childNodes[j];if(k&&k.getBoundingClientRect().right>=f){var l=Vf(a.doc,g),m=a.options.gutters[j];return e(a,c,a,l,m,b),ng(b)}}}function nd(a,b){return md(a,b,"gutterClick",!0,vg)}function pd(a){var b=this;if(!xg(b,a)&&!ed(b.display,a)){lg(a),d&&(od=+new Date);var c=fd(b,a,!0),e=a.dataTransfer.files;if(c&&!bd(b))if(e&&e.length&&window.FileReader&&window.File)for(var f=e.length,g=Array(f),h=0,i=function(a,d){var e=new FileReader;e.onload=Kc(b,function(){if(g[d]=e.result,++h==f){c=wb(b.doc,c);var a={from:c,to:c,text:rh(g.join("\n")),origin:"paste"};Rd(b.doc,a),Gb(b.doc,ub(c,Ld(a)))}}),e.readAsText(a)},j=0;f>j;++j)i(e[j],j);else{if(b.state.draggingText&&b.doc.sel.contains(c)>-1)return b.state.draggingText(a),setTimeout(Rg(_c,b),20),void 0;try{var g=a.dataTransfer.getData("Text");if(g){if(b.state.draggingText&&!(p?a.metaKey:a.ctrlKey))var k=b.listSelection
 s();if(Ib(b.doc,ub(c,c)),k)for(var j=0;j<k.length;++j)Xd(b.doc,"",k[j].anchor,k[j].head,"drag");b.replaceSelection(g,"around","paste"),_c(b)}}catch(a){}}}}function qd(a,b){if(d&&(!a.state.draggingText||+new Date-od<100))return og(b),void 0;if(!xg(a,b)&&!ed(a.display,b)&&(b.dataTransfer.setData("Text",a.getSelection()),b.dataTransfer.setDragImage&&!j)){var c=Yg("img",null,null,"position: fixed; left: 0; top: 0;");c.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",i&&(c.width=c.height=1,a.display.wrapper.appendChild(c),c._top=c.offsetTop),b.dataTransfer.setDragImage(c,0,0),i&&c.parentNode.removeChild(c)}}function rd(b,c){Math.abs(b.doc.scrollTop-c)<2||(b.doc.scrollTop=c,a||V(b,{top:c}),b.display.scroller.scrollTop!=c&&(b.display.scroller.scrollTop=c),b.display.scrollbarV.scrollTop!=c&&(b.display.scrollbarV.scrollTop=c),a&&V(b),Tb(b,100))}function sd(a,b,c){(c?b==a.doc.scrollLeft:Math.abs(a.doc.scrollLeft-b)<2)||(b=Math.min(b,a.display.scroller.scrollWid
 th-a.display.scroller.clientWidth),a.doc.scrollLeft=b,O(a),a.display.scroller.scrollLeft!=b&&(a.display.scroller.scrollLeft=b),a.display.scrollbarH.scrollLeft!=b&&(a.display.scrollbarH.scrollLeft=b))}function vd(b,c){var d=c.wheelDeltaX,e=c.wheelDeltaY;null==d&&c.detail&&c.axis==c.HORIZONTAL_AXIS&&(d=c.detail),null==e&&c.detail&&c.axis==c.VERTICAL_AXIS?e=c.detail:null==e&&(e=c.wheelDelta);var g=b.display,h=g.scroller;if(d&&h.scrollWidth>h.clientWidth||e&&h.scrollHeight>h.clientHeight){if(e&&p&&f)a:for(var j=c.target,k=g.view;j!=h;j=j.parentNode)for(var l=0;l<k.length;l++)if(k[l].node==j){b.display.currentWheelTarget=j;break a}if(d&&!a&&!i&&null!=ud)return e&&rd(b,Math.max(0,Math.min(h.scrollTop+e*ud,h.scrollHeight-h.clientHeight))),sd(b,Math.max(0,Math.min(h.scrollLeft+d*ud,h.scrollWidth-h.clientWidth))),lg(c),g.wheelStartX=null,void 0;if(e&&null!=ud){var m=e*ud,n=b.doc.scrollTop,o=n+g.wrapper.clientHeight;0>m?n=Math.max(0,n+m-50):o=Math.min(b.doc.height,o+m+50),V(b,{top:n,bottom:o}
 )}20>td&&(null==g.wheelStartX?(g.wheelStartX=h.scrollLeft,g.wheelStartY=h.scrollTop,g.wheelDX=d,g.wheelDY=e,setTimeout(function(){if(null!=g.wheelStartX){var a=h.scrollLeft-g.wheelStartX,b=h.scrollTop-g.wheelStartY,c=b&&g.wheelDY&&b/g.wheelDY||a&&g.wheelDX&&a/g.wheelDX;g.wheelStartX=g.wheelStartY=null,c&&(ud=(ud*td+c)/(td+1),++td)}},200)):(g.wheelDX+=d,g.wheelDY+=e))}}function wd(a,b,c){if("string"==typeof b&&(b=te[b],!b))return!1;a.display.pollingFast&&Zc(a)&&(a.display.pollingFast=!1);var d=a.display.shift,e=!1;try{bd(a)&&(a.state.suppressEdits=!0),c&&(a.display.shift=!1),e=b(a)!=Cg}finally{a.display.shift=d,a.state.suppressEdits=!1}return e}function xd(a,b,c){for(var d=0;d<a.state.keyMaps.length;d++){var e=we(b,a.state.keyMaps[d],c);if(e)return e}return a.options.extraKeys&&we(b,a.options.extraKeys,c)||we(b,a.options.keyMap,c)}function zd(a,b,c,d){var e=a.state.keySeq;if(e){if(xe(b))return"handled";yd.set(50,function(){a.state.keySeq==e&&(a.state.keySeq=null,$c(a))}),b=e+" "+b}va
 r f=xd(a,b,d);return"multi"==f&&(a.state.keySeq=b),"handled"==f&&vg(a,"keyHandled",a,b,c),("handled"==f||"multi"==f)&&(lg(c),Sb(a)),e&&!f&&/\'$/.test(b)?(lg(c),!0):!!f}function Ad(a,b){var c=ye(b,!0);return c?b.shiftKey&&!a.state.keySeq?zd(a,"Shift-"+c,b,function(b){return wd(a,b,!0)})||zd(a,c,b,function(b){return("string"==typeof b?/^go[A-Z]/.test(b):b.motion)?wd(a,b):void 0}):zd(a,c,b,function(b){return wd(a,b)}):!1}function Bd(a,b,c){return zd(a,"'"+c+"'",b,function(b){return wd(a,b,!0)})}function Dd(a){var b=this;if(ad(b),!xg(b,a)){d&&11>e&&27==a.keyCode&&(a.returnValue=!1);var c=a.keyCode;b.display.shift=16==c||a.shiftKey;var f=Ad(b,a);i&&(Cd=f?c:null,!f&&88==c&&!th&&(p?a.metaKey:a.ctrlKey)&&b.replaceSelection("",null,"cut")),18!=c||/\bCodeMirror-crosshair\b/.test(b.display.lineDiv.className)||Ed(b)}}function Ed(a){function c(a){18!=a.keyCode&&a.altKey||(dh(b,"CodeMirror-crosshair"),sg(document,"keyup",c),sg(document,"mouseover",c))}var b=a.display.lineDiv;eh(b,"CodeMirror-cros
 shair"),rg(document,"keyup",c),rg(document,"mouseover",c)}function Fd(a){16==a.keyCode&&(this.doc.sel.shift=!1),xg(this,a)}function Gd(a){var b=this;if(!(xg(b,a)||a.ctrlKey&&!a.altKey||p&&a.metaKey)){var c=a.keyCode,f=a.charCode;if(i&&c==Cd)return Cd=null,lg(a),void 0;if(!(i&&(!a.which||a.which<10)||k)||!Ad(b,a)){var g=String.fromCharCode(null==f?c:f);Bd(b,a,g)||(d&&e>=9&&(b.display.inputHasSelection=null),Xc(b))}}}function Hd(a){"nocursor"!=a.options.readOnly&&(a.state.focused||(tg(a,"focus",a),a.state.focused=!0,eh(a.display.wrapper,"CodeMirror-focused"),a.curOp||a.display.selForContextMenu==a.doc.sel||($c(a),f&&setTimeout(Rg($c,a,!0),0))),Wc(a),Sb(a))}function Id(a){a.state.focused&&(tg(a,"blur",a),a.state.focused=!1,dh(a.display.wrapper,"CodeMirror-focused")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.display.shift=!1)},150)}function Jd(a,b){function m(){if(null!=c.input.selectionStart){var b=a.somethingSelected(),d=c.input.value="\u200b"+(b?c.inp
 ut.value:"");c.prevInput=b?"":"\u200b",c.input.selectionStart=1,c.input.selectionEnd=d.length,c.selForContextMenu=a.doc.sel}}function n(){if(c.inputDiv.style.position="relative",c.input.style.cssText=k,d&&9>e&&(c.scrollbarV.scrollTop=c.scroller.scrollTop=h),Wc(a),null!=c.input.selectionStart){(!d||d&&9>e)&&m();var b=0,f=function(){c.selForContextMenu==a.doc.sel&&0==c.input.selectionStart?Kc(a,te.selectAll)(a):b++<10?c.detectingSelectAll=setTimeout(f,500):$c(a)};c.detectingSelectAll=setTimeout(f,200)}}if(!xg(a,b,"contextmenu")){var c=a.display;if(!ed(c,b)&&!Kd(a,b)){var g=fd(a,b),h=c.scroller.scrollTop;if(g&&!i){var j=a.options.resetSelectionOnContextMenu;j&&-1==a.doc.sel.contains(g)&&Kc(a,Hb)(a.doc,ub(g),Dg);var k=c.input.style.cssText;if(c.inputDiv.style.position="absolute",c.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(b.clientY-5)+"px; left: "+(b.clientX-5)+"px; z-index: 1000; background: "+(d?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none;
  border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",f)var l=window.scrollY;if(_c(a),f&&window.scrollTo(null,l),$c(a),a.somethingSelected()||(c.input.value=c.prevInput=" "),c.selForContextMenu=a.doc.sel,clearTimeout(c.detectingSelectAll),d&&e>=9&&m(),t){og(b);var o=function(){sg(window,"mouseup",o),setTimeout(n,20)};rg(window,"mouseup",o)}else setTimeout(n,50)}}}}function Kd(a,b){return zg(a,"gutterContextMenu")?md(a,b,"gutterContextMenu",!1,tg):!1}function Md(a,b){if(nb(a,b.from)<0)return a;if(nb(a,b.to)<=0)return Ld(b);var c=a.line+b.text.length-(b.to.line-b.from.line)-1,d=a.ch;return a.line==b.to.line&&(d+=Ld(b).ch-b.to.ch),mb(c,d)}function Nd(a,b){for(var c=[],d=0;d<a.sel.ranges.length;d++){var e=a.sel.ranges[d];c.push(new sb(Md(e.anchor,b),Md(e.head,b)))}return tb(c,a.sel.primIndex)}function Od(a,b,c){return a.line==b.line?mb(c.line,a.ch-b.ch+c.ch):mb(c.line+(a.line-b.line),a.ch)}function Pd(a,b,c){for(var d=[],e=mb(a.first,0),f=e,g=0;g<b.
 length;g++){var h=b[g],i=Od(h.from,e,f),j=Od(Ld(h),e,f);if(e=h.to,f=j,"around"==c){var k=a.sel.ranges[g],l=nb(k.head,k.anchor)<0;d[g]=new sb(l?j:i,l?i:j)}else d[g]=new sb(i,i)}return new rb(d,a.sel.primIndex)}function Qd(a,b,c){var d={canceled:!1,from:b.from,to:b.to,text:b.text,origin:b.origin,cancel:function(){this.canceled=!0}};return c&&(d.update=function(b,c,d,e){b&&(this.from=wb(a,b)),c&&(this.to=wb(a,c)),d&&(this.text=d),void 0!==e&&(this.origin=e)}),tg(a,"beforeChange",a,d),a.cm&&tg(a.cm,"beforeChange",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function Rd(a,b,c){if(a.cm){if(!a.cm.curOp)return Kc(a.cm,Rd)(a,b,c);if(a.cm.state.suppressEdits)return}if(!(zg(a,"beforeChange")||a.cm&&zg(a.cm,"beforeChange"))||(b=Qd(a,b,!0))){var d=u&&!c&&Se(a,b.from,b.to);if(d)for(var e=d.length-1;e>=0;--e)Sd(a,{from:d[e].from,to:d[e].to,text:e?[""]:b.text});else Sd(a,b)}}function Sd(a,b){if(1!=b.text.length||""!=b.text[0]||0!=nb(b.from,b.to)){var c=Nd(a,b);ag(a,b,c,
 a.cm?a.cm.curOp.id:0/0),Vd(a,b,c,Pe(a,b));var d=[];Of(a,function(a,c){c||-1!=Ng(d,a.history)||(kg(a.history,b),d.push(a.history)),Vd(a,b,null,Pe(a,b))})}}function Td(a,b,c){if(!a.cm||!a.cm.state.suppressEdits){for(var e,d=a.history,f=a.sel,g="undo"==b?d.done:d.undone,h="undo"==b?d.undone:d.done,i=0;i<g.length&&(e=g[i],c?!e.ranges||e.equals(a.sel):e.ranges);i++);if(i!=g.length){for(d.lastOrigin=d.lastSelOrigin=null;e=g.pop(),e.ranges;){if(dg(e,h),c&&!e.equals(a.sel))return Hb(a,e,{clearRedo:!1}),void 0;f=e}var j=[];dg(f,h),h.push({changes:j,generation:d.generation}),d.generation=e.generation||++d.maxGeneration;for(var k=zg(a,"beforeChange")||a.cm&&zg(a.cm,"beforeChange"),i=e.changes.length-1;i>=0;--i){var l=e.changes[i];if(l.origin=b,k&&!Qd(a,l,!1))return g.length=0,void 0;j.push(Zf(a,l));var m=i?Nd(a,l):Lg(g);Vd(a,l,m,Re(a,l)),!i&&a.cm&&a.cm.scrollIntoView({from:l.from,to:Ld(l)});var n=[];Of(a,function(a,b){b||-1!=Ng(n,a.history)||(kg(a.history,l),n.push(a.history)),Vd(a,l,null,Re(a
 ,l))})}}}}function Ud(a,b){if(0!=b&&(a.first+=b,a.sel=new rb(Og(a.sel.ranges,function(a){return new sb(mb(a.anchor.line+b,a.anchor.ch),mb(a.head.line+b,a.head.ch))}),a.sel.primIndex),a.cm)){Pc(a.cm,a.first,a.first-b,b);for(var c=a.cm.display,d=c.viewFrom;d<c.viewTo;d++)Qc(a.cm,d,"gutter")}}function Vd(a,b,c,d){if(a.cm&&!a.cm.curOp)return Kc(a.cm,Vd)(a,b,c,d);if(b.to.line<a.first)return Ud(a,b.text.length-1-(b.to.line-b.from.line)),void 0;if(!(b.from.line>a.lastLine())){if(b.from.line<a.first){var e=b.text.length-1-(a.first-b.from.line);Ud(a,e),b={from:mb(a.first,0),to:mb(b.to.line+e,b.to.ch),text:[Lg(b.text)],origin:b.origin}}var f=a.lastLine();b.to.line>f&&(b={from:b.from,to:mb(f,Qf(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=Rf(a,b.from,b.to),c||(c=Nd(a,b)),a.cm?Wd(a.cm,b,d):Hf(a,b,d),Ib(a,c,Dg)}}function Wd(a,b,c){var d=a.doc,e=a.display,f=b.from,g=b.to,h=!1,i=f.line;a.options.lineWrapping||(i=Uf(af(Qf(d,f.line))),d.iter(i,g.line+1,function(a){return a==e.maxLi
 ne?(h=!0,!0):void 0})),d.sel.contains(b.from,b.to)>-1&&yg(a),Hf(d,b,c,B(a)),a.options.lineWrapping||(d.iter(i,f.line+b.text.length,function(a){var b=H(a);b>e.maxLineLength&&(e.maxLine=a,e.maxLineLength=b,e.maxLineChanged=!0,h=!1)}),h&&(a.curOp.updateMaxLine=!0)),d.frontier=Math.min(d.frontier,f.line),Tb(a,400);var j=b.text.length-(g.line-f.line)-1;f.line!=g.line||1!=b.text.length||Gf(a.doc,b)?Pc(a,f.line,g.line+1,j):Qc(a,f.line,"text");var k=zg(a,"changes"),l=zg(a,"change");if(l||k){var m={from:f,to:g,text:b.text,removed:b.removed,origin:b.origin};l&&vg(a,"change",a,m),k&&(a.curOp.changeObjs||(a.curOp.changeObjs=[])).push(m)}a.display.selForContextMenu=null}function Xd(a,b,c,d,e){if(d||(d=c),nb(d,c)<0){var f=d;d=c,c=f}"string"==typeof b&&(b=rh(b)),Rd(a,{from:c,to:d,text:b,origin:e})}function Yd(a,b){if(!xg(a,"scrollCursorIntoView")){var c=a.display,d=c.sizer.getBoundingClientRect(),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight
 )&&(e=!1),null!=e&&!m){var f=Yg("div","\u200b",null,"position: absolute; top: "+(b.top-c.viewOffset-Xb(a.display))+"px; height: "+(b.bottom-b.top+Bg)+"px; left: "+b.left+"px; width: 2px;");a.display.lineSpace.appendChild(f),f.scrollIntoView(e),a.display.lineSpace.removeChild(f)}}}function Zd(a,b,c,d){null==d&&(d=0);for(var e=0;5>e;e++){var f=!1,g=qc(a,b),h=c&&c!=b?qc(a,c):g,i=_d(a,Math.min(g.left,h.left),Math.min(g.top,h.top)-d,Math.max(g.left,h.left),Math.max(g.bottom,h.bottom)+d),j=a.doc.scrollTop,k=a.doc.scrollLeft;if(null!=i.scrollTop&&(rd(a,i.scrollTop),Math.abs(a.doc.scrollTop-j)>1&&(f=!0)),null!=i.scrollLeft&&(sd(a,i.scrollLeft),Math.abs(a.doc.scrollLeft-k)>1&&(f=!0)),!f)return g}}function $d(a,b,c,d,e){var f=_d(a,b,c,d,e);null!=f.scrollTop&&rd(a,f.scrollTop),null!=f.scrollLeft&&sd(a,f.scrollLeft)}function _d(a,b,c,d,e){var f=a.display,g=wc(a.display);0>c&&(c=0);var h=a.curOp&&null!=a.curOp.scrollTop?a.curOp.scrollTop:f.scroller.scrollTop,i=f.scroller.clientHeight-Bg,j={};e-c
 >i&&(e=c+i);var k=a.doc.height+Yb(f),l=g>c,m=e>k-g;if(h>c)j.scrollTop=l?0:c;else if(e>h+i){var n=Math.min(c,(m?k:e)-i);n!=h&&(j.scrollTop=n)}var o=a.curOp&&null!=a.curOp.scrollLeft?a.curOp.scrollLeft:f.scroller.scrollLeft,p=f.scroller.clientWidth-Bg-f.gutters.offsetWidth,q=d-b>p;return q&&(d=b+p),10>b?j.scrollLeft=0:o>b?j.scrollLeft=Math.max(0,b-(q?0:10)):d>p+o-3&&(j.scrollLeft=d+(q?0:10)-p),j}function ae(a,b,c){(null!=b||null!=c)&&ce(a),null!=b&&(a.curOp.scrollLeft=(null==a.curOp.scrollLeft?a.doc.scrollLeft:a.curOp.scrollLeft)+b),null!=c&&(a.curOp.scrollTop=(null==a.curOp.scrollTop?a.doc.scrollTop:a.curOp.scrollTop)+c)}function be(a){ce(a);var b=a.getCursor(),c=b,d=b;a.options.lineWrapping||(c=b.ch?mb(b.line,b.ch-1):b,d=mb(b.line,b.ch+1)),a.curOp.scrollToPos={from:c,to:d,margin:a.options.cursorScrollMargin,isCursor:!0}}function ce(a){var b=a.curOp.scrollToPos;if(b){a.curOp.scrollToPos=null;var c=rc(a,b.from),d=rc(a,b.to),e=_d(a,Math.min(c.left,d.left),Math.min(c.top,d.top)-b.margin
 ,Math.max(c.right,d.right),Math.max(c.bottom,d.bottom)+b.margin);a.scrollTo(e.scrollLeft,e.scrollTop)}}function de(a,b,c,d){var f,e=a.doc;null==c&&(c="add"),"smart"==c&&(e.mode.indent?f=Wb(a,b):c="prev");var g=a.options.tabSize,h=Qf(e,b),i=Hg(h.text,null,g);h.stateAfter&&(h.stateAfter=null);var k,j=h.text.match(/^\s*/)[0];if(d||/\S/.test(h.text)){if("smart"==c&&(k=e.mode.indent(f,h.text.slice(j.length),h.text),k==Cg||k>150)){if(!d)return;c="prev"}}else k=0,c="not";"prev"==c?k=b>e.first?Hg(Qf(e,b-1).text,null,g):0:"add"==c?k=i+a.options.indentUnit:"subtract"==c?k=i-a.options.indentUnit:"number"==typeof c&&(k=i+c),k=Math.max(0,k);var l="",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(k/g);n;--n)m+=g,l+="	";if(k>m&&(l+=Kg(k-m)),l!=j)Xd(e,l,mb(b,0),mb(b,j.length),"+input");else for(var n=0;n<e.sel.ranges.length;n++){var o=e.sel.ranges[n];if(o.head.line==b&&o.head.ch<j.length){var m=mb(b,j.length);Db(e,n,new sb(m,m));break}}h.stateAfter=null}function ee(a,b,c,d){var e=b,f=b;return
 "number"==typeof b?f=Qf(a,vb(a,b)):e=Uf(b),null==e?null:(d(f,e)&&a.cm&&Qc(a.cm,e,c),f)}function fe(a,b){for(var c=a.doc.sel.ranges,d=[],e=0;e<c.length;e++){for(var f=b(c[e]);d.length&&nb(f.from,Lg(d).to)<=0;){var g=d.pop();if(nb(g.from,f.from)<0){f.from=g.from;break}}d.push(f)}Jc(a,function(){for(var b=d.length-1;b>=0;b--)Xd(a.doc,"",d[b].from,d[b].to,"+delete");be(a)})}function ge(a,b,c,d,e){function k(){var b=f+c;return b<a.first||b>=a.first+a.size?j=!1:(f=b,i=Qf(a,b))}function l(a){var b=(e?Jh:Kh)(i,g,c,!0);if(null==b){if(a||!k())return j=!1;g=e?(0>c?Bh:Ah)(i):0>c?i.text.length:0}else g=b;return!0}var f=b.line,g=b.ch,h=c,i=Qf(a,f),j=!0;if("char"==d)l();else if("column"==d)l(!0);else if("word"==d||"group"==d)for(var m=null,n="group"==d,o=a.cm&&a.cm.getHelper(b,"wordChars"),p=!0;!(0>c)||l(!p);p=!1){var q=i.text.charAt(g)||"\n",r=Ug(q,o)?"w":n&&"\n"==q?"n":!n||/\s/.test(q)?null:"p";if(!n||p||r||(r="s"),m&&m!=r){0>c&&(c=1,l());break}if(r&&(m=r),c>0&&!l(!p))break}var s=Mb(a,mb(f,g),h,
 !0);return j||(s.hitSide=!0),s}function he(a,b,c,d){var g,e=a.doc,f=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);g=b.top+c*(h-(0>c?1.5:.5)*wc(a.display))}else"line"==d&&(g=c>0?b.bottom+3:b.top-3);for(;;){var i=tc(a,f,g);if(!i.outside)break;if(0>c?0>=g:g>=e.height){i.hitSide=!0;break}g+=5*c}return i}function ke(a,b,c,d){w.defaults[a]=b,c&&(je[a]=d?function(a,b,d){d!=le&&c(a,b,d)}:c)}function ve(a){for(var c,d,e,f,b=a.split(/-(?!$)/),a=b[b.length-1],g=0;g<b.length-1;g++){var h=b[g];if(/^(cmd|meta|m)$/i.test(h))f=!0;else if(/^a(lt)?$/i.test(h))c=!0;else if(/^(c|ctrl|control)$/i.test(h))d=!0;else{if(!/^s(hift)$/i.test(h))throw new Error("Unrecognized modifier name: "+h);e=!0}}return c&&(a="Alt-"+a),d&&(a="Ctrl-"+a),f&&(a="Cmd-"+a),e&&(a="Shift-"+a),a}function ze(a){return"string"==typeof a?ue[a]:a}function De(a,b,c,d,e){if(d&&d.shared)return Fe(a,b,c,d,e);if(a.cm&&!a.cm.curOp)return Kc(a.cm,De)(a,b,c,d,e);v
 ar f=new Be(a,e),g=nb(b,c);if(d&&Qg(d,f,!1),g>0||0==g&&f.clearWhenEmpty!==!1)return f;if(f.replacedWith&&(f.collapsed=!0,f.widgetNode=Yg("span",[f.replacedWith],"CodeMirror-widget"),d.handleMouseEvents||(f.widgetNode.ignoreEvents=!0),d.insertLeft&&(f.widgetNode.insertLeft=!0)),f.collapsed){if(_e(a,b.line,b,c,f)||b.line!=c.line&&_e(a,c.line,b,c,f))throw new Error("Inserting collapsed marker partially overlapping an existing one");
+v=!0}f.addToHistory&&ag(a,{from:b,to:c,origin:"markText"},a.sel,0/0);var j,h=b.line,i=a.cm;if(a.iter(h,c.line+1,function(a){i&&f.collapsed&&!i.options.lineWrapping&&af(a)==i.display.maxLine&&(j=!0),f.collapsed&&h!=b.line&&Tf(a,0),Me(a,new Je(f,h==b.line?b.ch:null,h==c.line?c.ch:null)),++h}),f.collapsed&&a.iter(b.line,c.line+1,function(b){ef(a,b)&&Tf(b,0)}),f.clearOnEnter&&rg(f,"beforeCursorEnter",function(){f.clear()}),f.readOnly&&(u=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed&&(f.id=++Ce,f.atomic=!0),i){if(j&&(i.curOp.updateMaxLine=!0),f.collapsed)Pc(i,b.line,c.line+1);else if(f.className||f.title||f.startStyle||f.endStyle)for(var k=b.line;k<=c.line;k++)Qc(i,k,"text");f.atomic&&Kb(i.doc),vg(i,"markerAdded",i,f)}return f}function Fe(a,b,c,d,e){d=Qg(d),d.shared=!1;var f=[De(a,b,c,d,e)],g=f[0],h=d.widgetNode;return Of(a,function(a){h&&(d.widgetNode=h.cloneNode(!0)),f.push(De(a,wb(a,b),wb(a,c),d,e));for(var i=0;i<a.linked.length;++i)if(a.linked[i]
 .isParent)return;g=Lg(f)}),new Ee(f,g)}function Ge(a){return a.findMarks(mb(a.first,0),a.clipPos(mb(a.lastLine())),function(a){return a.parent})}function He(a,b){for(var c=0;c<b.length;c++){var d=b[c],e=d.find(),f=a.clipPos(e.from),g=a.clipPos(e.to);if(nb(f,g)){var h=De(a,f,g,d.primary,d.primary.type);d.markers.push(h),h.parent=d}}}function Ie(a){for(var b=0;b<a.length;b++){var c=a[b],d=[c.primary.doc];Of(c.primary.doc,function(a){d.push(a)});for(var e=0;e<c.markers.length;e++){var f=c.markers[e];-1==Ng(d,f.doc)&&(f.parent=null,c.markers.splice(e--,1))}}}function Je(a,b,c){this.marker=a,this.from=b,this.to=c}function Ke(a,b){if(a)for(var c=0;c<a.length;++c){var d=a[c];if(d.marker==b)return d}}function Le(a,b){for(var c,d=0;d<a.length;++d)a[d]!=b&&(c||(c=[])).push(a[d]);return c}function Me(a,b){a.markedSpans=a.markedSpans?a.markedSpans.concat([b]):[b],b.marker.attachLine(a)}function Ne(a,b,c){if(a)for(var e,d=0;d<a.length;++d){var f=a[d],g=f.marker,h=null==f.from||(g.inclusiveLeft?f
 .from<=b:f.from<b);if(h||f.from==b&&"bookmark"==g.type&&(!c||!f.marker.insertLeft)){var i=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);(e||(e=[])).push(new Je(g,f.from,i?null:f.to))}}return e}function Oe(a,b,c){if(a)for(var e,d=0;d<a.length;++d){var f=a[d],g=f.marker,h=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);if(h||f.from==b&&"bookmark"==g.type&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);(e||(e=[])).push(new Je(g,i?null:f.from-b,null==f.to?null:f.to-b))}}return e}function Pe(a,b){var c=yb(a,b.from.line)&&Qf(a,b.from.line).markedSpans,d=yb(a,b.to.line)&&Qf(a,b.to.line).markedSpans;if(!c&&!d)return null;var e=b.from.ch,f=b.to.ch,g=0==nb(b.from,b.to),h=Ne(c,e,g),i=Oe(d,f,g),j=1==b.text.length,k=Lg(b.text).length+(j?e:0);if(h)for(var l=0;l<h.length;++l){var m=h[l];if(null==m.to){var n=Ke(i,m.marker);n?j&&(m.to=null==n.to?null:n.to+k):m.to=e}}if(i)for(var l=0;l<i.length;++l){var m=i[l];if(null!=m.to&&(m.to+=k),null==m.from){var n=Ke(h,m.mark
 er);n||(m.from=k,j&&(h||(h=[])).push(m))}else m.from+=k,j&&(h||(h=[])).push(m)}h&&(h=Qe(h)),i&&i!=h&&(i=Qe(i));var o=[h];if(!j){var q,p=b.text.length-2;if(p>0&&h)for(var l=0;l<h.length;++l)null==h[l].to&&(q||(q=[])).push(new Je(h[l].marker,null,null));for(var l=0;p>l;++l)o.push(q);o.push(i)}return o}function Qe(a){for(var b=0;b<a.length;++b){var c=a[b];null!=c.from&&c.from==c.to&&c.marker.clearWhenEmpty!==!1&&a.splice(b--,1)}return a.length?a:null}function Re(a,b){var c=gg(a,b),d=Pe(a,b);if(!c)return d;if(!d)return c;for(var e=0;e<c.length;++e){var f=c[e],g=d[e];if(f&&g)a:for(var h=0;h<g.length;++h){for(var i=g[h],j=0;j<f.length;++j)if(f[j].marker==i.marker)continue a;f.push(i)}else g&&(c[e]=g)}return c}function Se(a,b,c){var d=null;if(a.iter(b.line,c.line+1,function(a){if(a.markedSpans)for(var b=0;b<a.markedSpans.length;++b){var c=a.markedSpans[b].marker;!c.readOnly||d&&-1!=Ng(d,c)||(d||(d=[])).push(c)}}),!d)return null;for(var e=[{from:b,to:c}],f=0;f<d.length;++f)for(var g=d[f],h=
 g.find(0),i=0;i<e.length;++i){var j=e[i];if(!(nb(j.to,h.from)<0||nb(j.from,h.to)>0)){var k=[i,1],l=nb(j.from,h.from),m=nb(j.to,h.to);(0>l||!g.inclusiveLeft&&!l)&&k.push({from:j.from,to:h.from}),(m>0||!g.inclusiveRight&&!m)&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function Te(a){var b=a.markedSpans;if(b){for(var c=0;c<b.length;++c)b[c].marker.detachLine(a);a.markedSpans=null}}function Ue(a,b){if(b){for(var c=0;c<b.length;++c)b[c].marker.attachLine(a);a.markedSpans=b}}function Ve(a){return a.inclusiveLeft?-1:0}function We(a){return a.inclusiveRight?1:0}function Xe(a,b){var c=a.lines.length-b.lines.length;if(0!=c)return c;var d=a.find(),e=b.find(),f=nb(d.from,e.from)||Ve(a)-Ve(b);if(f)return-f;var g=nb(d.to,e.to)||We(a)-We(b);return g?g:b.id-a.id}function Ye(a,b){var d,c=v&&a.markedSpans;if(c)for(var e,f=0;f<c.length;++f)e=c[f],e.marker.collapsed&&null==(b?e.from:e.to)&&(!d||Xe(d,e.marker)<0)&&(d=e.marker);return d}function Ze(a){return Ye(a,!0)}function
  $e(a){return Ye(a,!1)}function _e(a,b,c,d,e){var f=Qf(a,b),g=v&&f.markedSpans;if(g)for(var h=0;h<g.length;++h){var i=g[h];if(i.marker.collapsed){var j=i.marker.find(0),k=nb(j.from,c)||Ve(i.marker)-Ve(e),l=nb(j.to,d)||We(i.marker)-We(e);if(!(k>=0&&0>=l||0>=k&&l>=0)&&(0>=k&&(nb(j.to,c)>0||i.marker.inclusiveRight&&e.inclusiveLeft)||k>=0&&(nb(j.from,d)<0||i.marker.inclusiveLeft&&e.inclusiveRight)))return!0}}}function af(a){for(var b;b=Ze(a);)a=b.find(-1,!0).line;return a}function bf(a){for(var b,c;b=$e(a);)a=b.find(1,!0).line,(c||(c=[])).push(a);return c}function cf(a,b){var c=Qf(a,b),d=af(c);return c==d?b:Uf(d)}function df(a,b){if(b>a.lastLine())return b;var d,c=Qf(a,b);if(!ef(a,c))return b;for(;d=$e(c);)c=d.find(1,!0).line;return Uf(c)+1}function ef(a,b){var c=v&&b.markedSpans;if(c)for(var d,e=0;e<c.length;++e)if(d=c[e],d.marker.collapsed){if(null==d.from)return!0;if(!d.marker.widgetNode&&0==d.from&&d.marker.inclusiveLeft&&ff(a,b,d))return!0}}function ff(a,b,c){if(null==c.to){var d=c
 .marker.find(1,!0);return ff(a,d.line,Ke(d.line.markedSpans,c.marker))}if(c.marker.inclusiveRight&&c.to==b.text.length)return!0;for(var e,f=0;f<b.markedSpans.length;++f)if(e=b.markedSpans[f],e.marker.collapsed&&!e.marker.widgetNode&&e.from==c.to&&(null==e.to||e.to!=c.from)&&(e.marker.inclusiveLeft||c.marker.inclusiveRight)&&ff(a,b,e))return!0}function hf(a,b,c){Wf(b)<(a.curOp&&a.curOp.scrollTop||a.doc.scrollTop)&&ae(a,null,c)}function jf(a){if(null!=a.height)return a.height;if(!ah(document.body,a.node)){var b="position: relative;";a.coverGutter&&(b+="margin-left: -"+a.cm.getGutterElement().offsetWidth+"px;"),_g(a.cm.display.measure,Yg("div",[a.node],null,b))}return a.height=a.node.offsetHeight}function kf(a,b,c,d){var e=new gf(a,c,d);return e.noHScroll&&(a.display.alignWidgets=!0),ee(a.doc,b,"widget",function(b){var c=b.widgets||(b.widgets=[]);if(null==e.insertAt?c.push(e):c.splice(Math.min(c.length-1,Math.max(0,e.insertAt)),0,e),e.line=b,!ef(a.doc,b)){var d=Wf(b)<a.doc.scrollTop;Tf
 (b,b.height+jf(e)),d&&ae(a,null,e.height),a.curOp.forceUpdate=!0}return!0}),e}function mf(a,b,c,d){a.text=b,a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null),null!=a.order&&(a.order=null),Te(a),Ue(a,c);var e=d?d(a):1;e!=a.height&&Tf(a,e)}function nf(a){a.parent=null,Te(a)}function of(a,b){if(a)for(;;){var c=a.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!c)break;a=a.slice(0,c.index)+a.slice(c.index+c[0].length);var d=c[1]?"bgClass":"textClass";null==b[d]?b[d]=c[2]:new RegExp("(?:^|s)"+c[2]+"(?:$|s)").test(b[d])||(b[d]+=" "+c[2])}return a}function pf(a,b){if(a.blankLine)return a.blankLine(b);if(a.innerMode){var c=w.innerMode(a,b);return c.mode.blankLine?c.mode.blankLine(c.state):void 0}}function qf(a,b,c,d){for(var e=0;10>e;e++){d&&(d[0]=w.innerMode(a,c).mode);var f=a.token(b,c);if(b.pos>b.start)return f}throw new Error("Mode "+a.name+" failed to advance stream.")}function rf(a,b,c,d){function e(a){return{start:k.start,end:k.pos,string:k.current(),type:h||null,state:a?re(f
 .mode,j):j}}var h,f=a.doc,g=f.mode;b=wb(f,b);var l,i=Qf(f,b.line),j=Wb(a,b.line,c),k=new Ae(i.text,a.options.tabSize);for(d&&(l=[]);(d||k.pos<b.ch)&&!k.eol();)k.start=k.pos,h=qf(g,k,j),d&&l.push(e(!0));return d?l:e()}function sf(a,b,c,d,e,f,g){var h=c.flattenSpans;null==h&&(h=a.options.flattenSpans);var l,i=0,j=null,k=new Ae(b,a.options.tabSize),m=a.options.addModeClass&&[null];for(""==b&&of(pf(c,d),f);!k.eol();){if(k.pos>a.options.maxHighlightLength?(h=!1,g&&vf(a,b,d,k.pos),k.pos=b.length,l=null):l=of(qf(c,k,d,m),f),m){var n=m[0].name;n&&(l="m-"+(l?n+" "+l:n))}h&&j==l||(i<k.start&&e(k.start,j),i=k.start,j=l),k.start=k.pos}for(;i<k.pos;){var o=Math.min(k.pos,i+5e4);e(o,j),i=o}}function tf(a,b,c,d){var e=[a.state.modeGen],f={};sf(a,b.text,a.doc.mode,c,function(a,b){e.push(a,b)},f,d);for(var g=0;g<a.state.overlays.length;++g){var h=a.state.overlays[g],i=1,j=0;sf(a,b.text,h.mode,!0,function(a,b){for(var c=i;a>j;){var d=e[i];d>a&&e.splice(i,1,a,e[i+1],d),i+=2,j=Math.min(a,d)}if(b)if(h.o
 paque)e.splice(c,i-c,a,"cm-overlay "+b),i=c+2;else for(;i>c;c+=2){var f=e[c+1];e[c+1]=(f?f+" ":"")+"cm-overlay "+b}},f)}return{styles:e,classes:f.bgClass||f.textClass?f:null}}function uf(a,b,c){if(!b.styles||b.styles[0]!=a.state.modeGen){var d=tf(a,b,b.stateAfter=Wb(a,Uf(b)));b.styles=d.styles,d.classes?b.styleClasses=d.classes:b.styleClasses&&(b.styleClasses=null),c===a.doc.frontier&&a.doc.frontier++}return b.styles}function vf(a,b,c,d){var e=a.doc.mode,f=new Ae(b,a.options.tabSize);for(f.start=f.pos=d||0,""==b&&pf(e,c);!f.eol()&&f.pos<=a.options.maxHighlightLength;)qf(e,f,c),f.start=f.pos}function yf(a,b){if(!a||/^\s*$/.test(a))return null;var c=b.addModeClass?xf:wf;return c[a]||(c[a]=a.replace(/\S+/g,"cm-$&"))}function zf(a,b){var c=Yg("span",null,null,f?"padding-right: .1px":null),e={pre:Yg("pre",[c]),content:c,col:0,pos:0,cm:a};b.measure={};for(var g=0;g<=(b.rest?b.rest.length:0);g++){var i,h=g?b.rest[g-1]:b.line;e.pos=0,e.addToken=Bf,(d||f)&&a.getOption("lineWrapping")&&(e.add
 Token=Cf(e.addToken)),qh(a.display.measure)&&(i=Xf(h))&&(e.addToken=Df(e.addToken,i)),e.map=[];var j=b!=a.display.externalMeasured&&Uf(h);Ff(h,e,uf(a,h,j)),h.styleClasses&&(h.styleClasses.bgClass&&(e.bgClass=fh(h.styleClasses.bgClass,e.bgClass||"")),h.styleClasses.textClass&&(e.textClass=fh(h.styleClasses.textClass,e.textClass||""))),0==e.map.length&&e.map.push(0,0,e.content.appendChild(oh(a.display.measure))),0==g?(b.measure.map=e.map,b.measure.cache={}):((b.measure.maps||(b.measure.maps=[])).push(e.map),(b.measure.caches||(b.measure.caches=[])).push({}))}return f&&/\bcm-tab\b/.test(e.content.lastChild.className)&&(e.content.className="cm-tab-wrap-hack"),tg(a,"renderLine",a,b.line,e.pre),e.pre.className&&(e.textClass=fh(e.pre.className,e.textClass||"")),e}function Af(a){var b=Yg("span","\u2022","cm-invalidchar");return b.title="\\u"+a.charCodeAt(0).toString(16),b}function Bf(a,b,c,f,g,h){if(b){var i=a.cm.options.specialChars,j=!1;if(i.test(b))for(var k=document.createDocumentFragme
 nt(),l=0;;){i.lastIndex=l;var m=i.exec(b),n=m?m.index-l:b.length-l;if(n){var o=document.createTextNode(b.slice(l,l+n));d&&9>e?k.appendChild(Yg("span",[o])):k.appendChild(o),a.map.push(a.pos,a.pos+n,o),a.col+=n,a.pos+=n}if(!m)break;if(l+=n+1,"	"==m[0]){var p=a.cm.options.tabSize,q=p-a.col%p,o=k.appendChild(Yg("span",Kg(q),"cm-tab"));a.col+=q}else{var o=a.cm.options.specialCharPlaceholder(m[0]);d&&9>e?k.appendChild(Yg("span",[o])):k.appendChild(o),a.col+=1}a.map.push(a.pos,a.pos+1,o),a.pos++}else{a.col+=b.length;var k=document.createTextNode(b);a.map.push(a.pos,a.pos+b.length,k),d&&9>e&&(j=!0),a.pos+=b.length}if(c||f||g||j){var r=c||"";f&&(r+=f),g&&(r+=g);var s=Yg("span",[k],r);return h&&(s.title=h),a.content.appendChild(s)}a.content.appendChild(k)}}function Cf(a){function b(a){for(var b=" ",c=0;c<a.length-2;++c)b+=c%2?" ":"\xa0";return b+=" "}return function(c,d,e,f,g,h){a(c,d.replace(/ {3,}/g,b),e,f,g,h)}}function Df(a,b){return function(c,d,e,f,g,h){e=e?e+" cm-force-border":"cm-for
 ce-border";for(var i=c.pos,j=i+d.length;;){for(var k=0;k<b.length;k++){var l=b[k];if(l.to>i&&l.from<=i)break}if(l.to>=j)return a(c,d,e,f,g,h);a(c,d.slice(0,l.to-i),e,f,null,h),f=null,d=d.slice(l.to-i),i=l.to}}}function Ef(a,b,c,d){var e=!d&&c.widgetNode;e&&(a.map.push(a.pos,a.pos+b,e),a.content.appendChild(e)),a.pos+=b}function Ff(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var k,m,n,o,p,q,h=e.length,i=0,g=1,j="",l=0;;){if(l==i){m=n=o=p="",q=null,l=1/0;for(var r=[],s=0;s<d.length;++s){var t=d[s],u=t.marker;t.from<=i&&(null==t.to||t.to>i)?(null!=t.to&&l>t.to&&(l=t.to,n=""),u.className&&(m+=" "+u.className),u.startStyle&&t.from==i&&(o+=" "+u.startStyle),u.endStyle&&t.to==l&&(n+=" "+u.endStyle),u.title&&!p&&(p=u.title),u.collapsed&&(!q||Xe(q.marker,u)<0)&&(q=t)):t.from>i&&l>t.from&&(l=t.from),"bookmark"==u.type&&t.from==i&&u.widgetNode&&r.push(u)}if(q&&(q.from||0)==i&&(Ef(b,(null==q.to?h+1:q.to)-i,q.marker,null==q.from),null==q.to))return;if(!q&&r.length)for(var s=0;s<r.length;++s
 )Ef(b,0,r[s])}if(i>=h)break;for(var v=Math.min(h,l);;){if(j){var w=i+j.length;if(!q){var x=w>v?j.slice(0,v-i):j;b.addToken(b,x,k?k+m:m,o,i+x.length==l?n:"",p)}if(w>=v){j=j.slice(v-i),i=v;break}i=w,o=""}j=e.slice(f,f=c[g++]),k=yf(c[g++],b.cm.options)}}else for(var g=1;g<c.length;g+=2)b.addToken(b,e.slice(f,f=c[g]),yf(c[g+1],b.cm.options))}function Gf(a,b){return 0==b.from.ch&&0==b.to.ch&&""==Lg(b.text)&&(!a.cm||a.cm.options.wholeLineUpdateBefore)}function Hf(a,b,c,d){function e(a){return c?c[a]:null}function f(a,c,e){mf(a,c,e,d),vg(a,"change",a,b)}var g=b.from,h=b.to,i=b.text,j=Qf(a,g.line),k=Qf(a,h.line),l=Lg(i),m=e(i.length-1),n=h.line-g.line;if(Gf(a,b)){for(var o=0,p=[];o<i.length-1;++o)p.push(new lf(i[o],e(o),d));f(k,k.text,m),n&&a.remove(g.line,n),p.length&&a.insert(g.line,p)}else if(j==k)if(1==i.length)f(j,j.text.slice(0,g.ch)+l+j.text.slice(h.ch),m);else{for(var p=[],o=1;o<i.length-1;++o)p.push(new lf(i[o],e(o),d));p.push(new lf(l+j.text.slice(h.ch),m,d)),f(j,j.text.slice(0,g.
 ch)+i[0],e(0)),a.insert(g.line+1,p)}else if(1==i.length)f(j,j.text.slice(0,g.ch)+i[0]+k.text.slice(h.ch),e(0)),a.remove(g.line+1,n);else{f(j,j.text.slice(0,g.ch)+i[0],e(0)),f(k,l+k.text.slice(h.ch),m);for(var o=1,p=[];o<i.length-1;++o)p.push(new lf(i[o],e(o),d));n>1&&a.remove(g.line+1,n-1),a.insert(g.line+1,p)}vg(a,"change",a,b)}function If(a){this.lines=a,this.parent=null;for(var b=0,c=0;b<a.length;++b)a[b].parent=this,c+=a[b].height;this.height=c}function Jf(a){this.children=a;for(var b=0,c=0,d=0;d<a.length;++d){var e=a[d];b+=e.chunkSize(),c+=e.height,e.parent=this}this.size=b,this.height=c,this.parent=null}function Of(a,b,c){function d(a,e,f){if(a.linked)for(var g=0;g<a.linked.length;++g){var h=a.linked[g];if(h.doc!=e){var i=f&&h.sharedHist;(!c||i)&&(b(h.doc,i),d(h.doc,a,i))}}}d(a,null,!0)}function Pf(a,b){if(b.cm)throw new Error("This document is already in use.");a.doc=b,b.cm=a,C(a),y(a),a.options.lineWrapping||I(a),a.options.mode=b.modeOption,Pc(a)}function Qf(a,b){if(b-=a.fir
 st,0>b||b>=a.size)throw new Error("There is no line "+(b+a.first)+" in the document.");for(var c=a;!c.lines;)for(var d=0;;++d){var e=c.children[d],f=e.chunkSize();if(f>b){c=e;break}b-=f}return c.lines[b]}function Rf(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function Sf(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function Tf(a,b){var c=b-a.height;if(c)for(var d=a;d;d=d.parent)d.height+=c}function Uf(a){if(null==a.parent)return null;for(var b=a.parent,c=Ng(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function Vf(a,b){var c=a.first;a:do{for(var d=0;d<a.children.length;++d){var e=a.children[d],f=e.height;if(f>b){a=e;continue a}b-=f,c+=e.chunkSize()}return c}while(!a.lines);for(var d=0;d<a.lines.length;++d){var g=a.lines[d],h=g.height;if(h>b)break;b-=h}return c+d}function Wf(a){a=a
 f(a);for(var b=0,c=a.parent,d=0;d<c.lines.length;++d){var e=c.lines[d];if(e==a)break;b+=e.height}for(var f=c.parent;f;c=f,f=c.parent)for(var d=0;d<f.children.length;++d){var g=f.children[d];if(g==c)break;b+=g.height}return b}function Xf(a){var b=a.order;return null==b&&(b=a.order=Lh(a.text)),b}function Yf(a){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=a||1}function Zf(a,b){var c={from:ob(b.from),to:Ld(b),text:Rf(a,b.from,b.to)};return eg(a,c,b.from.line,b.to.line+1),Of(a,function(a){eg(a,c,b.from.line,b.to.line+1)},!0),c}function $f(a){for(;a.length;){var b=Lg(a);if(!b.ranges)break;a.pop()}}function _f(a,b){return b?($f(a.done),Lg(a.done)):a.done.length&&!Lg(a.done).ranges?Lg(a.done):a.done.length>1&&!a.done[a.done.length-2].ranges?(a.done.pop(),Lg(a.done)):void 0}function ag(a,b,c,d){var e=a.history;e.undone.length=0;var g,f=+new Date;if(
 (e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&("+"==b.origin.charAt(0)&&a.cm&&e.lastModTime>f-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))&&(g=_f(e,e.lastOp==d))){var h=Lg(g.changes);0==nb(b.from,b.to)&&0==nb(b.from,h.to)?h.to=Ld(b):g.changes.push(Zf(a,b))}else{var i=Lg(e.done);for(i&&i.ranges||dg(a.sel,e.done),g={changes:[Zf(a,b)],generation:e.generation},e.done.push(g);e.done.length>e.undoDepth;)e.done.shift(),e.done[0].ranges||e.done.shift()}e.done.push(c),e.generation=++e.maxGeneration,e.lastModTime=e.lastSelTime=f,e.lastOp=e.lastSelOp=d,e.lastOrigin=e.lastSelOrigin=b.origin,h||tg(a,"historyAdded")}function bg(a,b,c,d){var e=b.charAt(0);return"*"==e||"+"==e&&c.ranges.length==d.ranges.length&&c.somethingSelected()==d.somethingSelected()&&new Date-a.history.lastSelTime<=(a.cm?a.cm.options.historyEventDelay:500)}function cg(a,b,c,d){var e=a.history,f=d&&d.origin;c==e.lastSelOp||f&&e.lastSelOrigin==f&&(e.lastModTime==e.lastSelTime&&e.lastOrigin==f||bg(a,f,Lg(e.done),b
 ))?e.done[e.done.length-1]=b:dg(b,e.done),e.lastSelTime=+new Date,e.lastSelOrigin=f,e.lastSelOp=c,d&&d.clearRedo!==!1&&$f(e.undone)}function dg(a,b){var c=Lg(b);c&&c.ranges&&c.equals(a)||b.push(a)}function eg(a,b,c,d){var e=b["spans_"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b["spans_"+a.id]={}))[f]=c.markedSpans),++f})}function fg(a){if(!a)return null;for(var c,b=0;b<a.length;++b)a[b].marker.explicitlyCleared?c||(c=a.slice(0,b)):c&&c.push(a[b]);return c?c.length?c:null:a}function gg(a,b){var c=b["spans_"+a.id];if(!c)return null;for(var d=0,e=[];d<b.text.length;++d)e.push(fg(c[d]));return e}function hg(a,b,c){for(var d=0,e=[];d<a.length;++d){var f=a[d];if(f.ranges)e.push(c?rb.prototype.deepCopy.call(f):f);else{var g=f.changes,h=[];e.push({changes:h});for(var i=0;i<g.length;++i){var k,j=g[i];if(h.push({from:j.from,to:j.to,text:j.text}),b)for(var l in j)(k=l.match(/^spans_(\d+)$/))&&Ng(b,Number(k[1]))>-1&&(Lg(h)[l]=j[l],delete 
 j[l])}}}return e}function ig(a,b,c,d){c<a.line?a.line+=d:b<a.line&&(a.line=b,a.ch=0)}function jg(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e],g=!0;if(f.ranges){f.copied||(f=a[e]=f.deepCopy(),f.copied=!0);for(var h=0;h<f.ranges.length;h++)ig(f.ranges[h].anchor,b,c,d),ig(f.ranges[h].head,b,c,d)}else{for(var h=0;h<f.changes.length;++h){var i=f.changes[h];if(c<i.from.line)i.from=mb(i.from.line+d,i.from.ch),i.to=mb(i.to.line+d,i.to.ch);else if(b<=i.to.line){g=!1;break}}g||(a.splice(0,e+1),e=0)}}}function kg(a,b){var c=b.from.line,d=b.to.line,e=b.text.length-(d-c)-1;jg(a.done,c,d,e),jg(a.undone,c,d,e)}function ng(a){return null!=a.defaultPrevented?a.defaultPrevented:0==a.returnValue}function pg(a){return a.target||a.srcElement}function qg(a){var b=a.which;return null==b&&(1&a.button?b=1:2&a.button?b=3:4&a.button&&(b=2)),p&&a.ctrlKey&&1==b&&(b=3),b}function vg(a,b){function f(a){return function(){a.apply(null,d)}}var c=a._handlers&&a._handlers[b];if(c){var e,d=Array.prototype.slice.call
 (arguments,2);yc?e=yc.delayedCallbacks:ug?e=ug:(e=ug=[],setTimeout(wg,0));for(var g=0;g<c.length;++g)e.push(f(c[g]))}}function wg(){var a=ug;ug=null;for(var b=0;b<a.length;++b)a[b]()}function xg(a,b,c){return"string"==typeof b&&(b={type:b,preventDefault:function(){this.defaultPrevented=!0}}),tg(a,c||b.type,a,b),ng(b)||b.codemirrorIgnore}function yg(a){var b=a._handlers&&a._handlers.cursorActivity;if(b)for(var c=a.curOp.cursorActivityHandlers||(a.curOp.cursorActivityHandlers=[]),d=0;d<b.length;++d)-1==Ng(c,b[d])&&c.push(b[d])}function zg(a,b){var c=a._handlers&&a._handlers[b];return c&&c.length>0}function Ag(a){a.prototype.on=function(a,b){rg(this,a,b)},a.prototype.off=function(a,b){sg(this,a,b)}}function Gg(){this.id=null}function Ig(a,b,c){for(var d=0,e=0;;){var f=a.indexOf("	",d);-1==f&&(f=a.length);var g=f-d;if(f==a.length||e+g>=b)return d+Math.min(g,b-e);if(e+=f-d,e+=c-e%c,d=f+1,e>=b)return d}}function Kg(a){for(;Jg.length<=a;)Jg.push(Lg(Jg)+" ");return Jg[a]}function Lg(a){retu
 rn a[a.length-1]}function Ng(a,b){for(var c=0;c<a.length;++c)if(a[c]==b)return c;return-1}function Og(a,b){for(var c=[],d=0;d<a.length;d++)c[d]=b(a[d],d);return c}function Pg(a,b){var c;if(Object.create)c=Object.create(a);else{var d=function(){};d.prototype=a,c=new d}return b&&Qg(b,c),c}function Qg(a,b,c){b||(b={});for(var d in a)!a.hasOwnProperty(d)||c===!1&&b.hasOwnProperty(d)||(b[d]=a[d]);return b}function Rg(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function Ug(a,b){return b?b.source.indexOf("\\w")>-1&&Tg(a)?!0:b.test(a):Tg(a)}function Vg(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function Xg(a){return a.charCodeAt(0)>=768&&Wg.test(a)}function Yg(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)e.appendChild(document.createTextNode(b));else if(b)for(var f=0;f<b.length;++f)e.appendChild(b[f]);return e}function $g(a){for(var b=a.childNodes.length;b>0;--b)a
 .removeChild(a.firstChild);return a}function _g(a,b){return $g(a).appendChild(b)}function ah(a,b){if(a.contains)return a.contains(b);for(;b=b.parentNode;)if(b==a)return!0}function bh(){return document.activeElement}function ch(a){return new RegExp("(^|\\s)"+a+"(?:$|\\s)\\s*")}function fh(a,b){for(var c=a.split(" "),d=0;d<c.length;d++)c[d]&&!ch(c[d]).test(b)&&(b+=" "+c[d]);return b}function gh(a){if(document.body.getElementsByClassName)for(var b=document.body.getElementsByClassName("CodeMirror"),c=0;c<b.length;c++){var d=b[c].CodeMirror;d&&a(d)}}function ih(){hh||(jh(),hh=!0)}function jh(){var a;rg(window,"resize",function(){null==a&&(a=setTimeout(function(){a=null,lh=null,gh(dd)},100))}),rg(window,"blur",function(){gh(Id)})}function mh(a){if(null!=lh)return lh;var b=Yg("div",null,null,"width: 50px; height: 50px; overflow-x: scroll");return _g(a,b),b.offsetWidth&&(lh=b.offsetHeight-b.clientHeight),lh||0}function oh(a){if(null==nh){var b=Yg("span","\u200b");_g(a,Yg("span",[b,document.
 createTextNode("x")])),0!=a.firstChild.offsetHeight&&(nh=b.offsetWidth<=1&&b.offsetHeight>2&&!(d&&8>e))}return nh?Yg("span","\u200b"):Yg("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px")}function qh(a){if(null!=ph)return ph;var b=_g(a,document.createTextNode("A\u062eA")),c=Zg(b,0,1).getBoundingClientRect();if(!c||c.left==c.right)return!1;var d=Zg(b,1,2).getBoundingClientRect();return ph=d.right-c.right<3}function vh(a){if(null!=uh)return uh;var b=_g(a,Yg("span","x")),c=b.getBoundingClientRect(),d=Zg(b,0,1).getBoundingClientRect();return uh=Math.abs(c.left-d.left)>1}function xh(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;f<a.length;++f){var g=a[f];(g.from<c&&g.to>b||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function yh(a){return a.level%2?a.to:a.from}function zh(a){return a.level%2?a.from:a.to}function Ah(a){var b=Xf(a);return b?yh(b[0]):0}function Bh(a){var b=Xf(a);return b?zh(Lg(b)):a.text.
 length}function Ch(a,b){var c=Qf(a.doc,b),d=af(c);d!=c&&(b=Uf(d));var e=Xf(d),f=e?e[0].level%2?Bh(d):Ah(d):0;return mb(b,f)}function Dh(a,b){for(var c,d=Qf(a.doc,b);c=$e(d);)d=c.find(1,!0).line,b=null;var e=Xf(d),f=e?e[0].level%2?Ah(d):Bh(d):d.text.length;return mb(

<TRUNCATED>

[02/28] incubator-nifi git commit: Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/incubator-nifi into develop

Posted by mc...@apache.org.
Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/incubator-nifi into develop


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/cb63c666
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/cb63c666
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/cb63c666

Branch: refs/heads/nifi-27
Commit: cb63c66602a398b0c14cc78732db5ca63e36a94c
Parents: 567dfc7 0125f3d
Author: Mark Payne <ma...@hotmail.com>
Authored: Tue Dec 9 11:20:13 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Tue Dec 9 11:20:13 2014 -0500

----------------------------------------------------------------------
 nar-bundles/framework-bundle/framework/site-to-site/pom.xml | 4 ++++
 nar-bundles/framework-bundle/pom.xml                        | 5 +++++
 2 files changed, 9 insertions(+)
----------------------------------------------------------------------



[07/28] incubator-nifi git commit: NIFI-145: Bug Fixes and updated nifi.sh to use bootstrap code

Posted by mc...@apache.org.
NIFI-145: Bug Fixes and updated nifi.sh to use bootstrap code


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/192d7822
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/192d7822
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/192d7822

Branch: refs/heads/nifi-27
Commit: 192d7822772752cb939921af1610476c8e7dcfda
Parents: 6d46829
Author: Mark Payne <ma...@hotmail.com>
Authored: Wed Dec 10 11:03:21 2014 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Wed Dec 10 11:03:21 2014 -0500

----------------------------------------------------------------------
 .../apache/nifi/controller/FlowController.java  |  15 ++
 .../repository/FileSystemRepository.java        |   4 +-
 .../WriteAheadFlowFileRepository.java           |   7 +-
 .../scheduling/StandardProcessScheduler.java    |   3 +
 .../java/org/apache/nifi/engine/FlowEngine.java |  15 ++
 .../src/main/resources/bin/nifi-status.bat      |  19 +-
 .../resources/src/main/resources/bin/nifi.sh    | 193 +------------------
 .../src/main/resources/bin/run-nifi.bat         |  19 +-
 .../src/main/resources/bin/start-nifi.bat       |  19 +-
 .../src/main/resources/bin/stop-nifi.bat        |  19 +-
 .../java/org/apache/nifi/bootstrap/RunNiFi.java |  15 +-
 .../org/apache/nifi/bootstrap/ShutdownHook.java |  13 +-
 12 files changed, 130 insertions(+), 211 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/FlowController.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/FlowController.java b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/FlowController.java
index a0a07f2..20c50b5 100644
--- a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/FlowController.java
+++ b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/FlowController.java
@@ -1045,6 +1045,21 @@ public class FlowController implements EventAccess, ControllerServiceProvider, H
             if (flowFileSwapManager != null) {
                 flowFileSwapManager.shutdown();
             }
+            
+            if ( processScheduler != null ) {
+            	processScheduler.shutdown();
+            }
+            
+            if ( provenanceEventRepository != null ) {
+            	try {
+            		provenanceEventRepository.close();
+            	} catch (final IOException ioe) {
+            		LOG.warn("There was a problem shutting down the Provenance Repository: " + ioe.toString());
+            		if ( LOG.isDebugEnabled() ) {
+            			LOG.warn("", ioe);
+            		}
+            	}
+            }
         } finally {
             writeLock.unlock();
         }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/FileSystemRepository.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/FileSystemRepository.java b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/FileSystemRepository.java
index 8be9c62..ba74295 100644
--- a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/FileSystemRepository.java
+++ b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/FileSystemRepository.java
@@ -92,7 +92,7 @@ public class FileSystemRepository implements ContentRepository {
     private final List<String> containerNames;
     private final AtomicLong index;
 
-    private final ScheduledExecutorService executor = new FlowEngine(4, "FileSystemRepository Workers");
+    private final ScheduledExecutorService executor = new FlowEngine(4, "FileSystemRepository Workers", true);
     private final ConcurrentMap<String, BlockingQueue<ContentClaim>> reclaimable = new ConcurrentHashMap<>();
     private final Map<String, ContainerState> containerStateMap = new HashMap<>();
 
@@ -209,7 +209,7 @@ public class FileSystemRepository implements ContentRepository {
             }
         }
 
-        containerCleanupExecutor = new FlowEngine(containers.size(), "Cleanup FileSystemRepository Container");
+        containerCleanupExecutor = new FlowEngine(containers.size(), "Cleanup FileSystemRepository Container", true);
         for (final Map.Entry<String, Path> containerEntry : containers.entrySet()) {
             final String containerName = containerEntry.getKey();
             final Path containerPath = containerEntry.getValue();

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/WriteAheadFlowFileRepository.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/WriteAheadFlowFileRepository.java b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/WriteAheadFlowFileRepository.java
index ab3a6a1..292c258 100644
--- a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/WriteAheadFlowFileRepository.java
+++ b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/repository/WriteAheadFlowFileRepository.java
@@ -90,6 +90,7 @@ public class WriteAheadFlowFileRepository implements FlowFileRepository, SyncLis
     private final long checkpointDelayMillis;
     private final Path flowFileRepositoryPath;
     private final int numPartitions;
+    private final ScheduledExecutorService checkpointExecutor;
 
     // effectively final
     private WriteAheadRepository<RepositoryRecord> wal;
@@ -128,6 +129,8 @@ public class WriteAheadFlowFileRepository implements FlowFileRepository, SyncLis
         flowFileRepositoryPath = properties.getFlowFileRepositoryPath();
         numPartitions = properties.getFlowFileRepositoryPartitions();
         checkpointDelayMillis = FormatUtils.getTimeDuration(properties.getFlowFileRepositoryCheckpointInterval(), TimeUnit.MILLISECONDS);
+        
+        checkpointExecutor = Executors.newSingleThreadScheduledExecutor();
     }
 
     @Override
@@ -150,6 +153,7 @@ public class WriteAheadFlowFileRepository implements FlowFileRepository, SyncLis
             checkpointFuture.cancel(false);
         }
 
+        checkpointExecutor.shutdown();
         wal.shutdown();
     }
 
@@ -363,8 +367,7 @@ public class WriteAheadFlowFileRepository implements FlowFileRepository, SyncLis
             }
         };
 
-        final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
-        checkpointFuture = executorService.scheduleWithFixedDelay(checkpointRunnable, checkpointDelayMillis, checkpointDelayMillis, TimeUnit.MILLISECONDS);
+        checkpointFuture = checkpointExecutor.scheduleWithFixedDelay(checkpointRunnable, checkpointDelayMillis, checkpointDelayMillis, TimeUnit.MILLISECONDS);
 
         return maxId;
     }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java
index 0d5055a..7fc65f9 100644
--- a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java
+++ b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java
@@ -138,6 +138,9 @@ public final class StandardProcessScheduler implements ProcessScheduler {
                 LOG.error("", t);
             }
         }
+        
+        frameworkTaskExecutor.shutdown();
+        componentLifeCycleThreadPool.shutdown();
     }
 
     public void schedule(final ReportingTaskNode taskNode) {

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/engine/FlowEngine.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/engine/FlowEngine.java b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/engine/FlowEngine.java
index 2430f56..76e8e3e 100644
--- a/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/engine/FlowEngine.java
+++ b/nar-bundles/framework-bundle/framework/core/src/main/java/org/apache/nifi/engine/FlowEngine.java
@@ -42,6 +42,18 @@ public final class FlowEngine extends ScheduledThreadPoolExecutor {
      * @param threadNamePrefix
      */
     public FlowEngine(int corePoolSize, final String threadNamePrefix) {
+    	this(corePoolSize, threadNamePrefix, false);
+    }
+    	
+    /**
+     * Creates a new instance of FlowEngine
+     *
+     * @param corePoolSize the maximum number of threads available to tasks
+     * running in the engine.
+     * @param threadNamePrefix
+     * @param deamon if true, the thread pool will be populated with daemon threads, otherwise the threads will not be marked as daemon.
+     */
+    public FlowEngine(int corePoolSize, final String threadNamePrefix, final boolean daemon) {
         super(corePoolSize);
 
         final AtomicInteger threadIndex = new AtomicInteger(0);
@@ -50,6 +62,9 @@ public final class FlowEngine extends ScheduledThreadPoolExecutor {
             @Override
             public Thread newThread(final Runnable r) {
                 final Thread t = defaultThreadFactory.newThread(r);
+                if ( daemon ) {
+                	t.setDaemon(true);
+                }
                 t.setName(threadNamePrefix + " Thread-" + threadIndex.incrementAndGet());
                 return t;
             }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat
index 9b88349..ed9c516 100644
--- a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi-status.bat
@@ -1,3 +1,20 @@
+rem
+rem    Licensed to the Apache Software Foundation (ASF) under one or more
+rem    contributor license agreements.  See the NOTICE file distributed with
+rem    this work for additional information regarding copyright ownership.
+rem    The ASF licenses this file to You under the Apache License, Version 2.0
+rem    (the "License"); you may not use this file except in compliance with
+rem    the License.  You may obtain a copy of the License at
+rem
+rem       http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem    Unless required by applicable law or agreed to in writing, software
+rem    distributed under the License is distributed on an "AS IS" BASIS,
+rem    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem    See the License for the specific language governing permissions and
+rem    limitations under the License.
+rem
+
 @echo off
 
 rem Use JAVA_HOME if it's set; otherwise, just use java
@@ -7,7 +24,7 @@ SET LIB_DIR=%~dp0..\lib
 SET CONF_DIR=%~dp0..\conf
 
 SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
-SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+SET JAVA_ARGS=-Dorg.apache.nifi.bootstrap.config.file=%BOOTSTRAP_CONF_FILE%
 
 SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
 SET BOOTSTRAP_ACTION=status

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
index d069fc9..81ae384 100644
--- a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/nifi.sh
@@ -21,34 +21,6 @@
 DIRNAME=`dirname "$0"`
 PROGNAME=`basename "$0"`
 
-#
-# Sourcing environment settings for NIFI similar to tomcats setenv
-#
-NIFI_SCRIPT="nifi.sh"
-export NIFI_SCRIPT
-if [ -f "$DIRNAME/setenv.sh" ]; then
-  . "$DIRNAME/setenv.sh"
-fi
-
-#
-# Check/Set up some easily accessible MIN/MAX params for JVM mem usage
-#
-if [ "x$JAVA_MIN_MEM" = "x" ]; then
-    JAVA_MIN_MEM=512M
-    export JAVA_MIN_MEM
-fi
-if [ "x$JAVA_MAX_MEM" = "x" ]; then
-    JAVA_MAX_MEM=512M
-    export JAVA_MAX_MEM
-fi
-if [ "x$JAVA_PERMSIZE" = "x" ]; then
-    JAVA_PERMSIZE=128M
-    export JAVA_PERMSIZE
-fi
-if [ "x$JAVA_MAX_PERMSIZE" = "x" ]; then
-    JAVA_MAX_PERMSIZE=128M
-    export JAVA_MAX_PERMSIZE
-fi
 
 
 warn() {
@@ -128,58 +100,6 @@ locateHome() {
 
 }
 
-locateBase() {
-    if [ "x$NIFI_BASE" != "x" ]; then
-        if [ ! -d "$NIFI_BASE" ]; then
-            die "NIFI_BASE is not valid: $NIFI_BASE"
-        fi
-    else
-        NIFI_BASE=$NIFI_HOME
-    fi
-}
-
-
-locateConf() {
-    if [ "x$NIFI_CONF" != "x" ]; then
-        if [ ! -d "$NIFI_CONF" ]; then
-            die "NIFI_CONF is not valid: $NIFI_CONF"
-        fi
-    else
-        NIFI_CONF=$NIFI_BASE/conf
-    fi
-}
-
-setupNativePath() {
-    # Support for loading native libraries
-    LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$NIFI_BASE/lib:$NIFI_HOME/lib"
-
-    # For Cygwin, set PATH from LD_LIBRARY_PATH
-    if $cygwin; then
-        LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"`
-        PATH="$PATH;$LD_LIBRARY_PATH"
-        export PATH
-    fi
-    export LD_LIBRARY_PATH
-}
-
-pathCanonical() {
-    local dst="${1}"
-    while [ -h "${dst}" ] ; do
-        ls=`ls -ld "${dst}"`
-        link=`expr "$ls" : '.*-> \(.*\)$'`
-        if expr "$link" : '/.*' > /dev/null; then
-            dst="$link"
-        else
-            dst="`dirname "${dst}"`/$link"
-        fi
-    done
-    local bas=`basename "${dst}"`
-    local dir=`dirname "${dst}"`
-    if [ "$bas" != "$dir" ]; then
-        dst="`pathCanonical "$dir"`/$bas"
-    fi
-    echo "${dst}" | sed -e 's#//#/#g' -e 's#/./#/#g' -e 's#/[^/]*/../#/#g'
-}
 
 locateJava() {
     # Setup the Java Virtual Machine
@@ -211,82 +131,6 @@ locateJava() {
     fi
 }
 
-detectJVM() {
-   #echo "`$JAVA -version`"
-   # This service should call `java -version`,
-   # read stdout, and look for hints
-   if $JAVA -version 2>&1 | grep "^IBM" ; then
-       JVM_VENDOR="IBM"
-   # on OS/400, java -version does not contain IBM explicitly
-   elif $os400; then
-       JVM_VENDOR="IBM"
-   else
-       JVM_VENDOR="SUN"
-   fi
-   # echo "JVM vendor is $JVM_VENDOR"
-}
-
-setupDebugOptions() {
-    if [ "x$JAVA_OPTS" = "x" ]; then
-        JAVA_OPTS="$DEFAULT_JAVA_OPTS"
-    fi
-    export JAVA_OPTS
-
-    if [ "x$EXTRA_JAVA_OPTS" != "x" ]; then
-        JAVA_OPTS="$JAVA_OPTS $EXTRA_JAVA_OPTS"
-    fi
-
-    # Set Debug options if enabled
-    if [ "x$NIFI_DEBUG" != "x" ]; then
-        # Use the defaults if JAVA_DEBUG_OPTS was not set
-        if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then
-            JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
-        fi
-
-        JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS"
-        warn "Enabling Java debug options: $JAVA_DEBUG_OPTS"
-    fi
-}
-
-setupDefaults() {
-    DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM -XX:PermSize=$JAVA_PERMSIZE -XX:MaxPermSize=$JAVA_MAX_PERMSIZE"
-
-    #Set the JVM_VENDOR specific JVM flags
-    if [ "$JVM_VENDOR" = "SUN" ]; then
-        #
-        # Check some easily accessible MIN/MAX params for JVM mem usage
-        #
-        if [ "x$JAVA_PERM_MEM" != "x" ]; then
-            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:PermSize=$JAVA_PERM_MEM"
-        fi
-        if [ "x$JAVA_MAX_PERM_MEM" != "x" ]; then
-            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:MaxPermSize=$JAVA_MAX_PERM_MEM"
-        fi
-        DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote"
-    elif [ "$JVM_VENDOR" = "IBM" ]; then
-        if $os400; then
-            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS"
-        elif $aix; then
-            DEFAULT_JAVA_OPTS="-Xverify:none -Xdump:heap -Xlp $DEFAULT_JAVA_OPTS"
-        else
-            DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS"
-        fi
-    fi
-
-    DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS  -Djava.net.preferIPv4Stack=true -Dsun.net.http.allowRestrictedHeaders=true -Djava.protocol.handler.pkgs=sun.net.www.protocol -Dorg.apache.jasper.compiler.disablejsr199=true -XX:ReservedCodeCacheSize=128m -XX:+UseCodeCacheFlushing"
-    
-    # Setup classpath
-    CLASSPATH="$NIFI_HOME"/conf
-    for f in "$NIFI_HOME"/lib/*
-    do
-      CLASSPATH="${CLASSPATH}":"${f}"
-    done
-    
-    
-    DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
-
-}
-
 init() {
     # Determine if there is special OS handling we must perform
     detectOS
@@ -297,49 +141,28 @@ init() {
     # Locate the NiFi home directory
     locateHome
 
-    # Locate the NiFi base directory
-    locateBase
-
-    # Locate the NiFi conf directory
-    locateConf
-
-    # Setup the native library path
-    setupNativePath
-
     # Locate the Java VM to execute
     locateJava
-
-    # Determine the JVM vendor
-    detectJVM
-
-    # Setup default options
-    setupDefaults
-
-    # Install debug options
-    setupDebugOptions
-
 }
 
 run() {
-
+	BOOTSTRAP_CONF="$NIFI_HOME/conf/bootstrap.conf";
+	
     if $cygwin; then
         NIFI_HOME=`cygpath --path --windows "$NIFI_HOME"`
-        NIFI_BASE=`cygpath --path --windows "$NIFI_BASE"`
-        NIFI_CONF=`cygpath --path --windows "$NIFI_CONF"`
-        CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+        BOOTSTRAP_CONF=`cygpath --path --windows "$BOOTSTRAP_CONF"`
     fi
-    # export CLASSPATH to the java process. Could also pass in via -cp
-    export CLASSPATH
+    
     echo 
     echo "Classpath: $CLASSPATH"
     echo
     echo "Java home: $JAVA_HOME"
     echo "NiFi home: $NIFI_HOME"
-    echo "Java Options: $JAVA_OPTS"
     echo
-    echo "Launching NiFi.  See logs..."
-    exec "$JAVA" -Dapp=nifi $JAVA_OPTS -Dnifi.properties.file.path="$NIFI_HOME"/conf/nifi.properties org.apache.nifi.NiFi
-
+    echo "Bootstrap Config File: $BOOTSTRAP_CONF"
+    echo
+    
+    exec "$JAVA" -cp "$NIFI_HOME"/lib/nifi-bootstrap*.jar -Xms12m -Xmx24m -Dorg.apache.nifi.bootstrap.config.file="$BOOTSTRAP_CONF" org.apache.nifi.bootstrap.RunNiFi $1
 }
 
 main() {

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat
index ee00204..fdff815 100644
--- a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/run-nifi.bat
@@ -1,3 +1,20 @@
+rem
+rem    Licensed to the Apache Software Foundation (ASF) under one or more
+rem    contributor license agreements.  See the NOTICE file distributed with
+rem    this work for additional information regarding copyright ownership.
+rem    The ASF licenses this file to You under the Apache License, Version 2.0
+rem    (the "License"); you may not use this file except in compliance with
+rem    the License.  You may obtain a copy of the License at
+rem
+rem       http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem    Unless required by applicable law or agreed to in writing, software
+rem    distributed under the License is distributed on an "AS IS" BASIS,
+rem    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem    See the License for the specific language governing permissions and
+rem    limitations under the License.
+rem
+
 @echo off
 
 rem Use JAVA_HOME if it's set; otherwise, just use java
@@ -7,7 +24,7 @@ SET LIB_DIR=%~dp0..\lib
 SET CONF_DIR=%~dp0..\conf
 
 SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
-SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+SET JAVA_ARGS=-Dorg.apache.nifi.bootstrap.config.file=%BOOTSTRAP_CONF_FILE%
 
 SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
 SET BOOTSTRAP_ACTION=run

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat
index c088672..ba4739a 100644
--- a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/start-nifi.bat
@@ -1,3 +1,20 @@
+rem
+rem    Licensed to the Apache Software Foundation (ASF) under one or more
+rem    contributor license agreements.  See the NOTICE file distributed with
+rem    this work for additional information regarding copyright ownership.
+rem    The ASF licenses this file to You under the Apache License, Version 2.0
+rem    (the "License"); you may not use this file except in compliance with
+rem    the License.  You may obtain a copy of the License at
+rem
+rem       http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem    Unless required by applicable law or agreed to in writing, software
+rem    distributed under the License is distributed on an "AS IS" BASIS,
+rem    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem    See the License for the specific language governing permissions and
+rem    limitations under the License.
+rem
+
 @echo off
 
 rem Use JAVA_HOME if it's set; otherwise, just use java
@@ -7,7 +24,7 @@ SET LIB_DIR=%~dp0..\lib
 SET CONF_DIR=%~dp0..\conf
 
 SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
-SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+SET JAVA_ARGS=-Dorg.apache.nifi.bootstrap.config.file=%BOOTSTRAP_CONF_FILE%
 
 SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
 SET BOOTSTRAP_ACTION=start

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat
index 753b09f..828be6e 100644
--- a/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat
+++ b/nar-bundles/framework-bundle/framework/resources/src/main/resources/bin/stop-nifi.bat
@@ -1,3 +1,20 @@
+rem
+rem    Licensed to the Apache Software Foundation (ASF) under one or more
+rem    contributor license agreements.  See the NOTICE file distributed with
+rem    this work for additional information regarding copyright ownership.
+rem    The ASF licenses this file to You under the Apache License, Version 2.0
+rem    (the "License"); you may not use this file except in compliance with
+rem    the License.  You may obtain a copy of the License at
+rem
+rem       http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem    Unless required by applicable law or agreed to in writing, software
+rem    distributed under the License is distributed on an "AS IS" BASIS,
+rem    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem    See the License for the specific language governing permissions and
+rem    limitations under the License.
+rem
+
 @echo off
 
 rem Use JAVA_HOME if it's set; otherwise, just use java
@@ -7,7 +24,7 @@ SET LIB_DIR=%~dp0..\lib
 SET CONF_DIR=%~dp0..\conf
 
 SET BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
-SET JAVA_ARGS=-Dorg.apache.nifi.boostrap.config.file=%BOOTSTRAP_CONF_FILE%
+SET JAVA_ARGS=-Dorg.apache.nifi.bootstrap.config.file=%BOOTSTRAP_CONF_FILE%
 
 SET JAVA_PARAMS=-cp %LIB_DIR%\nifi-bootstrap*.jar -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.bootstrap.RunNiFi
 SET BOOTSTRAP_ACTION=stop

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
index f93500f..af783a1 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/RunNiFi.java
@@ -54,7 +54,7 @@ import java.util.concurrent.locks.ReentrantLock;
  * If the {@code bootstrap.conf} file cannot be found, throws a {@code FileNotFoundException].
  */
 public class RunNiFi {
-	public static final String DEFAULT_CONFIG_FILE = "./conf/boostrap.conf";
+	public static final String DEFAULT_CONFIG_FILE = "./conf/bootstrap.conf";
 	public static final String DEFAULT_NIFI_PROPS_FILE = "./conf/nifi.properties";
 
 	public static final String GRACEFUL_SHUTDOWN_PROP = "graceful.shutdown.seconds";
@@ -111,7 +111,7 @@ public class RunNiFi {
 				return;
 		}
 		
-		String configFilename = System.getProperty("org.apache.nifi.boostrap.config.file");
+		String configFilename = System.getProperty("org.apache.nifi.bootstrap.config.file");
 		
 		if ( configFilename == null ) {
 			final String nifiHome = System.getenv("NIFI_HOME");
@@ -233,11 +233,11 @@ public class RunNiFi {
 	}
 	
 	
-	private boolean isAlive(final Process process) {
+	public static boolean isAlive(final Process process) {
 		try {
 			process.exitValue();
 			return false;
-		} catch (final IllegalThreadStateException itse) {
+		} catch (final IllegalStateException | IllegalThreadStateException itse) {
 			return true;
 		}
 	}
@@ -253,7 +253,7 @@ public class RunNiFi {
 		final ProcessBuilder builder = new ProcessBuilder();
 
 		if ( !bootstrapConfigFile.exists() ) {
-			throw new FileNotFoundException(DEFAULT_CONFIG_FILE);
+			throw new FileNotFoundException(bootstrapConfigFile.getAbsolutePath());
 		}
 		
 		final Properties properties = new Properties();
@@ -351,6 +351,7 @@ public class RunNiFi {
 		cmd.addAll(javaAdditionalArgs);
 		cmd.add("-Dnifi.properties.file.path=" + nifiPropsFilename);
 		cmd.add("-Dnifi.bootstrap.listen.port=" + listenPort);
+		cmd.add("-Dapp=NiFi");
 		cmd.add("org.apache.nifi.NiFi");
 		
 		builder.command(cmd);
@@ -374,11 +375,11 @@ public class RunNiFi {
 			try {
 				gracefulShutdownSeconds = Integer.parseInt(gracefulShutdown);
 			} catch (final NumberFormatException nfe) {
-				throw new NumberFormatException("The '" + GRACEFUL_SHUTDOWN_PROP + "' property in Boostrap Config File " + bootstrapConfigAbsoluteFile.getAbsolutePath() + " has an invalid value. Must be a non-negative integer");
+				throw new NumberFormatException("The '" + GRACEFUL_SHUTDOWN_PROP + "' property in Bootstrap Config File " + bootstrapConfigAbsoluteFile.getAbsolutePath() + " has an invalid value. Must be a non-negative integer");
 			}
 			
 			if ( gracefulShutdownSeconds < 0 ) {
-				throw new NumberFormatException("The '" + GRACEFUL_SHUTDOWN_PROP + "' property in Boostrap Config File " + bootstrapConfigAbsoluteFile.getAbsolutePath() + " has an invalid value. Must be a non-negative integer");
+				throw new NumberFormatException("The '" + GRACEFUL_SHUTDOWN_PROP + "' property in Bootstrap Config File " + bootstrapConfigAbsoluteFile.getAbsolutePath() + " has an invalid value. Must be a non-negative integer");
 			}
 			
 			Process process = builder.start();

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/192d7822/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
index 781b690..3c5ed1f 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/ShutdownHook.java
@@ -55,11 +55,11 @@ public class ShutdownHook extends Thread {
 		
 		System.out.println("Waiting for Apache NiFi to finish shutting down...");
 		final long startWait = System.nanoTime();
-		while ( isAlive(nifiProcess) ) {
+		while ( RunNiFi.isAlive(nifiProcess) ) {
 			final long waitNanos = System.nanoTime() - startWait;
 			final long waitSeconds = TimeUnit.NANOSECONDS.toSeconds(waitNanos);
 			if ( waitSeconds >= gracefulShutdownSeconds && gracefulShutdownSeconds > 0 ) {
-				if ( isAlive(nifiProcess) ) {
+				if ( RunNiFi.isAlive(nifiProcess) ) {
 					System.out.println("NiFi has not finished shutting down after " + gracefulShutdownSeconds + " seconds. Killing process.");
 					nifiProcess.destroy();
 				}
@@ -76,13 +76,4 @@ public class ShutdownHook extends Thread {
 			System.err.println("Failed to delete status file " + statusFile.getAbsolutePath() + "; this file should be cleaned up manually");
 		}
 	}
-	
-	private boolean isAlive(final Process process) {
-		try {
-			process.exitValue();
-			return false;
-		} catch (final IllegalThreadStateException itse) {
-			return true;
-		}
-	}
 }


[23/28] incubator-nifi git commit: NIFI-27: - Latest version of slickgrid.

Posted by mc...@apache.org.
NIFI-27:
- Latest version of slickgrid.


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/53f44060
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/53f44060
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/53f44060

Branch: refs/heads/nifi-27
Commit: 53f440609bb395393b7fb58e43c06e1fb6f53b30
Parents: 57b4178
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Dec 10 10:12:43 2014 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Wed Dec 10 12:19:26 2014 -0500

----------------------------------------------------------------------
 .../src/main/webapp/WEB-INF/pages/canvas.jsp    |    2 +-
 .../src/main/webapp/WEB-INF/pages/cluster.jsp   |    2 +-
 .../src/main/webapp/WEB-INF/pages/counters.jsp  |    2 +-
 .../src/main/webapp/WEB-INF/pages/history.jsp   |    2 +-
 .../main/webapp/WEB-INF/pages/provenance.jsp    |    2 +-
 .../src/main/webapp/WEB-INF/pages/summary.jsp   |    2 +-
 .../src/main/webapp/WEB-INF/pages/templates.jsp |    2 +-
 .../src/main/webapp/WEB-INF/pages/users.jsp     |    2 +-
 .../js/jquery/jquery.event.drag-2.0.min.js      |  194 -
 .../js/jquery/jquery.event.drag-2.2.min.js      |    6 +
 .../webapp/js/jquery/slickgrid/MIT-LICENSE.txt  |   20 +
 .../js/jquery/slickgrid/css/images/collapse.gif |  Bin 0 -> 846 bytes
 .../js/jquery/slickgrid/css/images/expand.gif   |  Bin 0 -> 851 bytes
 .../slickgrid/css/slick-default-theme.css       |   68 +-
 .../js/jquery/slickgrid/css/slick.grid.css      |  173 +-
 .../slickgrid/plugins/slick.autotooltips.js     |  121 +-
 .../plugins/slick.cellrangedecorator.js         |  110 +-
 .../plugins/slick.cellrangeselector.js          |  194 +-
 .../plugins/slick.cellselectionmodel.js         |  210 +-
 .../plugins/slick.rowselectionmodel.js          |  325 +-
 .../webapp/js/jquery/slickgrid/slick.core.js    |  796 +--
 .../js/jquery/slickgrid/slick.dataview.js       | 1920 +++---
 .../webapp/js/jquery/slickgrid/slick.editors.js |  994 +--
 .../js/jquery/slickgrid/slick.formatters.js     |   86 +-
 .../webapp/js/jquery/slickgrid/slick.grid.js    | 6254 ++++++++++--------
 25 files changed, 6144 insertions(+), 5343 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
index c8f2ff7..09c8207 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
@@ -48,7 +48,7 @@
         <script type="text/javascript" src="js/jquery/modal/jquery.modal.js?${project.version}"></script>
         <script type="text/javascript" src="js/jquery/minicolors/jquery.minicolors.min.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
index e3e7b86..a0bda24 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/cluster.jsp
@@ -36,7 +36,7 @@
         <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
index 21ee508..2678bf4 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/counters.jsp
@@ -36,7 +36,7 @@
         <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
index 61be727..19d9e90 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/history.jsp
@@ -36,7 +36,7 @@
         <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
index 2f51918..f3c9a88 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
@@ -38,7 +38,7 @@
         <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
index b34f0e6..e8a8e4c 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
@@ -38,7 +38,7 @@
         <script type="text/javascript" src="js/jquery/jquery.ellipsis.js"></script>
         <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
index c7c0293..889485f 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
@@ -37,7 +37,7 @@
         <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
index 770dad5..9ff887b 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
@@ -38,7 +38,7 @@
         <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
         <script type="text/javascript" src="js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
         <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
-        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.0.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
         <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.0.min.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.0.min.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.0.min.js
deleted file mode 100755
index 146b20a..0000000
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.0.min.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/*! 
- * jquery.event.drag - v 2.0.0 
- * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
- * Open Source MIT License - http://threedubmedia.com/code/license
- */
-;
-(function (f) {
-    f.fn.drag = function (b, a, d) {
-        var e = typeof b == "string" ? b : "", k = f.isFunction(b) ? b : f.isFunction(a) ? a : null;
-        if (e.indexOf("drag") !== 0)
-            e = "drag" + e;
-        d = (b == k ? a : d) || {};
-        return k ? this.bind(e, d, k) : this.trigger(e)
-    };
-    var i = f.event, h = i.special, c = h.drag = {defaults: {which: 1, distance: 0, not: ":input", handle: null, relative: false, drop: true, click: false}, datakey: "dragdata", livekey: "livedrag", add: function (b) {
-            var a = f.data(this, c.datakey), d = b.data || {};
-            a.related += 1;
-            if (!a.live && b.selector) {
-                a.live = true;
-                i.add(this, "draginit." + c.livekey, c.delegate)
-            }
-            f.each(c.defaults, function (e) {
-                if (d[e] !== undefined)
-                    a[e] = d[e]
-            })
-        }, remove: function () {
-            f.data(this, c.datakey).related -= 1
-        }, setup: function () {
-            if (!f.data(this, c.datakey)) {
-                var b = f.extend({related: 0}, c.defaults);
-                f.data(this, c.datakey, b);
-                i.add(this, "mousedown", c.init, b);
-                this.attachEvent && this.attachEvent("ondragstart", c.dontstart)
-            }
-        }, teardown: function () {
-            if (!f.data(this, c.datakey).related) {
-                f.removeData(this, c.datakey);
-                i.remove(this, "mousedown", c.init);
-                i.remove(this, "draginit", c.delegate);
-                c.textselect(true);
-                this.detachEvent && this.detachEvent("ondragstart", c.dontstart)
-            }
-        }, init: function (b) {
-            var a = b.data, d;
-            if (!(a.which > 0 && b.which != a.which))
-                if (!f(b.target).is(a.not))
-                    if (!(a.handle && !f(b.target).closest(a.handle, b.currentTarget).length)) {
-                        a.propagates = 1;
-                        a.interactions = [c.interaction(this, a)];
-                        a.target = b.target;
-                        a.pageX = b.pageX;
-                        a.pageY = b.pageY;
-                        a.dragging = null;
-                        d = c.hijack(b, "draginit", a);
-                        if (a.propagates) {
-                            if ((d = c.flatten(d)) && d.length) {
-                                a.interactions = [];
-                                f.each(d, function () {
-                                    a.interactions.push(c.interaction(this, a))
-                                })
-                            }
-                            a.propagates = a.interactions.length;
-                            a.drop !== false && h.drop && h.drop.handler(b, a);
-                            c.textselect(false);
-                            i.add(document, "mousemove mouseup", c.handler, a);
-                            return false
-                        }
-                    }
-        }, interaction: function (b, a) {
-            return{drag: b, callback: new c.callback, droppable: [], offset: f(b)[a.relative ? "position" : "offset"]() || {top: 0, left: 0}}
-        }, handler: function (b) {
-            var a = b.data;
-            switch (b.type) {
-                case !a.dragging && "mousemove":
-                    if (Math.pow(b.pageX - a.pageX, 2) + Math.pow(b.pageY - a.pageY, 2) < Math.pow(a.distance, 2))
-                        break;
-                    b.target = a.target;
-                    c.hijack(b, "dragstart", a);
-                    if (a.propagates)
-                        a.dragging = true;
-                case "mousemove":
-                    if (a.dragging) {
-                        c.hijack(b, "drag", a);
-                        if (a.propagates) {
-                            a.drop !== false && h.drop && h.drop.handler(b, a);
-                            break
-                        }
-                        b.type = "mouseup"
-                    }
-                case "mouseup":
-                    i.remove(document, "mousemove mouseup", c.handler);
-                    if (a.dragging) {
-                        a.drop !== false && h.drop && h.drop.handler(b, a);
-                        c.hijack(b, "dragend", a)
-                    }
-                    c.textselect(true);
-                    if (a.click === false && a.dragging) {
-                        jQuery.event.triggered = true;
-                        setTimeout(function () {
-                            jQuery.event.triggered = false
-                        }, 20);
-                        a.dragging = false
-                    }
-                    break
-            }
-        }, delegate: function (b) {
-            var a = [], d, e = f.data(this, "events") || {};
-            f.each(e.live || [], function (k, j) {
-                if (j.preType.indexOf("drag") === 0)
-                    if (d = f(b.target).closest(j.selector, b.currentTarget)[0]) {
-                        i.add(d, j.origType + "." + c.livekey, j.origHandler, j.data);
-                        f.inArray(d, a) < 0 && a.push(d)
-                    }
-            });
-            if (!a.length)
-                return false;
-            return f(a).bind("dragend." + c.livekey, function () {
-                i.remove(this, "." + c.livekey)
-            })
-        }, hijack: function (b, a, d, e, k) {
-            if (d) {
-                var j = {event: b.originalEvent, type: b.type}, n = a.indexOf("drop") ? "drag" : "drop", l, o = e || 0, g, m;
-                e = !isNaN(e) ? e : d.interactions.length;
-                b.type = a;
-                b.originalEvent = null;
-                d.results = [];
-                do
-                    if (g = d.interactions[o])
-                        if (!(a !== "dragend" && g.cancelled)) {
-                            m = c.properties(b, d, g);
-                            g.results = [];
-                            f(k || g[n] || d.droppable).each(function (q, p) {
-                                l = (m.target = p) ? i.handle.call(p, b, m) : null;
-                                if (l === false) {
-                                    if (n == "drag") {
-                                        g.cancelled = true;
-                                        d.propagates -= 1
-                                    }
-                                    if (a == "drop")
-                                        g[n][q] = null
-                                } else if (a == "dropinit")
-                                    g.droppable.push(c.element(l) || p);
-                                if (a == "dragstart")
-                                    g.proxy = f(c.element(l) || g.drag)[0];
-                                g.results.push(l);
-                                delete b.result;
-                                if (a !== "dropinit")
-                                    return l
-                            });
-                            d.results[o] = c.flatten(g.results);
-                            if (a == "dropinit")
-                                g.droppable = c.flatten(g.droppable);
-                            a == "dragstart" && !g.cancelled && m.update()
-                        }
-                while (++o < e);
-                b.type = j.type;
-                b.originalEvent = j.event;
-                return c.flatten(d.results)
-            }
-        }, properties: function (b, a, d) {
-            var e = d.callback;
-            e.drag = d.drag;
-            e.proxy = d.proxy || d.drag;
-            e.startX = a.pageX;
-            e.startY = a.pageY;
-            e.deltaX = b.pageX - a.pageX;
-            e.deltaY = b.pageY - a.pageY;
-            e.originalX = d.offset.left;
-            e.originalY = d.offset.top;
-            e.offsetX = b.pageX - (a.pageX - e.originalX);
-            e.offsetY = b.pageY - (a.pageY - e.originalY);
-            e.drop = c.flatten((d.drop || []).slice());
-            e.available = c.flatten((d.droppable || []).slice());
-            return e
-        }, element: function (b) {
-            if (b && (b.jquery || b.nodeType == 1))
-                return b
-        }, flatten: function (b) {
-            return f.map(b, function (a) {
-                return a && a.jquery ? f.makeArray(a) : a && a.length ? c.flatten(a) : a
-            })
-        }, textselect: function (b) {
-            f(document)[b ? "unbind" : "bind"]("selectstart", c.dontstart).attr("unselectable", b ? "off" : "on").css("MozUserSelect", b ? "" : "none")
-        }, dontstart: function () {
-            return false
-        }, callback: function () {
-        }};
-    c.callback.prototype = {update: function () {
-            h.drop && this.available.length && f.each(this.available, function (b) {
-                h.drop.locate(this, b)
-            })
-        }};
-    h.draginit = h.dragstart = h.dragend = c
-})(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.2.min.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.2.min.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.2.min.js
new file mode 100644
index 0000000..cff8ed6
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/jquery.event.drag-2.2.min.js
@@ -0,0 +1,6 @@
+/*!
+ * jquery.event.drag - v 2.2
+ * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
+ * Open Source MIT License - http://threedubmedia.com/code/license
+ */
+;(function(e){e.fn.drag=function(k,g,j){var i=typeof k=="string"?k:"",h=e.isFunction(k)?k:e.isFunction(g)?g:null;if(i.indexOf("drag")!==0){i="drag"+i}j=(k==h?g:j)||{};return h?this.bind(i,j,h):this.trigger(i)};var b=e.event,a=b.special,d=a.drag={defaults:{which:1,distance:0,not:":input",handle:null,relative:false,drop:true,click:false},datakey:"dragdata",noBubble:true,add:function(i){var h=e.data(this,d.datakey),g=i.data||{};h.related+=1;e.each(d.defaults,function(j,k){if(g[j]!==undefined){h[j]=g[j]}})},remove:function(){e.data(this,d.datakey).related-=1},setup:function(){if(e.data(this,d.datakey)){return}var g=e.extend({related:0},d.defaults);e.data(this,d.datakey,g);b.add(this,"touchstart mousedown",d.init,g);if(this.attachEvent){this.attachEvent("ondragstart",d.dontstart)}},teardown:function(){var g=e.data(this,d.datakey)||{};if(g.related){return}e.removeData(this,d.datakey);b.remove(this,"touchstart mousedown",d.init);d.textselect(true);if(this.detachEvent){this.detachEvent("ond
 ragstart",d.dontstart)}},init:function(i){if(d.touched){return}var g=i.data,h;if(i.which!=0&&g.which>0&&i.which!=g.which){return}if(e(i.target).is(g.not)){return}if(g.handle&&!e(i.target).closest(g.handle,i.currentTarget).length){return}d.touched=i.type=="touchstart"?this:null;g.propagates=1;g.mousedown=this;g.interactions=[d.interaction(this,g)];g.target=i.target;g.pageX=i.pageX;g.pageY=i.pageY;g.dragging=null;h=d.hijack(i,"draginit",g);if(!g.propagates){return}h=d.flatten(h);if(h&&h.length){g.interactions=[];e.each(h,function(){g.interactions.push(d.interaction(this,g))})}g.propagates=g.interactions.length;if(g.drop!==false&&a.drop){a.drop.handler(i,g)}d.textselect(false);if(d.touched){b.add(d.touched,"touchmove touchend",d.handler,g)}else{b.add(document,"mousemove mouseup",d.handler,g)}if(!d.touched||g.live){return false}},interaction:function(h,g){var i=e(h)[g.relative?"position":"offset"]()||{top:0,left:0};return{drag:h,callback:new d.callback(),droppable:[],offset:i}},handler:
 function(h){var g=h.data;switch(h.type){case !g.dragging&&"touchmove":h.preventDefault();case !g.dragging&&"mousemove":if(Math.pow(h.pageX-g.pageX,2)+Math.pow(h.pageY-g.pageY,2)<Math.pow(g.distance,2)){break}h.target=g.target;d.hijack(h,"dragstart",g);if(g.propagates){g.dragging=true}case"touchmove":h.preventDefault();case"mousemove":if(g.dragging){d.hijack(h,"drag",g);if(g.propagates){if(g.drop!==false&&a.drop){a.drop.handler(h,g)}break}h.type="mouseup"}case"touchend":case"mouseup":default:if(d.touched){b.remove(d.touched,"touchmove touchend",d.handler)}else{b.remove(document,"mousemove mouseup",d.handler)}if(g.dragging){if(g.drop!==false&&a.drop){a.drop.handler(h,g)}d.hijack(h,"dragend",g)}d.textselect(true);if(g.click===false&&g.dragging){e.data(g.mousedown,"suppress.click",new Date().getTime()+5)}g.dragging=d.touched=false;break}},hijack:function(h,o,r,p,k){if(!r){return}var q={event:h.originalEvent,type:h.type},m=o.indexOf("drop")?"drag":"drop",t,l=p||0,j,g,s,n=!isNaN(p)?p:r.in
 teractions.length;h.type=o;h.originalEvent=null;r.results=[];do{if(j=r.interactions[l]){if(o!=="dragend"&&j.cancelled){continue}s=d.properties(h,r,j);j.results=[];e(k||j[m]||r.droppable).each(function(u,i){s.target=i;h.isPropagationStopped=function(){return false};t=i?b.dispatch.call(i,h,s):null;if(t===false){if(m=="drag"){j.cancelled=true;r.propagates-=1}if(o=="drop"){j[m][u]=null}}else{if(o=="dropinit"){j.droppable.push(d.element(t)||i)}}if(o=="dragstart"){j.proxy=e(d.element(t)||j.drag)[0]}j.results.push(t);delete h.result;if(o!=="dropinit"){return t}});r.results[l]=d.flatten(j.results);if(o=="dropinit"){j.droppable=d.flatten(j.droppable)}if(o=="dragstart"&&!j.cancelled){s.update()}}}while(++l<n);h.type=q.type;h.originalEvent=q.event;return d.flatten(r.results)},properties:function(i,g,h){var j=h.callback;j.drag=h.drag;j.proxy=h.proxy||h.drag;j.startX=g.pageX;j.startY=g.pageY;j.deltaX=i.pageX-g.pageX;j.deltaY=i.pageY-g.pageY;j.originalX=h.offset.left;j.originalY=h.offset.top;j.of
 fsetX=j.originalX+j.deltaX;j.offsetY=j.originalY+j.deltaY;j.drop=d.flatten((h.drop||[]).slice());j.available=d.flatten((h.droppable||[]).slice());return j},element:function(g){if(g&&(g.jquery||g.nodeType==1)){return g}},flatten:function(g){return e.map(g,function(h){return h&&h.jquery?e.makeArray(h):h&&h.length?d.flatten(h):h})},textselect:function(g){e(document)[g?"unbind":"bind"]("selectstart",d.dontstart).css("MozUserSelect",g?"":"none");document.unselectable=g?"off":"on"},dontstart:function(){return false},callback:function(){}};d.callback.prototype={update:function(){if(a.drop&&this.available.length){e.each(this.available,function(g){a.drop.locate(this,g)})}}};var f=b.dispatch;b.dispatch=function(g){if(e.data(this,"suppress."+g.type)-new Date().getTime()>0){e.removeData(this,"suppress."+g.type);return}return f.apply(this,arguments)};var c=b.fixHooks.touchstart=b.fixHooks.touchmove=b.fixHooks.touchend=b.fixHooks.touchcancel={props:"clientX clientY pageX pageY screenX screenY".sp
 lit(" "),filter:function(h,i){if(i){var g=(i.touches&&i.touches[0])||(i.changedTouches&&i.changedTouches[0])||null;if(g){e.each(c.props,function(j,k){h[k]=g[k]})}}return h}};a.draginit=a.dragstart=a.dragend=d})(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/MIT-LICENSE.txt
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/MIT-LICENSE.txt b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/MIT-LICENSE.txt
new file mode 100755
index 0000000..60f6542
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/MIT-LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2010 Michael Leibman, http://github.com/mleibman/slickgrid
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/collapse.gif
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/collapse.gif b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/collapse.gif
new file mode 100755
index 0000000..01e6914
Binary files /dev/null and b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/collapse.gif differ

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/expand.gif
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/expand.gif b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/expand.gif
new file mode 100755
index 0000000..1b24ef1
Binary files /dev/null and b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/images/expand.gif differ

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css
index c68b703..6b45f3e 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css
@@ -31,24 +31,24 @@ classes should alter those!
 }
 
 .slick-headerrow {
-    background: #fafafa;
+  background: #fafafa;
 }
 
 .slick-headerrow-column {
-    background: #fafafa;
-    border-bottom: 0;
-    height: 100%;
+  background: #fafafa;
+  border-bottom: 0;
+  height: 100%;
 }
 
 .slick-row.ui-state-active {
-    background: #F5F7D7;
+  background: #F5F7D7;
 }
 
 .slick-row {
-    position: absolute;
-    background: white;
-    border: 0px;
-    line-height: 20px;
+  position: absolute;
+  background: white;
+  border: 0px;
+  line-height: 20px;
 }
 
 .slick-row:hover {
@@ -56,37 +56,37 @@ classes should alter those!
 }
 
 .slick-row.selected {
-    z-index: 10;
+  z-index: 10;
     background: #DFE8F6 !important;
 }
 
 .slick-cell {
-    padding-left: 4px;
-    padding-right: 4px;
+  padding-left: 4px;
+  padding-right: 4px;
     border-style: solid !important;
 }
 
 .slick-group {
-    border-bottom: 2px solid silver;
+  border-bottom: 2px solid silver;
 }
 
 .slick-group-toggle {
-    width: 9px;
-    height: 9px;
-    margin-right: 5px;
+  width: 9px;
+  height: 9px;
+  margin-right: 5px;
 }
 
 .slick-group-toggle.expanded {
-    background: url(../../../../images/collapse.gif) no-repeat center center;
+  background: url(images/collapse.gif) no-repeat center center;
 }
 
 .slick-group-toggle.collapsed {
-    background: url(../../../../images/expand.gif) no-repeat center center;
+  background: url(images/expand.gif) no-repeat center center;
 }
 
 .slick-group-totals {
-    color: gray;
-    background: white;
+  color: gray;
+  background: white;
 }
 
 .slick-cell.selected {
@@ -100,22 +100,36 @@ classes should alter those!
 }
 
 .slick-sortable-placeholder {
-    background: silver !important;
+  background: silver !important;
 }
 
-.slick-row[row$="1"], .slick-row[row$="3"], .slick-row[row$="5"], .slick-row[row$="7"], .slick-row[row$="9"] {
-    background: #fafafa;
+.slick-row.odd {
+  background: #fafafa;
 }
 
 .slick-row.ui-state-active {
-    background: #F5F7D7;
+  background: #F5F7D7;
 }
 
 .slick-row.loading {
-    opacity: 0.5;
-    filter: alpha(opacity = 50);
+  opacity: 0.5;
+  filter: alpha(opacity = 50);
 }
 
 .slick-cell.invalid {
-    border-color: red;
+  border-color: red;
+  -moz-animation-duration: 0.2s;
+  -webkit-animation-duration: 0.2s;
+  -moz-animation-name: slickgrid-invalid-hilite;
+  -webkit-animation-name: slickgrid-invalid-hilite;  
+}
+
+@-moz-keyframes slickgrid-invalid-hilite {
+  from { box-shadow: 0 0 6px red; }
+  to { box-shadow: none; }
+}
+
+@-webkit-keyframes slickgrid-invalid-hilite {
+  from { box-shadow: 0 0 6px red; }
+  to { box-shadow: none; }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick.grid.css
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick.grid.css b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick.grid.css
index 2e8f390..de94dbf 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick.grid.css
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick.grid.css
@@ -6,153 +6,152 @@ classes should alter those!
 */
 
 .slick-header.ui-state-default, .slick-headerrow.ui-state-default {
-    width: 100%;
-    overflow: hidden;
-    border-left: 0px;
+  width: 100%;
+  overflow: hidden;
+  border-left: 0px;
 }
 
 .slick-header-columns, .slick-headerrow-columns {
-    width: 999999px;
-    position: relative;
-    white-space: nowrap;
-    cursor: default;
-    overflow: hidden;
+  position: relative;
+  white-space: nowrap;
+  cursor: default;
+  overflow: hidden;
 }
 
 .slick-header-column.ui-state-default {
-    position: relative;
-    display: inline-block;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    height: 16px;
-    line-height: 16px;
-    margin: 0;
-    padding: 4px;
-    border-right: 1px solid silver;
-    border-left: 0px;
-    border-top: 0px;
-    border-bottom: 0px;
-    float: left;
+  position: relative;
+  display: inline-block;
+  overflow: hidden;
+  -o-text-overflow: ellipsis;
+  text-overflow: ellipsis;
+  height: 16px;
+  line-height: 16px;
+  margin: 0;
+  padding: 4px;
+  border-right: 1px solid silver;
+  border-left: 0px;
+  border-top: 0px;
+  border-bottom: 0px;
+  float: left;
 }
 
 .slick-headerrow-column.ui-state-default {
-    padding: 4px;
+  padding: 4px;
 }
 
 .slick-header-column-sorted {
-    font-style: italic;
+  font-style: italic;
 }
 
 .slick-sort-indicator {
-    display: inline-block;
-    width: 8px;
-    height: 5px;
-    margin-left: 4px;
+  display: inline-block;
+  width: 8px;
+  height: 5px;
+  margin-left: 4px;
+  margin-top: 6px;
+  /*float: left;*/
 }
 
 .slick-sort-indicator-desc {
-    background: url(images/sort-desc.gif);
+  background: url(images/sort-desc.gif);
 }
 
 .slick-sort-indicator-asc {
-    background: url(images/sort-asc.gif);
+  background: url(images/sort-asc.gif);
 }
 
 .slick-resizable-handle {
-    position: absolute;
-    font-size: 0.1px;
-    display: block;
-    cursor: col-resize;
-    width: 4px;
-    right: 0px;
-    top: 0;
-    height: 100%;
+  position: absolute;
+  font-size: 0.1px;
+  display: block;
+  cursor: col-resize;
+  width: 4px;
+  right: 0px;
+  top: 0;
+  height: 100%;
 }
 
 .slick-sortable-placeholder {
-    background: silver;
+  background: silver;
 }
 
 .grid-canvas {
-    position: relative;
-    outline: 0;
+  position: relative;
+  outline: 0;
 }
 
 .slick-row.ui-widget-content, .slick-row.ui-state-active {
-    position: absolute;
-    border: 0px;
-    width: 100%;
+  position: absolute;
+  border: 0px;
+  width: 100%;
 }
 
 .slick-cell, .slick-headerrow-column {
-    position: absolute;
-
-    border: 1px solid transparent;
-    border-right: 1px dotted silver;
-    border-bottom-color: silver;
-
-    overflow: hidden;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-    vertical-align: middle;
-    z-index: 1;
-    padding: 1px 2px 2px 1px;
-    margin: 0;
-
-    white-space: nowrap;
-
-    cursor: default;
+  position: absolute;
+  border: 1px solid transparent;
+  border-right: 1px dotted silver;
+  border-bottom-color: silver;
+  overflow: hidden;
+  -o-text-overflow: ellipsis;
+  text-overflow: ellipsis;
+  vertical-align: middle;
+  z-index: 1;
+  padding: 1px 2px 2px 1px;
+  margin: 0;
+  white-space: nowrap;
+  cursor: default;
 }
 
 .slick-group {
 }
 
 .slick-group-toggle {
-    display: inline-block;
+  display: inline-block;
 }
 
 .slick-cell.highlighted {
-    background: lightskyblue;
-    background: rgba(0, 0, 255, 0.2);
-    -webkit-transition: all 0.5s;
-    -moz-transition: all 0.5s;
-    transition: all 0.5s;
+  background: lightskyblue;
+  background: rgba(0, 0, 255, 0.2);
+  -webkit-transition: all 0.5s;
+  -moz-transition: all 0.5s;
+  -o-transition: all 0.5s;
+  transition: all 0.5s;
 }
 
 .slick-cell.flashing {
-    border: 1px solid red !important;
+  border: 1px solid red !important;
 }
 
 .slick-cell.editable {
-    z-index: 11;
-    overflow: visible;
-    background: white;
-    border-color: black;
-    border-style: solid;
+  z-index: 11;
+  overflow: visible;
+  background: white;
+  border-color: black;
+  border-style: solid;
 }
 
 .slick-cell:focus {
-    outline: none;
+  outline: none;
 }
 
 .slick-reorder-proxy {
-    display: inline-block;
-    background: blue;
-    opacity: 0.15;
-    filter: alpha(opacity = 15);
-    cursor: move;
+  display: inline-block;
+  background: blue;
+  opacity: 0.15;
+  filter: alpha(opacity = 15);
+  cursor: move;
 }
 
 .slick-reorder-guide {
-    display: inline-block;
-    height: 2px;
-    background: blue;
-    opacity: 0.7;
-    filter: alpha(opacity = 70);
+  display: inline-block;
+  height: 2px;
+  background: blue;
+  opacity: 0.7;
+  filter: alpha(opacity = 70);
 }
 
 .slick-selection {
-    z-index: 10;
-    position: absolute;
-    border: 2px dashed black;
-}
\ No newline at end of file
+  z-index: 10;
+  position: absolute;
+  border: 2px dashed black;
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.autotooltips.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.autotooltips.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.autotooltips.js
index bce0bea..955684f 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.autotooltips.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.autotooltips.js
@@ -1,48 +1,83 @@
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "AutoTooltips": AutoTooltips
-        }
-    });
-
-
-    function AutoTooltips(options) {
-        var _grid;
-        var _self = this;
-        var _defaults = {
-            maxToolTipLength: null
-        };
-
-        function init(grid) {
-            options = $.extend(true, {}, _defaults, options);
-            _grid = grid;
-            _grid.onMouseEnter.subscribe(handleMouseEnter);
-        }
-
-        function destroy() {
-            _grid.onMouseEnter.unsubscribe(handleMouseEnter);
-        }
+  // Register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "AutoTooltips": AutoTooltips
+    }
+  });
 
-        function handleMouseEnter(e, args) {
-            var cell = _grid.getCellFromEvent(e);
-            if (cell) {
-                var node = _grid.getCellNode(cell.row, cell.cell);
-                if ($(node).innerWidth() < node.scrollWidth) {
-                    var text = $.trim($(node).text());
-                    if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
-                        text = text.substr(0, options.maxToolTipLength - 3) + "...";
-                    }
-                    $(node).attr("title", text);
-                } else {
-                    $(node).attr("title", "");
-                }
-            }
+  /**
+   * AutoTooltips plugin to show/hide tooltips when columns are too narrow to fit content.
+   * @constructor
+   * @param {boolean} [options.enableForCells=true]        - Enable tooltip for grid cells
+   * @param {boolean} [options.enableForHeaderCells=false] - Enable tooltip for header cells
+   * @param {number}  [options.maxToolTipLength=null]      - The maximum length for a tooltip
+   */
+  function AutoTooltips(options) {
+    var _grid;
+    var _self = this;
+    var _defaults = {
+      enableForCells: true,
+      enableForHeaderCells: false,
+      maxToolTipLength: null
+    };
+    
+    /**
+     * Initialize plugin.
+     */
+    function init(grid) {
+      options = $.extend(true, {}, _defaults, options);
+      _grid = grid;
+      if (options.enableForCells) _grid.onMouseEnter.subscribe(handleMouseEnter);
+      if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.subscribe(handleHeaderMouseEnter);
+    }
+    
+    /**
+     * Destroy plugin.
+     */
+    function destroy() {
+      if (options.enableForCells) _grid.onMouseEnter.unsubscribe(handleMouseEnter);
+      if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.unsubscribe(handleHeaderMouseEnter);
+    }
+    
+    /**
+     * Handle mouse entering grid cell to add/remove tooltip.
+     * @param {jQuery.Event} e - The event
+     */
+    function handleMouseEnter(e) {
+      var cell = _grid.getCellFromEvent(e);
+      if (cell) {
+        var $node = $(_grid.getCellNode(cell.row, cell.cell));
+        var text;
+        if ($node.innerWidth() < $node[0].scrollWidth) {
+          text = $.trim($node.text());
+          if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
+            text = text.substr(0, options.maxToolTipLength - 3) + "...";
+          }
+        } else {
+          text = "";
         }
-
-        $.extend(this, {
-            "init": init,
-            "destroy": destroy
-        });
+        $node.attr("title", text);
+      }
+    }
+    
+    /**
+     * Handle mouse entering header cell to add/remove tooltip.
+     * @param {jQuery.Event} e     - The event
+     * @param {object} args.column - The column definition
+     */
+    function handleHeaderMouseEnter(e, args) {
+      var column = args.column,
+          $node = $(e.target).closest(".slick-header-column");
+      if (!column.toolTip) {
+        $node.attr("title", ($node.innerWidth() < $node[0].scrollWidth) ? column.name : "");
+      }
     }
+    
+    // Public API
+    $.extend(this, {
+      "init": init,
+      "destroy": destroy
+    });
+  }
 })(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangedecorator.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangedecorator.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangedecorator.js
index eb2d506..0cbe71d 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangedecorator.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangedecorator.js
@@ -1,64 +1,66 @@
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "CellRangeDecorator": CellRangeDecorator
-        }
-    });
-
-    /***
-     * Displays an overlay on top of a given cell range.
-     *
-     * TODO:
-     * Currently, it blocks mouse events to DOM nodes behind it.
-     * Use FF and WebKit-specific "pointer-events" CSS style, or some kind of event forwarding.
-     * Could also construct the borders separately using 4 individual DIVs.
-     *
-     * @param {Grid} grid
-     * @param {Object} options
-     */
-    function CellRangeDecorator(grid, options) {
-        var _elem;
-        var _defaults = {
-            selectionCss: {
-                "zIndex": "9999",
-                "border": "2px dashed red"
-            }
-        };
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "CellRangeDecorator": CellRangeDecorator
+    }
+  });
 
-        options = $.extend(true, {}, _defaults, options);
+  /***
+   * Displays an overlay on top of a given cell range.
+   *
+   * TODO:
+   * Currently, it blocks mouse events to DOM nodes behind it.
+   * Use FF and WebKit-specific "pointer-events" CSS style, or some kind of event forwarding.
+   * Could also construct the borders separately using 4 individual DIVs.
+   *
+   * @param {Grid} grid
+   * @param {Object} options
+   */
+  function CellRangeDecorator(grid, options) {
+    var _elem;
+    var _defaults = {
+      selectionCssClass: 'slick-range-decorator',
+      selectionCss: {
+        "zIndex": "9999",
+        "border": "2px dashed red"
+      }
+    };
 
+    options = $.extend(true, {}, _defaults, options);
 
-        function show(range) {
-            if (!_elem) {
-                _elem = $("<div></div>", {css: options.selectionCss})
-                        .css("position", "absolute")
-                        .appendTo(grid.getCanvasNode());
-            }
 
-            var from = grid.getCellNodeBox(range.fromRow, range.fromCell);
-            var to = grid.getCellNodeBox(range.toRow, range.toCell);
+    function show(range) {
+      if (!_elem) {
+        _elem = $("<div></div>", {css: options.selectionCss})
+            .addClass(options.selectionCssClass)
+            .css("position", "absolute")
+            .appendTo(grid.getCanvasNode());
+      }
 
-            _elem.css({
-                top: from.top - 1,
-                left: from.left - 1,
-                height: to.bottom - from.top - 2,
-                width: to.right - from.left - 2
-            });
+      var from = grid.getCellNodeBox(range.fromRow, range.fromCell);
+      var to = grid.getCellNodeBox(range.toRow, range.toCell);
 
-            return _elem;
-        }
+      _elem.css({
+        top: from.top - 1,
+        left: from.left - 1,
+        height: to.bottom - from.top - 2,
+        width: to.right - from.left - 2
+      });
 
-        function hide() {
-            if (_elem) {
-                _elem.remove();
-                _elem = null;
-            }
-        }
+      return _elem;
+    }
 
-        $.extend(this, {
-            "show": show,
-            "hide": hide
-        });
+    function hide() {
+      if (_elem) {
+        _elem.remove();
+        _elem = null;
+      }
     }
-})(jQuery);
\ No newline at end of file
+
+    $.extend(this, {
+      "show": show,
+      "hide": hide
+    });
+  }
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangeselector.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangeselector.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangeselector.js
index 04d2f90..520b17f 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangeselector.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellrangeselector.js
@@ -1,111 +1,113 @@
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "CellRangeSelector": CellRangeSelector
-        }
-    });
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "CellRangeSelector": CellRangeSelector
+    }
+  });
+
+
+  function CellRangeSelector(options) {
+    var _grid;
+    var _canvas;
+    var _dragging;
+    var _decorator;
+    var _self = this;
+    var _handler = new Slick.EventHandler();
+    var _defaults = {
+      selectionCss: {
+        "border": "2px dashed blue"
+      }
+    };
+
+
+    function init(grid) {
+      options = $.extend(true, {}, _defaults, options);
+      _decorator = new Slick.CellRangeDecorator(grid, options);
+      _grid = grid;
+      _canvas = _grid.getCanvasNode();
+      _handler
+        .subscribe(_grid.onDragInit, handleDragInit)
+        .subscribe(_grid.onDragStart, handleDragStart)
+        .subscribe(_grid.onDrag, handleDrag)
+        .subscribe(_grid.onDragEnd, handleDragEnd);
+    }
 
+    function destroy() {
+      _handler.unsubscribeAll();
+    }
 
-    function CellRangeSelector(options) {
-        var _grid;
-        var _canvas;
-        var _dragging;
-        var _decorator;
-        var _self = this;
-        var _defaults = {
-            selectionCss: {
-                "border": "2px dashed blue"
-            }
-        };
-
-
-        function init(grid) {
-            options = $.extend(true, {}, _defaults, options);
-            _decorator = new Slick.CellRangeDecorator(grid, options);
-            _grid = grid;
-            _canvas = _grid.getCanvasNode();
-            _grid.onDragInit.subscribe(handleDragInit);
-            _grid.onDragStart.subscribe(handleDragStart);
-            _grid.onDrag.subscribe(handleDrag);
-            _grid.onDragEnd.subscribe(handleDragEnd);
-        }
+    function handleDragInit(e, dd) {
+      // prevent the grid from cancelling drag'n'drop by default
+      e.stopImmediatePropagation();
+    }
 
-        function destroy() {
-            _grid.onDragInit.unsubscribe(handleDragInit);
-            _grid.onDragStart.unsubscribe(handleDragStart);
-            _grid.onDrag.unsubscribe(handleDrag);
-            _grid.onDragEnd.unsubscribe(handleDragEnd);
+    function handleDragStart(e, dd) {
+      var cell = _grid.getCellFromEvent(e);
+      if (_self.onBeforeCellRangeSelected.notify(cell) !== false) {
+        if (_grid.canCellBeSelected(cell.row, cell.cell)) {
+          _dragging = true;
+          e.stopImmediatePropagation();
         }
+      }
+      if (!_dragging) {
+        return;
+      }
 
-        function handleDragInit(e, dd) {
-            // prevent the grid from cancelling drag'n'drop by default
-            e.stopImmediatePropagation();
-        }
+      _grid.focus();
 
-        function handleDragStart(e, dd) {
-            var cell = _grid.getCellFromEvent(e);
-            if (_self.onBeforeCellRangeSelected.notify(cell) !== false) {
-                if (_grid.canCellBeSelected(cell.row, cell.cell)) {
-                    _dragging = true;
-                    e.stopImmediatePropagation();
-                }
-            }
-            if (!_dragging) {
-                return;
-            }
-
-            var start = _grid.getCellFromPoint(
-                    dd.startX - $(_canvas).offset().left,
-                    dd.startY - $(_canvas).offset().top);
-
-            dd.range = {start: start, end: {}};
-
-            return _decorator.show(new Slick.Range(start.row, start.cell));
-        }
+      var start = _grid.getCellFromPoint(
+          dd.startX - $(_canvas).offset().left,
+          dd.startY - $(_canvas).offset().top);
 
-        function handleDrag(e, dd) {
-            if (!_dragging) {
-                return;
-            }
-            e.stopImmediatePropagation();
+      dd.range = {start: start, end: {}};
 
-            var end = _grid.getCellFromPoint(
-                    e.pageX - $(_canvas).offset().left,
-                    e.pageY - $(_canvas).offset().top);
+      return _decorator.show(new Slick.Range(start.row, start.cell));
+    }
 
-            if (!_grid.canCellBeSelected(end.row, end.cell)) {
-                return;
-            }
+    function handleDrag(e, dd) {
+      if (!_dragging) {
+        return;
+      }
+      e.stopImmediatePropagation();
 
-            dd.range.end = end;
-            _decorator.show(new Slick.Range(dd.range.start.row, dd.range.start.cell, end.row, end.cell));
-        }
+      var end = _grid.getCellFromPoint(
+          e.pageX - $(_canvas).offset().left,
+          e.pageY - $(_canvas).offset().top);
 
-        function handleDragEnd(e, dd) {
-            if (!_dragging) {
-                return;
-            }
-
-            _dragging = false;
-            e.stopImmediatePropagation();
-
-            _decorator.hide();
-            _self.onCellRangeSelected.notify({
-                range: new Slick.Range(
-                        dd.range.start.row,
-                        dd.range.start.cell,
-                        dd.range.end.row,
-                        dd.range.end.cell
-                        )
-            });
-        }
+      if (!_grid.canCellBeSelected(end.row, end.cell)) {
+        return;
+      }
+
+      dd.range.end = end;
+      _decorator.show(new Slick.Range(dd.range.start.row, dd.range.start.cell, end.row, end.cell));
+    }
 
-        $.extend(this, {
-            "init": init,
-            "destroy": destroy,
-            "onBeforeCellRangeSelected": new Slick.Event(),
-            "onCellRangeSelected": new Slick.Event()
-        });
+    function handleDragEnd(e, dd) {
+      if (!_dragging) {
+        return;
+      }
+
+      _dragging = false;
+      e.stopImmediatePropagation();
+
+      _decorator.hide();
+      _self.onCellRangeSelected.notify({
+        range: new Slick.Range(
+            dd.range.start.row,
+            dd.range.start.cell,
+            dd.range.end.row,
+            dd.range.end.cell
+        )
+      });
     }
+
+    $.extend(this, {
+      "init": init,
+      "destroy": destroy,
+
+      "onBeforeCellRangeSelected": new Slick.Event(),
+      "onCellRangeSelected": new Slick.Event()
+    });
+  }
 })(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellselectionmodel.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellselectionmodel.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellselectionmodel.js
index 9f0730a..74bc3eb 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellselectionmodel.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.cellselectionmodel.js
@@ -1,90 +1,154 @@
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "CellSelectionModel": CellSelectionModel
-        }
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "CellSelectionModel": CellSelectionModel
+    }
+  });
+
+
+  function CellSelectionModel(options) {
+    var _grid;
+    var _canvas;
+    var _ranges = [];
+    var _self = this;
+    var _selector = new Slick.CellRangeSelector({
+      "selectionCss": {
+        "border": "2px solid black"
+      }
     });
+    var _options;
+    var _defaults = {
+      selectActiveCell: true
+    };
 
 
-    function CellSelectionModel(options) {
-        var _grid;
-        var _canvas;
-        var _ranges = [];
-        var _self = this;
-        var _selector = new Slick.CellRangeSelector({
-            "selectionCss": {
-                "border": "2px solid black"
-            }
-        });
-        var _options;
-        var _defaults = {
-            selectActiveCell: true
-        };
-
-
-        function init(grid) {
-            _options = $.extend(true, {}, _defaults, options);
-            _grid = grid;
-            _canvas = _grid.getCanvasNode();
-            _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
-            grid.registerPlugin(_selector);
-            _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
-            _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
-        }
+    function init(grid) {
+      _options = $.extend(true, {}, _defaults, options);
+      _grid = grid;
+      _canvas = _grid.getCanvasNode();
+      _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
+      _grid.onKeyDown.subscribe(handleKeyDown);
+      grid.registerPlugin(_selector);
+      _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
+      _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
+    }
 
-        function destroy() {
-            _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
-            _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
-            _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
-            _grid.unregisterPlugin(_selector);
+    function destroy() {
+      _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
+      _grid.onKeyDown.unsubscribe(handleKeyDown);
+      _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
+      _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
+      _grid.unregisterPlugin(_selector);
+    }
+
+    function removeInvalidRanges(ranges) {
+      var result = [];
+
+      for (var i = 0; i < ranges.length; i++) {
+        var r = ranges[i];
+        if (_grid.canCellBeSelected(r.fromRow, r.fromCell) && _grid.canCellBeSelected(r.toRow, r.toCell)) {
+          result.push(r);
         }
+      }
 
-        function removeInvalidRanges(ranges) {
-            var result = [];
+      return result;
+    }
 
-            for (var i = 0; i < ranges.length; i++) {
-                var r = ranges[i];
-                if (_grid.canCellBeSelected(r.fromRow, r.fromCell) && _grid.canCellBeSelected(r.toRow, r.toCell)) {
-                    result.push(r);
-                }
-            }
+    function setSelectedRanges(ranges) {
+      _ranges = removeInvalidRanges(ranges);
+      _self.onSelectedRangesChanged.notify(_ranges);
+    }
 
-            return result;
-        }
+    function getSelectedRanges() {
+      return _ranges;
+    }
 
-        function setSelectedRanges(ranges) {
-            _ranges = removeInvalidRanges(ranges);
-            _self.onSelectedRangesChanged.notify(_ranges);
-        }
+    function handleBeforeCellRangeSelected(e, args) {
+      if (_grid.getEditorLock().isActive()) {
+        e.stopPropagation();
+        return false;
+      }
+    }
 
-        function getSelectedRanges() {
-            return _ranges;
-        }
+    function handleCellRangeSelected(e, args) {
+      setSelectedRanges([args.range]);
+    }
 
-        function handleBeforeCellRangeSelected(e, args) {
-            if (_grid.getEditorLock().isActive()) {
-                e.stopPropagation();
-                return false;
-            }
-        }
+    function handleActiveCellChange(e, args) {
+      if (_options.selectActiveCell && args.row != null && args.cell != null) {
+        setSelectedRanges([new Slick.Range(args.row, args.cell)]);
+      }
+    }
+    
+    function handleKeyDown(e) {
+      /***
+       * Кey codes
+       * 37 left
+       * 38 up
+       * 39 right
+       * 40 down                     
+       */                                         
+      var ranges, last;
+      var active = _grid.getActiveCell(); 
 
-        function handleCellRangeSelected(e, args) {
-            setSelectedRanges([args.range]);
+      if ( active && e.shiftKey && !e.ctrlKey && !e.altKey && 
+          (e.which == 37 || e.which == 39 || e.which == 38 || e.which == 40) ) {
+      
+        ranges = getSelectedRanges();
+        if (!ranges.length)
+         ranges.push(new Slick.Range(active.row, active.cell));
+         
+        // keyboard can work with last range only          
+        last = ranges.pop();
+        
+        // can't handle selection out of active cell
+        if (!last.contains(active.row, active.cell))
+          last = new Slick.Range(active.row, active.cell);
+        
+        var dRow = last.toRow - last.fromRow,
+            dCell = last.toCell - last.fromCell,
+            // walking direction
+            dirRow = active.row == last.fromRow ? 1 : -1,
+            dirCell = active.cell == last.fromCell ? 1 : -1;
+                 
+        if (e.which == 37) {
+          dCell -= dirCell; 
+        } else if (e.which == 39) {
+          dCell += dirCell ; 
+        } else if (e.which == 38) {
+          dRow -= dirRow; 
+        } else if (e.which == 40) {
+          dRow += dirRow; 
         }
-
-        function handleActiveCellChange(e, args) {
-            if (_options.selectActiveCell) {
-                setSelectedRanges([new Slick.Range(args.row, args.cell)]);
-            }
+        
+        // define new selection range 
+        var new_last = new Slick.Range(active.row, active.cell, active.row + dirRow*dRow, active.cell + dirCell*dCell);
+        if (removeInvalidRanges([new_last]).length) {
+          ranges.push(new_last);
+          var viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow;
+          var viewCell = dirCell > 0 ? new_last.toCell : new_last.fromCell;
+         _grid.scrollRowIntoView(viewRow);
+         _grid.scrollCellIntoView(viewRow, viewCell);
         }
+        else 
+          ranges.push(last);
 
-        $.extend(this, {
-            "getSelectedRanges": getSelectedRanges,
-            "setSelectedRanges": setSelectedRanges,
-            "init": init,
-            "destroy": destroy,
-            "onSelectedRangesChanged": new Slick.Event()
-        });
+        setSelectedRanges(ranges);  
+       
+        e.preventDefault();
+        e.stopPropagation();        
+      }           
     }
-})(jQuery);
\ No newline at end of file
+
+    $.extend(this, {
+      "getSelectedRanges": getSelectedRanges,
+      "setSelectedRanges": setSelectedRanges,
+
+      "init": init,
+      "destroy": destroy,
+
+      "onSelectedRangesChanged": new Slick.Event()
+    });
+  }
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53f44060/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.rowselectionmodel.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.rowselectionmodel.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.rowselectionmodel.js
index af966c0..0de8dd3 100755
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.rowselectionmodel.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/plugins/slick.rowselectionmodel.js
@@ -1,184 +1,187 @@
 (function ($) {
-    // register namespace
-    $.extend(true, window, {
-        "Slick": {
-            "RowSelectionModel": RowSelectionModel
-        }
-    });
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "RowSelectionModel": RowSelectionModel
+    }
+  });
+
+  function RowSelectionModel(options) {
+    var _grid;
+    var _ranges = [];
+    var _self = this;
+    var _handler = new Slick.EventHandler();
+    var _inHandler;
+    var _options;
+    var _defaults = {
+      selectActiveRow: true
+    };
+
+    function init(grid) {
+      _options = $.extend(true, {}, _defaults, options);
+      _grid = grid;
+      _handler.subscribe(_grid.onActiveCellChanged,
+          wrapHandler(handleActiveCellChange));
+      _handler.subscribe(_grid.onKeyDown,
+          wrapHandler(handleKeyDown));
+      _handler.subscribe(_grid.onClick,
+          wrapHandler(handleClick));
+    }
 
-    function RowSelectionModel(options) {
-        var _grid;
-        var _ranges = [];
-        var _self = this;
-        var _handler = new Slick.EventHandler();
-        var _inHandler;
-        var _options;
-        var _defaults = {
-            selectActiveRow: true
-        };
-
-        function init(grid) {
-            _options = $.extend(true, {}, _defaults, options);
-            _grid = grid;
-            _handler.subscribe(_grid.onActiveCellChanged,
-                    wrapHandler(handleActiveCellChange));
-            _handler.subscribe(_grid.onKeyDown,
-                    wrapHandler(handleKeyDown));
-            _handler.subscribe(_grid.onClick,
-                    wrapHandler(handleClick));
-        }
+    function destroy() {
+      _handler.unsubscribeAll();
+    }
 
-        function destroy() {
-            _handler.unsubscribeAll();
+    function wrapHandler(handler) {
+      return function () {
+        if (!_inHandler) {
+          _inHandler = true;
+          handler.apply(this, arguments);
+          _inHandler = false;
         }
+      };
+    }
 
-        function wrapHandler(handler) {
-            return function () {
-                if (!_inHandler) {
-                    _inHandler = true;
-                    handler.apply(this, arguments);
-                    _inHandler = false;
-                }
-            };
+    function rangesToRows(ranges) {
+      var rows = [];
+      for (var i = 0; i < ranges.length; i++) {
+        for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
+          rows.push(j);
         }
+      }
+      return rows;
+    }
 
-        function rangesToRows(ranges) {
-            var rows = [];
-            for (var i = 0; i < ranges.length; i++) {
-                for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
-                    rows.push(j);
-                }
-            }
-            return rows;
-        }
+    function rowsToRanges(rows) {
+      var ranges = [];
+      var lastCell = _grid.getColumns().length - 1;
+      for (var i = 0; i < rows.length; i++) {
+        ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
+      }
+      return ranges;
+    }
 
-        function rowsToRanges(rows) {
-            var ranges = [];
-            var lastCell = _grid.getColumns().length - 1;
-            for (var i = 0; i < rows.length; i++) {
-                ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
-            }
-            return ranges;
-        }
+    function getRowsRange(from, to) {
+      var i, rows = [];
+      for (i = from; i <= to; i++) {
+        rows.push(i);
+      }
+      for (i = to; i < from; i++) {
+        rows.push(i);
+      }
+      return rows;
+    }
 
-        function getRowsRange(from, to) {
-            var i, rows = [];
-            for (i = from; i <= to; i++) {
-                rows.push(i);
-            }
-            for (i = to; i < from; i++) {
-                rows.push(i);
-            }
-            return rows;
-        }
+    function getSelectedRows() {
+      return rangesToRows(_ranges);
+    }
 
-        function getSelectedRows() {
-            return rangesToRows(_ranges);
-        }
+    function setSelectedRows(rows) {
+      setSelectedRanges(rowsToRanges(rows));
+    }
 
-        function setSelectedRows(rows) {
-            setSelectedRanges(rowsToRanges(rows));
-        }
+    function setSelectedRanges(ranges) {
+      _ranges = ranges;
+      _self.onSelectedRangesChanged.notify(_ranges);
+    }
 
-        function setSelectedRanges(ranges) {
-            _ranges = ranges;
-            _self.onSelectedRangesChanged.notify(_ranges);
-        }
+    function getSelectedRanges() {
+      return _ranges;
+    }
 
-        function getSelectedRanges() {
-            return _ranges;
-        }
+    function handleActiveCellChange(e, data) {
+      if (_options.selectActiveRow && data.row != null) {
+        setSelectedRanges([new Slick.Range(data.row, 0, data.row, _grid.getColumns().length - 1)]);
+      }
+    }
 
-        function handleActiveCellChange(e, data) {
-            if (_options.selectActiveRow) {
-                setSelectedRanges([new Slick.Range(data.row, 0, data.row, _grid.getColumns().length - 1)]);
-            }
+    function handleKeyDown(e) {
+      var activeRow = _grid.getActiveCell();
+      if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.which == 38 || e.which == 40)) {
+        var selectedRows = getSelectedRows();
+        selectedRows.sort(function (x, y) {
+          return x - y
+        });
+
+        if (!selectedRows.length) {
+          selectedRows = [activeRow.row];
         }
 
-        function handleKeyDown(e) {
-            var activeRow = _grid.getActiveCell();
-            if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.which == 38 || e.which == 40)) {
-                var selectedRows = getSelectedRows();
-                selectedRows.sort(function (x, y) {
-                    return x - y
-                });
-
-                if (!selectedRows.length) {
-                    selectedRows = [activeRow.row];
-                }
-
-                var top = selectedRows[0];
-                var bottom = selectedRows[selectedRows.length - 1];
-                var active;
-
-                if (e.which == 40) {
-                    active = activeRow.row < bottom || top == bottom ? ++bottom : ++top;
-                } else {
-                    active = activeRow.row < bottom ? --bottom : --top;
-                }
-
-                if (active >= 0 && active < _grid.getDataLength()) {
-                    _grid.scrollRowIntoView(active);
-                    _ranges = rowsToRanges(getRowsRange(top, bottom));
-                    setSelectedRanges(_ranges);
-                }
-
-                e.preventDefault();
-                e.stopPropagation();
-            }
+        var top = selectedRows[0];
+        var bottom = selectedRows[selectedRows.length - 1];
+        var active;
+
+        if (e.which == 40) {
+          active = activeRow.row < bottom || top == bottom ? ++bottom : ++top;
+        } else {
+          active = activeRow.row < bottom ? --bottom : --top;
         }
 
-        function handleClick(e) {
-            var cell = _grid.getCellFromEvent(e);
-            if (!cell || !_grid.canCellBeActive(cell.row, cell.cell)) {
-                return false;
-            }
-
-            var selection = rangesToRows(_ranges);
-            var idx = $.inArray(cell.row, selection);
-
-            if (!e.ctrlKey && !e.shiftKey && !e.metaKey) {
-                return false;
-            }
-            else if (_grid.getOptions().multiSelect) {
-                if (idx === -1 && (e.ctrlKey || e.metaKey)) {
-                    selection.push(cell.row);
-                    _grid.setActiveCell(cell.row, cell.cell);
-                } else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
-                    selection = $.grep(selection, function (o, i) {
-                        return (o !== cell.row);
-                    });
-                    _grid.setActiveCell(cell.row, cell.cell);
-                } else if (selection.length && e.shiftKey) {
-                    var last = selection.pop();
-                    var from = Math.min(cell.row, last);
-                    var to = Math.max(cell.row, last);
-                    selection = [];
-                    for (var i = from; i <= to; i++) {
-                        if (i !== last) {
-                            selection.push(i);
-                        }
-                    }
-                    selection.push(last);
-                    _grid.setActiveCell(cell.row, cell.cell);
-                }
-            }
-
-            _ranges = rowsToRanges(selection);
-            setSelectedRanges(_ranges);
-            e.stopImmediatePropagation();
-
-            return true;
+        if (active >= 0 && active < _grid.getDataLength()) {
+          _grid.scrollRowIntoView(active);
+          _ranges = rowsToRanges(getRowsRange(top, bottom));
+          setSelectedRanges(_ranges);
         }
 
-        $.extend(this, {
-            "getSelectedRows": getSelectedRows,
-            "setSelectedRows": setSelectedRows,
-            "getSelectedRanges": getSelectedRanges,
-            "setSelectedRanges": setSelectedRanges,
-            "init": init,
-            "destroy": destroy,
-            "onSelectedRangesChanged": new Slick.Event()
+        e.preventDefault();
+        e.stopPropagation();
+      }
+    }
+
+    function handleClick(e) {
+      var cell = _grid.getCellFromEvent(e);
+      if (!cell || !_grid.canCellBeActive(cell.row, cell.cell)) {
+        return false;
+      }
+
+      if (!_grid.getOptions().multiSelect || (
+          !e.ctrlKey && !e.shiftKey && !e.metaKey)) {
+        return false;
+      }
+
+      var selection = rangesToRows(_ranges);
+      var idx = $.inArray(cell.row, selection);
+
+      if (idx === -1 && (e.ctrlKey || e.metaKey)) {
+        selection.push(cell.row);
+        _grid.setActiveCell(cell.row, cell.cell);
+      } else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
+        selection = $.grep(selection, function (o, i) {
+          return (o !== cell.row);
         });
+        _grid.setActiveCell(cell.row, cell.cell);
+      } else if (selection.length && e.shiftKey) {
+        var last = selection.pop();
+        var from = Math.min(cell.row, last);
+        var to = Math.max(cell.row, last);
+        selection = [];
+        for (var i = from; i <= to; i++) {
+          if (i !== last) {
+            selection.push(i);
+          }
+        }
+        selection.push(last);
+        _grid.setActiveCell(cell.row, cell.cell);
+      }
+
+      _ranges = rowsToRanges(selection);
+      setSelectedRanges(_ranges);
+      e.stopImmediatePropagation();
+
+      return true;
     }
+
+    $.extend(this, {
+      "getSelectedRows": getSelectedRows,
+      "setSelectedRows": setSelectedRows,
+
+      "getSelectedRanges": getSelectedRanges,
+      "setSelectedRanges": setSelectedRanges,
+
+      "init": init,
+      "destroy": destroy,
+
+      "onSelectedRangesChanged": new Slick.Event()
+    });
+  }
 })(jQuery);
\ No newline at end of file