From 9ee1be2ecea62b991a8bffd1736ed0f80ee06a21 Mon Sep 17 00:00:00 2001
From: juanf <juanf>
Date: Mon, 14 Dec 2015 14:31:23 +0000
Subject: [PATCH] SSDM-2960 : ELN: Layout Improvements - Side Menu as tree

SVN: 35305
---
 .../1/as/webapps/eln-lims/html/index.html     |     4 +
 .../SideMenu/SideMenuWidgetController.js      |   111 +-
 .../js/views/SideMenu/SideMenuWidgetView.js   |    71 +-
 .../html/lib/jquery-fancytree/LICENSE.txt     |     9 +
 .../html/lib/jquery-fancytree/VERSION.txt     |     1 +
 .../js/jquery.fancytree-all.js                |  7678 +++++++
 .../js/jquery.fancytree-all.min.js            |    47 +
 .../jquery-fancytree/js/jquery.fancytree.js   |  4515 +++++
 .../js/jquery.fancytree.min.js                |    14 +
 .../js/skin-awesome/ui.fancytree.css          |   361 +
 .../js/skin-awesome/ui.fancytree.less         |    53 +
 .../js/skin-awesome/ui.fancytree.min.css      |     6 +
 .../js/skin-bootstrap-n/ui.fancytree.css      |   441 +
 .../js/skin-bootstrap-n/ui.fancytree.less     |   173 +
 .../js/skin-bootstrap-n/ui.fancytree.min.css  |     6 +
 .../js/skin-bootstrap/ui.fancytree.css        |   492 +
 .../js/skin-bootstrap/ui.fancytree.less       |   333 +
 .../js/skin-bootstrap/ui.fancytree.min.css    |     6 +
 .../lib/jquery-fancytree/js/skin-common.less  |   685 +
 .../js/skin-custom-1/README.md                |    14 +
 .../jquery-fancytree/js/skin-lion/icons.gif   |   Bin 0 -> 5906 bytes
 .../jquery-fancytree/js/skin-lion/loading.gif |   Bin 0 -> 1849 bytes
 .../js/skin-lion/ui.fancytree.css             |   565 +
 .../js/skin-lion/ui.fancytree.less            |    95 +
 .../js/skin-lion/ui.fancytree.min.css         |     6 +
 .../js/skin-themeroller/icons.gif             |   Bin 0 -> 5492 bytes
 .../js/skin-themeroller/loading.gif           |   Bin 0 -> 3234 bytes
 .../js/skin-themeroller/ui.fancytree.css      |   505 +
 .../js/skin-themeroller/ui.fancytree.min.css  |     1 +
 .../jquery-fancytree/js/skin-vista/icons.gif  |   Bin 0 -> 5492 bytes
 .../js/skin-vista/loading.gif                 |   Bin 0 -> 3234 bytes
 .../js/skin-vista/ui.fancytree.css            |   571 +
 .../js/skin-vista/ui.fancytree.less           |   112 +
 .../js/skin-vista/ui.fancytree.min.css        |     6 +
 .../jquery-fancytree/js/skin-win7/icons.gif   |   Bin 0 -> 5492 bytes
 .../jquery-fancytree/js/skin-win7/loading.gif |   Bin 0 -> 3234 bytes
 .../js/skin-win7/ui.fancytree.css             |   630 +
 .../js/skin-win7/ui.fancytree.less            |   152 +
 .../js/skin-win7/ui.fancytree.min.css         |     6 +
 .../jquery-fancytree/js/skin-win8-n/icons.gif |   Bin 0 -> 5492 bytes
 .../js/skin-win8-n/loading.gif                |   Bin 0 -> 3234 bytes
 .../js/skin-win8-n/ui.fancytree.css           |   575 +
 .../js/skin-win8-n/ui.fancytree.less          |   143 +
 .../js/skin-win8-n/ui.fancytree.min.css       |     6 +
 .../js/skin-win8-xxl/icons.gif                |   Bin 0 -> 20860 bytes
 .../js/skin-win8-xxl/loading.gif              |   Bin 0 -> 6243 bytes
 .../js/skin-win8-xxl/ui.fancytree.css         |   583 +
 .../js/skin-win8-xxl/ui.fancytree.less        |    37 +
 .../js/skin-win8-xxl/ui.fancytree.min.css     |    11 +
 .../jquery-fancytree/js/skin-win8/icons.gif   |   Bin 0 -> 5492 bytes
 .../jquery-fancytree/js/skin-win8/loading.gif |   Bin 0 -> 3234 bytes
 .../js/skin-win8/ui.fancytree.css             |   573 +
 .../js/skin-win8/ui.fancytree.less            |   153 +
 .../js/skin-win8/ui.fancytree.min.css         |     6 +
 .../jquery-fancytree/js/skin-xp/icons-rtl.gif |   Bin 0 -> 4046 bytes
 .../lib/jquery-fancytree/js/skin-xp/icons.gif |   Bin 0 -> 4041 bytes
 .../jquery-fancytree/js/skin-xp/loading.gif   |   Bin 0 -> 570 bytes
 .../js/skin-xp/ui.fancytree.css               |   562 +
 .../js/skin-xp/ui.fancytree.less              |    96 +
 .../js/skin-xp/ui.fancytree.min.css           |     6 +
 .../jquery-fancytree/js/skin-xp/vline-rtl.gif |   Bin 0 -> 842 bytes
 .../lib/jquery-fancytree/js/skin-xp/vline.gif |   Bin 0 -> 844 bytes
 .../js/src/jquery.fancytree.childcounter.js   |   208 +
 .../js/src/jquery.fancytree.clones.js         |   451 +
 .../js/src/jquery.fancytree.columnview.js     |   150 +
 .../js/src/jquery.fancytree.debug.js          |   142 +
 .../js/src/jquery.fancytree.dnd.js            |   553 +
 .../js/src/jquery.fancytree.edit.js           |   309 +
 .../js/src/jquery.fancytree.filter.js         |   283 +
 .../js/src/jquery.fancytree.glyph.js          |   139 +
 .../js/src/jquery.fancytree.gridnav.js        |   199 +
 .../js/src/jquery.fancytree.js                |  4515 +++++
 .../js/src/jquery.fancytree.menu.js           |   155 +
 .../js/src/jquery.fancytree.persist.js        |   383 +
 .../js/src/jquery.fancytree.table.js          |   366 +
 .../js/src/jquery.fancytree.themeroller.js    |    78 +
 .../js/src/jquery.fancytree.wide.js           |   183 +
 .../eln-lims/html/lib/jquery-ui/LICENSE.txt   |     1 +
 .../eln-lims/html/lib/jquery-ui/VERSION.txt   |     1 +
 .../html/lib/jquery-ui/js/jquery-ui-custom.js | 16617 ++++++++++++++++
 80 files changed, 45071 insertions(+), 82 deletions(-)
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/LICENSE.txt
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/VERSION.txt
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.min.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.min.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-common.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-custom-1/README.md
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/icons-rtl.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/icons.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/loading.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.less
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.min.css
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/vline-rtl.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/vline.gif
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.childcounter.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.clones.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.columnview.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.debug.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.dnd.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.edit.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.filter.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.glyph.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.gridnav.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.menu.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.persist.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.table.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.themeroller.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.wide.js
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/LICENSE.txt
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/VERSION.txt
 create mode 100644 plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/js/jquery-ui-custom.js

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html
index 9fc1d389765..5f9cc348693 100644
--- a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html
@@ -32,12 +32,16 @@
 	<link type="text/css" rel="stylesheet" href="./lib/jquery-tooltipster/css/tooltipster.css" />
 	<link type="text/css" rel="stylesheet" href="./lib/fuelux/css/fuelux.min.css" />
 	<link type="text/css" rel="stylesheet" href="./lib/drawingboard/css/drawingboard.min.css" />
+	<link type="text/css" rel="stylesheet" href="./lib/jquery-fancytree/js/skin-lion/ui.fancytree.min.css" />
 	
 	<!-- ELN UI Stylesheets -->
 	<link type="text/css" rel="stylesheet" href="./css/style.css" />
 	
 	<!-- Third party libraries -->
 	<script type="text/javascript" src="./lib/jquery/js/jquery-1.11.3.min.js"></script>
+	<script type="text/javascript" src="./lib/jquery-ui/js/jquery-ui-custom.js"></script>
+	<script type="text/javascript" src="./lib/jquery-fancytree/js/jquery.fancytree.js"></script>
+	
 	<script type="text/javascript" src="./lib/bootstrap-datetimepicker/js/moment.js"></script>
 	<script type="text/javascript" src="./lib/bootstrap/js/bootstrap.min.js"></script>
 	<script type="text/javascript" src="./lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js"></script>
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetController.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetController.js
index 8330a8216f2..e1722786255 100644
--- a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetController.js
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetController.js
@@ -40,8 +40,8 @@ function SideMenuWidgetController(mainController) {
             		if(currentItemChild.uniqueId === uniqueId) {
             			currentItem.newMenuIfSelected.children.splice(i,1);
             			if(!notMoveToParent) {
+            				this._sideMenuWidgetModel.pointerToMenuNode = currentItem;
             				mainController.changeView(currentItem.newViewIfSelected, currentItem.newViewIfSelectedData);
-                			this._sideMenuWidgetModel.pointerToMenuNode = currentItem;
             			}
             			
             			this._sideMenuWidgetView.repaint();
@@ -91,7 +91,7 @@ function SideMenuWidgetController(mainController) {
     
     
     this.refreshProject = function(spaceCode, projectCode) {
-        var menuItemSpace = this._getSpaceNodeForCode(spaceCode);
+        var menuItemSpace = this._getUniqueId(spaceCode);
         var newMenuIfSelectedProject = {
             children: []
         };
@@ -136,7 +136,7 @@ function SideMenuWidgetController(mainController) {
     this.refreshExperiment = function(experiment, isInventory) {
         var projectIdentifierEnd = experiment.identifier.lastIndexOf("/");
         var projectIdentifier = experiment.identifier.substring(0, projectIdentifierEnd);
-        var projectNode = this._getProjectNodeForIdentifier(projectIdentifier);
+        var projectNode = this._getUniqueId(projectIdentifier);
 
         var newMenuIfSelectedExperiment = {
             children: []
@@ -171,7 +171,7 @@ function SideMenuWidgetController(mainController) {
                 for (var i = 0; i < subExperiments.result.length; i++) {
                     var subExperiment = subExperiments.result[i];
                     if (subExperiment.experimentIdentifierOrNull) {
-                        var experimentNode = _this._getExperimentNodeForIdentifier(subExperiment.experimentIdentifierOrNull);
+                        var experimentNode = _this._getUniqueId(subExperiment.experimentIdentifierOrNull);
                         var displayName = null;
                         if (profile.hideCodes) {
                             displayName = subExperiment.properties[profile.propertyReplacingCode];
@@ -198,10 +198,9 @@ function SideMenuWidgetController(mainController) {
     this.init = function($container, initCallback) {
     	this._sideMenuWidgetModel.$container = $container;
         var _this = this;
-
-        this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                new SideMenuWidgetComponent(false, true, "LAB NOTEBOOK", "LAB_NOTEBOOK", this._sideMenuWidgetModel.menuStructure, null, null, null, "")
-                );
+        
+        var labNotebookNode = new SideMenuWidgetComponent(true, true, "LAB NOTEBOOK", "LAB_NOTEBOOK", this._sideMenuWidgetModel.menuStructure, { children: [] }, null, null, "");
+        this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(labNotebookNode);
 
         mainController.serverFacade.listSpacesWithProjectsAndRoleAssignments(null, function(dataWithSpacesAndProjects) {
             //Fill Spaces
@@ -217,9 +216,9 @@ function SideMenuWidgetController(mainController) {
                 var newMenuIfSelectedSpace = {
                     children: []
                 };
-                var menuItemSpace = new SideMenuWidgetComponent(true, false, space.code, space.code, _this._sideMenuWidgetModel.menuStructure, newMenuIfSelectedSpace, 'showSpacePage', space.code, "(Space)");
-                _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(menuItemSpace);
-
+                var menuItemSpace = new SideMenuWidgetComponent(true, false, space.code, space.code, labNotebookNode, newMenuIfSelectedSpace, 'showSpacePage', space.code, "(Space)");
+                labNotebookNode.newMenuIfSelected.children.push(menuItemSpace);
+                
                 //Fill Projects
                 for (var j = 0; j < space.projects.length; j++) {
                     var project = space.projects[j];
@@ -250,7 +249,7 @@ function SideMenuWidgetController(mainController) {
                         experimentsToAskForSamples.push(experiment);
                         var projectIdentifierEnd = experiment.identifier.lastIndexOf("/");
                         var projectIdentifier = experiment.identifier.substring(0, projectIdentifierEnd);
-                        var projectNode = _this._getProjectNodeForIdentifier(projectIdentifier);
+                        var projectNode = _this._getUniqueId(projectIdentifier);
                         toSortExperiments[projectNode.uniqueId] = projectNode;
                         var newMenuIfSelectedExperiment = {
                             children: []
@@ -280,7 +279,7 @@ function SideMenuWidgetController(mainController) {
 
                         for (var i = 0; i < subExperiments.result.length; i++) {
                             var subExperiment = subExperiments.result[i];
-                            var experimentNode = _this._getExperimentNodeForIdentifier(subExperiment.experimentIdentifierOrNull);
+                            var experimentNode = _this._getUniqueId(subExperiment.experimentIdentifierOrNull);
                             toSortSubExperiments[experimentNode.uniqueId] = experimentNode;
                             if (subExperiment.experimentIdentifierOrNull) {
                                 var displayName = null;
@@ -303,9 +302,8 @@ function SideMenuWidgetController(mainController) {
 
                     
                     //Fill Inventory
-                    _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                            new SideMenuWidgetComponent(false, true, "INVENTORY", "INVENTORY", _this._sideMenuWidgetModel.menuStructure, null, null, null, "")
-                            );
+                    var inventoryNode = new SideMenuWidgetComponent(true, true, "INVENTORY", "INVENTORY", _this._sideMenuWidgetModel.menuStructure, { children: [] }, null, null, "");
+                    _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(inventoryNode);
 
                     //Fill Spaces
                     var spaces = dataWithSpacesAndProjects.result;
@@ -320,8 +318,8 @@ function SideMenuWidgetController(mainController) {
                         var newMenuIfSelectedSpace = {
                             children: []
                         };
-                        var menuItemSpace = new SideMenuWidgetComponent(true, false, space.code, space.code, _this._sideMenuWidgetModel.menuStructure, newMenuIfSelectedSpace, 'showSpacePage', space.code, "(Space)");
-                        _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(menuItemSpace);
+                        var menuItemSpace = new SideMenuWidgetComponent(true, false, space.code, space.code, inventoryNode, newMenuIfSelectedSpace, 'showSpacePage', space.code, "(Space)");
+                        inventoryNode.newMenuIfSelected.children.push(menuItemSpace);
 
                         //Fill Projects
                         for (var j = 0; j < space.projects.length; j++) {
@@ -349,7 +347,7 @@ function SideMenuWidgetController(mainController) {
                                 experimentsToAskForSamples.push(experiment);
                                 var projectIdentifierEnd = experiment.identifier.lastIndexOf("/");
                                 var projectIdentifier = experiment.identifier.substring(0, projectIdentifierEnd);
-                                var projectNode = _this._getProjectNodeForIdentifier(projectIdentifier);
+                                var projectNode = _this._getUniqueId(projectIdentifier);
 
                                 var newMenuIfSelectedExperiment = {
                                     children: []
@@ -371,31 +369,30 @@ function SideMenuWidgetController(mainController) {
 
 
                         //Fill Utils
-                        _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                                new SideMenuWidgetComponent(false, true, "UTILITIES", "UTILITIES", _this._sideMenuWidgetModel.menuStructure, null, null, null, "")
-                                );
-//                        _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-//                                new SideMenuWidgetComponent(true, false, "DRAWING BOARD", "DRAWING_BOARD", _this._sideMenuWidgetModel.menuStructure, null, "showDrawingBoard", null, "")
+                        var utilities = new SideMenuWidgetComponent(true, true, "UTILITIES", "UTILITIES", _this._sideMenuWidgetModel.menuStructure, { children : [] } , null, null, "");
+                        _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(utilities);
+//                        utilities.newMenuIfSelected.children.push(
+//                                new SideMenuWidgetComponent(true, false, "DRAWING BOARD", "DRAWING_BOARD", utilities, null, "showDrawingBoard", null, "")
 //                                );
-                        _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                                new SideMenuWidgetComponent(true, false, "SAMPLE BROWSER", "SAMPLE_BROWSER", _this._sideMenuWidgetModel.menuStructure, null, "showSamplesPage", null, "")
+                        utilities.newMenuIfSelected.children.push(
+                                new SideMenuWidgetComponent(true, false, "SAMPLE BROWSER", "SAMPLE_BROWSER", utilities, null, "showSamplesPage", null, "")
                                 );
                         if (profile.storagesConfiguration["isEnabled"]) {
-                            _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                                    new SideMenuWidgetComponent(true, false, "STORAGE MANAGER", "STORAGE_MANAGER", _this._sideMenuWidgetModel.menuStructure, null, "showStorageManager", null, "")
+                        	utilities.newMenuIfSelected.children.push(
+                                    new SideMenuWidgetComponent(true, false, "STORAGE MANAGER", "STORAGE_MANAGER", utilities, null, "showStorageManager", null, "")
                                     );
                         }
-                        _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                                new SideMenuWidgetComponent(true, false, "TRASHCAN", "TRASHCAN", _this._sideMenuWidgetModel.menuStructure, null, "showTrashcanPage", null, "")
+                        utilities.newMenuIfSelected.children.push(
+                                new SideMenuWidgetComponent(true, false, "TRASHCAN", "TRASHCAN", utilities, null, "showTrashcanPage", null, "")
                                 );
-                        _this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                                new SideMenuWidgetComponent(true, false, "VOCABULARY VIEWER", "VOCABULARY_VIEWER", _this._sideMenuWidgetModel.menuStructure, null, "showVocabularyManagerPage", null, "")
+                        utilities.newMenuIfSelected.children.push(
+                                new SideMenuWidgetComponent(true, false, "VOCABULARY VIEWER", "VOCABULARY_VIEWER", utilities, null, "showVocabularyManagerPage", null, "")
                                 );
                         
                         mainController.serverFacade.listPersons(function(data) {
                 			if(data.result && data.result.length > 0) {
-                				_this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.push(
-                                        new SideMenuWidgetComponent(true, false, "USER MANAGER", "USER_MANAGER", _this._sideMenuWidgetModel.menuStructure, null, "showUserManagerPage", null, "")
+                				utilities.newMenuIfSelected.children.push(
+                                        new SideMenuWidgetComponent(true, false, "USER MANAGER", "USER_MANAGER", utilities, null, "showUserManagerPage", null, "")
                                 );
                 			}
                 			
@@ -439,53 +436,7 @@ function SideMenuWidgetController(mainController) {
             $elementBody.css('max-height', (windowHeight - sideMenuHeaderHeight - 17) + "px");
         });
     };
-    
-    //
-    // Utility Methods
-    //
-    this._getSpaceNodeForCode = function(spaceCode) {
-        for (var sIdx = 0; sIdx < this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.length; sIdx++) {
-            var spaceNode = this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children[sIdx];
-            if (spaceNode.isTitle && !spaceNode.isSelectable) {
-                continue;
-            }
-            if (spaceNode.uniqueId === spaceCode) {
-                return spaceNode;
-            }
-        }
-        return null;
-    };
-
-    this._getProjectNodeForIdentifier = function(projectIdentifier) {
-        for (var sIdx = 0; sIdx < this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children.length; sIdx++) {
-            var spaceNode = this._sideMenuWidgetModel.menuStructure.newMenuIfSelected.children[sIdx];
-            if (spaceNode.isTitle && !spaceNode.isSelectable) {
-                continue;
-            }
-            var projectsFromSpace = spaceNode.newMenuIfSelected.children;
-            for (var pIdx = 0; pIdx < projectsFromSpace.length; pIdx++) {
-                var projectNode = projectsFromSpace[pIdx];
-                if (projectNode.uniqueId === projectIdentifier) {
-                    return projectNode;
-                }
-            }
-        }
-        return null;
-    };
 
-    this._getExperimentNodeForIdentifier = function(experimentIdentifier) {
-        var projectIdentifierEnd = experimentIdentifier.lastIndexOf("/");
-        var projectIdentifier = experimentIdentifier.substring(0, projectIdentifierEnd);
-        var projectNode = this._getProjectNodeForIdentifier(projectIdentifier);
-        var experimentsFromProject = projectNode.newMenuIfSelected.children;
-        for (var eIdx = 0; eIdx < experimentsFromProject.length; eIdx++) {
-            var experimentNode = experimentsFromProject[eIdx];
-            if (experimentNode.uniqueId === experimentIdentifier) {
-                return experimentNode;
-            }
-        }
-        return null;
-    };
 }
 
 function SideMenuWidgetComponent(isSelectable, isTitle, displayName, uniqueId, parent, newMenuIfSelected, newViewIfSelected, newViewIfSelectedData, contextTitle) {
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js
index 604ae7ef5e9..1bf393cbc7c 100644
--- a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js
@@ -205,8 +205,76 @@ function SideMenuWidgetView(sideMenuWidgetController, sideMenuWidgetModel) {
         this._sideMenuWidgetModel.menuDOMBody = $body;
         this.repaint();
     };
-
+    
     this.repaint = function() {
+    	this.treeMenu();
+//    	this.repaintSliderMenu();
+    }
+    
+    this.treeMenu = function() {
+    	var _this = this;
+        
+        this._sideMenuWidgetModel.menuDOMBody.empty();
+        var tree = $("<div>", { "id" : "tree" });
+        
+        //
+        // Body
+        //
+        var rootNode = { title : "Main Menu", key : "MAIN_MENU", menuData : this._sideMenuWidgetModel.menuStructure };
+        var sourceByKey = { "MAIN_MENU" : rootNode };
+        var treeModel = [rootNode];
+        var todo = [this._sideMenuWidgetModel.menuStructure];
+
+        while(todo.length > 0) {
+        	var modelNode = todo.shift();
+        	var treeModelNode = sourceByKey[modelNode.uniqueId];
+        	if(modelNode.newMenuIfSelected && modelNode.newMenuIfSelected.children.length !== 0) {
+        		treeModelNode.folder = true;
+        		if(!treeModelNode.children) {
+        			treeModelNode.children = [];
+        		}
+        		
+        		for(var cIdx = 0; cIdx < modelNode.newMenuIfSelected.children.length; cIdx++) {
+        			var modelNodeChild = modelNode.newMenuIfSelected.children[cIdx];
+        			treeModelChild = {title : modelNodeChild.displayName, key : modelNodeChild.uniqueId, menuData : modelNodeChild};
+        			treeModelNode.children.push(treeModelChild);
+        			todo.push(modelNodeChild);
+        			sourceByKey[treeModelChild.key] = treeModelChild;
+        		}
+        	}
+        }
+        tree.fancytree({
+        	source: treeModel,
+        	activate: function(event, data){
+        		var menuData = data.node.data.menuData;
+        		data.node.setExpanded(true);
+        		if(menuData.isSelectable) {
+        			_this._sideMenuWidgetModel.pointerToMenuNode = menuData;
+        			if(menuData.newViewIfSelected && menuData.newViewIfSelectedData) {
+        				mainController.changeView(menuData.newViewIfSelected, menuData.newViewIfSelectedData);
+        			}
+        		}
+        	}
+        });
+        this._sideMenuWidgetModel.menuDOMBody.append(tree);
+        
+        //Expand Tree Node
+        var expandToParent = function(tree, menuData, isFirst) {
+        	var node = tree.fancytree("getTree").getNodeByKey(menuData.uniqueId);
+        	node.setExpanded(true);
+        	if(isFirst) {
+        		node.setActive(true);
+        	}
+        	if(menuData.parent) {
+        		expandToParent(tree, menuData.parent, false);
+        	}
+        }
+        
+        var menuToPaint = this._sideMenuWidgetModel.pointerToMenuNode;
+        expandToParent(tree, menuToPaint, true);
+    }
+    
+    this.repaintSliderMenu = function() {
         var _this = this;
         var menuToPaint = this._sideMenuWidgetModel.pointerToMenuNode;
         //
@@ -219,7 +287,6 @@ function SideMenuWidgetView(sideMenuWidgetController, sideMenuWidgetModel) {
             var titleDisplayName = (menuToPaint.displayName);
         }
         //
-
         this._sideMenuWidgetModel.menuDOMTitle.empty();
         var isBackButtonShown = menuToPaint.parent !== null;
         if (isBackButtonShown) {
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/LICENSE.txt b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/LICENSE.txt
new file mode 100644
index 00000000000..f8e92fe22e5
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/LICENSE.txt
@@ -0,0 +1,9 @@
+Open Source - MIT License : https://github.com/mar10/fancytree/wiki/LicenseInfo
+
+artin@MBP edited this page on 17 Jan 2014 · 1 revision 
+
+You may use Fancytree under the terms of the MIT License.
+
+The MIT License is simple and easy to understand and it places almost no restrictions on what you can do with Fancytree.
+
+You are free to use Fancytree in any other project (even commercial projects) as long as the copyright header is left intact.
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/VERSION.txt b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/VERSION.txt
new file mode 100644
index 00000000000..a3ebb9f516e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/VERSION.txt
@@ -0,0 +1 @@
+2.13.0
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.js
new file mode 100644
index 00000000000..2ac1aa18426
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.js
@@ -0,0 +1,7678 @@
+/*!
+ * jquery.fancytree.js
+ * Tree view control with support for lazy loading and much more.
+ * https://github.com/mar10/fancytree/
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+/** Core Fancytree module.
+ */
+
+
+// Start of local namespace
+;(function($, window, document, undefined) {
+"use strict";
+
+// prevent duplicate loading
+if ( $.ui && $.ui.fancytree ) {
+	$.ui.fancytree.warn("Fancytree: ignored duplicate include");
+	return;
+}
+
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+
+function _assert(cond, msg){
+	// TODO: see qunit.js extractStacktrace()
+	if(!cond){
+		msg = msg ? ": " + msg : "";
+		// consoleApply("assert", [!!cond, msg]);
+		$.error("Fancytree assertion failed" + msg);
+	}
+}
+
+_assert($.ui, "Fancytree requires jQuery UI (http://jqueryui.com)");
+
+function consoleApply(method, args){
+	var i, s,
+		fn = window.console ? window.console[method] : null;
+
+	if(fn){
+		try{
+			fn.apply(window.console, args);
+		} catch(e) {
+			// IE 8?
+			s = "";
+			for( i=0; i<args.length; i++){
+				s += args[i];
+			}
+			fn(s);
+		}
+	}
+}
+
+/*Return true if x is a FancytreeNode.*/
+function _isNode(x){
+	return !!(x.tree && x.statusNodeType !== undefined);
+}
+
+/** Return true if dotted version string is equal or higher than requested version.
+ *
+ * See http://jsfiddle.net/mar10/FjSAN/
+ */
+function isVersionAtLeast(dottedVersion, major, minor, patch){
+	var i, v, t,
+		verParts = $.map($.trim(dottedVersion).split("."), function(e){ return parseInt(e, 10); }),
+		testParts = $.map(Array.prototype.slice.call(arguments, 1), function(e){ return parseInt(e, 10); });
+
+	for( i = 0; i < testParts.length; i++ ){
+		v = verParts[i] || 0;
+		t = testParts[i] || 0;
+		if( v !== t ){
+			return ( v > t );
+		}
+	}
+	return true;
+}
+
+/** Return a wrapper that calls sub.methodName() and exposes
+ *  this        : tree
+ *  this._local : tree.ext.EXTNAME
+ *  this._super : base.methodName()
+ */
+function _makeVirtualFunction(methodName, tree, base, extension, extName){
+	// $.ui.fancytree.debug("_makeVirtualFunction", methodName, tree, base, extension, extName);
+	// if(rexTestSuper && !rexTestSuper.test(func)){
+	//     // extension.methodName() doesn't call _super(), so no wrapper required
+	//     return func;
+	// }
+	// Use an immediate function as closure
+	var proxy = (function(){
+		var prevFunc = tree[methodName],      // org. tree method or prev. proxy
+			baseFunc = extension[methodName], //
+			_local = tree.ext[extName],
+			_super = function(){
+				return prevFunc.apply(tree, arguments);
+			},
+			_superApply = function(args){
+				return prevFunc.apply(tree, args);
+			};
+
+		// Return the wrapper function
+		return function(){
+			var prevLocal = tree._local,
+				prevSuper = tree._super,
+				prevSuperApply = tree._superApply;
+
+			try{
+				tree._local = _local;
+				tree._super = _super;
+				tree._superApply = _superApply;
+				return  baseFunc.apply(tree, arguments);
+			}finally{
+				tree._local = prevLocal;
+				tree._super = prevSuper;
+				tree._superApply = prevSuperApply;
+			}
+		};
+	})(); // end of Immediate Function
+	return proxy;
+}
+
+/**
+ * Subclass `base` by creating proxy functions
+ */
+function _subclassObject(tree, base, extension, extName){
+	// $.ui.fancytree.debug("_subclassObject", tree, base, extension, extName);
+	for(var attrName in extension){
+		if(typeof extension[attrName] === "function"){
+			if(typeof tree[attrName] === "function"){
+				// override existing method
+				tree[attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);
+			}else if(attrName.charAt(0) === "_"){
+				// Create private methods in tree.ext.EXTENSION namespace
+				tree.ext[extName][attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);
+			}else{
+				$.error("Could not override tree." + attrName + ". Use prefix '_' to create tree." + extName + "._" + attrName);
+			}
+		}else{
+			// Create member variables in tree.ext.EXTENSION namespace
+			if(attrName !== "options"){
+				tree.ext[extName][attrName] = extension[attrName];
+			}
+		}
+	}
+}
+
+
+function _getResolvedPromise(context, argArray){
+	if(context === undefined){
+		return $.Deferred(function(){this.resolve();}).promise();
+	}else{
+		return $.Deferred(function(){this.resolveWith(context, argArray);}).promise();
+	}
+}
+
+
+function _getRejectedPromise(context, argArray){
+	if(context === undefined){
+		return $.Deferred(function(){this.reject();}).promise();
+	}else{
+		return $.Deferred(function(){this.rejectWith(context, argArray);}).promise();
+	}
+}
+
+
+function _makeResolveFunc(deferred, context){
+	return function(){
+		deferred.resolveWith(context);
+	};
+}
+
+
+function _getElementDataAsDict($el){
+	// Evaluate 'data-NAME' attributes with special treatment for 'data-json'.
+	var d = $.extend({}, $el.data()),
+		json = d.json;
+
+	delete d.fancytree; // added to container by widget factory (old jQuery UI)
+	delete d.uiFancytree; // added to container by widget factory
+
+	if( json ) {
+		delete d.json;
+		// <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)
+		d = $.extend(d, json);
+	}
+	return d;
+}
+
+
+// TODO: use currying
+function _makeNodeTitleMatcher(s){
+	s = s.toLowerCase();
+	return function(node){
+		return node.title.toLowerCase().indexOf(s) >= 0;
+	};
+}
+
+
+function _makeNodeTitleStartMatcher(s){
+	var reMatch = new RegExp("^" + s, "i");
+	return function(node){
+		return reMatch.test(node.title);
+	};
+}
+
+var i, attr,
+	FT = null, // initialized below
+	ENTITY_MAP = {"&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;", "/": "&#x2F;"},
+	IGNORE_KEYCODES = { 16: true, 17: true, 18: true },
+	SPECIAL_KEYCODES = {
+		8: "backspace", 9: "tab", 10: "return", 13: "return",
+		// 16: null, 17: null, 18: null, // ignore shift, ctrl, alt
+		19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup",
+		34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up",
+		39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=",
+		96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6",
+		103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".",
+		111: "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5",
+		117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11",
+		123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=",
+		188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
+		221: "]", 222: "'"},
+	MOUSE_BUTTONS = { 0: "", 1: "left", 2: "middle", 3: "right" },
+	//boolean attributes that can be set with equivalent class names in the LI tags
+	CLASS_ATTRS = "active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),
+	CLASS_ATTR_MAP = {},
+	//	Top-level Fancytree node attributes, that can be set by dict
+	NODE_ATTRS = "expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "),
+	NODE_ATTR_MAP = {},
+	// Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)
+	NODE_ATTR_LOWERCASE_MAP = {},
+	// Attribute names that should NOT be added to node.data
+	NONE_NODE_DATA_MAP = {"active": true, "children": true, "data": true, "focus": true};
+
+for(i=0; i<CLASS_ATTRS.length; i++){ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true; }
+for(i=0; i<NODE_ATTRS.length; i++) {
+	attr = NODE_ATTRS[i];
+	NODE_ATTR_MAP[attr] = true;
+	if( attr !== attr.toLowerCase() ) {
+		NODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;
+	}
+}
+
+
+/* *****************************************************************************
+ * FancytreeNode
+ */
+
+
+/**
+ * Creates a new FancytreeNode
+ *
+ * @class FancytreeNode
+ * @classdesc A FancytreeNode represents the hierarchical data model and operations.
+ *
+ * @param {FancytreeNode} parent
+ * @param {NodeData} obj
+ *
+ * @property {Fancytree} tree The tree instance
+ * @property {FancytreeNode} parent The parent node
+ * @property {string} key Node id (must be unique inside the tree)
+ * @property {string} title Display name (may contain HTML)
+ * @property {object} data Contains all extra data that was passed on node creation
+ * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>
+ *     For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array
+ *     to define a node that has no children.
+ * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.
+ * @property {string} extraClasses Addtional CSS classes, added to the node's `&lt;span>`
+ * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>
+ *     Note: Also non-folders may have children.
+ * @property {string} statusNodeType null or type of temporarily generated system node like 'loading', or 'error'.
+ * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.
+ * @property {boolean} selected Use isSelected(), setSelected() to access this property.
+ * @property {string} tooltip Alternative description used as hover banner
+ */
+function FancytreeNode(parent, obj){
+	var i, l, name, cl;
+
+	this.parent = parent;
+	this.tree = parent.tree;
+	this.ul = null;
+	this.li = null;  // <li id='key' ftnode=this> tag
+	this.statusNodeType = null; // if this is a temp. node to display the status of its parent
+	this._isLoading = false;    // if this node itself is loading
+	this._error = null;         // {message: '...'} if a load error occurred
+	this.data = {};
+
+	// TODO: merge this code with node.toDict()
+	// copy attributes from obj object
+	for(i=0, l=NODE_ATTRS.length; i<l; i++){
+		name = NODE_ATTRS[i];
+		this[name] = obj[name];
+	}
+	// node.data += obj.data
+	if(obj.data){
+		$.extend(this.data, obj.data);
+	}
+	// copy all other attributes to this.data.NAME
+	for(name in obj){
+		if(!NODE_ATTR_MAP[name] && !$.isFunction(obj[name]) && !NONE_NODE_DATA_MAP[name]){
+			// node.data.NAME = obj.NAME
+			this.data[name] = obj[name];
+		}
+	}
+
+	// Fix missing key
+	if( this.key == null ){ // test for null OR undefined
+		if( this.tree.options.defaultKey ) {
+			this.key = this.tree.options.defaultKey(this);
+			_assert(this.key, "defaultKey() must return a unique key");
+		} else {
+			this.key = "_" + (FT._nextNodeKey++);
+		}
+	} else {
+		this.key = "" + this.key; // Convert to string (#217)
+	}
+
+	// Fix tree.activeNode
+	// TODO: not elegant: we use obj.active as marker to set tree.activeNode
+	// when loading from a dictionary.
+	if(obj.active){
+		_assert(this.tree.activeNode === null, "only one active node allowed");
+		this.tree.activeNode = this;
+	}
+	if( obj.selected ){ // #186
+		this.tree.lastSelectedNode = this;
+	}
+	// TODO: handle obj.focus = true
+	// Create child nodes
+	cl = obj.children;
+	if( cl ){
+		if( cl.length ){
+			this._setChildren(cl);
+		} else {
+			// if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'
+			this.children = this.lazy ? [] : null;
+		}
+	} else {
+		this.children = null;
+	}
+	// Add to key/ref map (except for root node)
+//	if( parent ) {
+	this.tree._callHook("treeRegisterNode", this.tree, true, this);
+//	}
+}
+
+
+FancytreeNode.prototype = /** @lends FancytreeNode# */{
+	/* Return the direct child FancytreeNode with a given key, index. */
+	_findDirectChild: function(ptr){
+		var i, l,
+			cl = this.children;
+
+		if(cl){
+			if(typeof ptr === "string"){
+				for(i=0, l=cl.length; i<l; i++){
+					if(cl[i].key === ptr){
+						return cl[i];
+					}
+				}
+			}else if(typeof ptr === "number"){
+				return this.children[ptr];
+			}else if(ptr.parent === this){
+				return ptr;
+			}
+		}
+		return null;
+	},
+	// TODO: activate()
+	// TODO: activateSilently()
+	/* Internal helper called in recursive addChildren sequence.*/
+	_setChildren: function(children){
+		_assert(children && (!this.children || this.children.length === 0), "only init supported");
+		this.children = [];
+		for(var i=0, l=children.length; i<l; i++){
+			this.children.push(new FancytreeNode(this, children[i]));
+		}
+	},
+	/**
+	 * Append (or insert) a list of child nodes.
+	 *
+	 * @param {NodeData[]} children array of child node definitions (also single child accepted)
+	 * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).
+	 *     If omitted, the new children are appended.
+	 * @returns {FancytreeNode} first child added
+	 *
+	 * @see FancytreeNode#applyPatch
+	 */
+	addChildren: function(children, insertBefore){
+		var i, l, pos,
+			firstNode = null,
+			nodeList = [];
+
+		if($.isPlainObject(children) ){
+			children = [children];
+		}
+		if(!this.children){
+			this.children = [];
+		}
+		for(i=0, l=children.length; i<l; i++){
+			nodeList.push(new FancytreeNode(this, children[i]));
+		}
+		firstNode = nodeList[0];
+		if(insertBefore == null){
+			this.children = this.children.concat(nodeList);
+		}else{
+			insertBefore = this._findDirectChild(insertBefore);
+			pos = $.inArray(insertBefore, this.children);
+			_assert(pos >= 0, "insertBefore must be an existing child");
+			// insert nodeList after children[pos]
+			this.children.splice.apply(this.children, [pos, 0].concat(nodeList));
+		}
+		if( !this.parent || this.parent.ul || this.tr ){
+			// render if the parent was rendered (or this is a root node)
+			this.render();
+		}
+		if( this.tree.options.selectMode === 3 ){
+			this.fixSelection3FromEndNodes();
+		}
+		return firstNode;
+	},
+	/**
+	 * Append or prepend a node, or append a child node.
+	 *
+	 * This a convenience function that calls addChildren()
+	 *
+	 * @param {NodeData} node node definition
+	 * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
+	 * @returns {FancytreeNode} new node
+	 */
+	addNode: function(node, mode){
+		if(mode === undefined || mode === "over"){
+			mode = "child";
+		}
+		switch(mode){
+		case "after":
+			return this.getParent().addChildren(node, this.getNextSibling());
+		case "before":
+			return this.getParent().addChildren(node, this);
+		case "firstChild":
+			// Insert before the first child if any
+			var insertBefore = (this.children ? this.children[0] : null);
+			return this.addChildren(node, insertBefore);
+		case "child":
+		case "over":
+			return this.addChildren(node);
+		}
+		_assert(false, "Invalid mode: " + mode);
+	},
+	/**
+	 * Append new node after this.
+	 *
+	 * This a convenience function that calls addNode(node, 'after')
+	 *
+	 * @param {NodeData} node node definition
+	 * @returns {FancytreeNode} new node
+	 */
+	appendSibling: function(node){
+		return this.addNode(node, "after");
+	},
+	/**
+	 * Modify existing child nodes.
+	 *
+	 * @param {NodePatch} patch
+	 * @returns {$.Promise}
+	 * @see FancytreeNode#addChildren
+	 */
+	applyPatch: function(patch) {
+		// patch [key, null] means 'remove'
+		if(patch === null){
+			this.remove();
+			return _getResolvedPromise(this);
+		}
+		// TODO: make sure that root node is not collapsed or modified
+		// copy (most) attributes to node.ATTR or node.data.ATTR
+		var name, promise, v,
+			IGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global
+
+		for(name in patch){
+			v = patch[name];
+			if( !IGNORE_MAP[name] && !$.isFunction(v)){
+				if(NODE_ATTR_MAP[name]){
+					this[name] = v;
+				}else{
+					this.data[name] = v;
+				}
+			}
+		}
+		// Remove and/or create children
+		if(patch.hasOwnProperty("children")){
+			this.removeChildren();
+			if(patch.children){ // only if not null and not empty list
+				// TODO: addChildren instead?
+				this._setChildren(patch.children);
+			}
+			// TODO: how can we APPEND or INSERT child nodes?
+		}
+		if(this.isVisible()){
+			this.renderTitle();
+			this.renderStatus();
+		}
+		// Expand collapse (final step, since this may be async)
+		if(patch.hasOwnProperty("expanded")){
+			promise = this.setExpanded(patch.expanded);
+		}else{
+			promise = _getResolvedPromise(this);
+		}
+		return promise;
+	},
+	/** Collapse all sibling nodes.
+	 * @returns {$.Promise}
+	 */
+	collapseSiblings: function() {
+		return this.tree._callHook("nodeCollapseSiblings", this);
+	},
+	/** Copy this node as sibling or child of `node`.
+	 *
+	 * @param {FancytreeNode} node source node
+	 * @param {string} [mode=child] 'before' | 'after' | 'child'
+	 * @param {Function} [map] callback function(NodeData) that could modify the new node
+	 * @returns {FancytreeNode} new
+	 */
+	copyTo: function(node, mode, map) {
+		return node.addNode(this.toDict(true, map), mode);
+	},
+	/** Count direct and indirect children.
+	 *
+	 * @param {boolean} [deep=true] pass 'false' to only count direct children
+	 * @returns {int} number of child nodes
+	 */
+	countChildren: function(deep) {
+		var cl = this.children, i, l, n;
+		if( !cl ){
+			return 0;
+		}
+		n = cl.length;
+		if(deep !== false){
+			for(i=0, l=n; i<l; i++){
+				n += cl[i].countChildren();
+			}
+		}
+		return n;
+	},
+	// TODO: deactivate()
+	/** Write to browser console if debugLevel >= 2 (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	debug: function(msg){
+		if( this.tree.options.debugLevel >= 2 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("log", arguments);
+		}
+	},
+	/** Deprecated.
+	 * @deprecated since 2014-02-16. Use resetLazy() instead.
+	 */
+	discard: function(){
+		this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead.");
+		return this.resetLazy();
+	},
+
+	// TODO: expand(flag)
+
+	/**Find all nodes that match condition (excluding self).
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode[]} array of nodes (may be empty)
+	 */
+	findAll: function(match) {
+		match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);
+		var res = [];
+		this.visit(function(n){
+			if(match(n)){
+				res.push(n);
+			}
+		});
+		return res;
+	},
+	/**Find first node that matches condition (excluding self).
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode} matching node or null
+	 * @see FancytreeNode#findAll
+	 */
+	findFirst: function(match) {
+		match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);
+		var res = null;
+		this.visit(function(n){
+			if(match(n)){
+				res = n;
+				return false;
+			}
+		});
+		return res;
+	},
+	/* Apply selection state (internal use only) */
+	_changeSelectStatusAttrs: function (state) {
+		var changed = false;
+
+		switch(state){
+		case false:
+			changed = ( this.selected || this.partsel );
+			this.selected = false;
+			this.partsel = false;
+			break;
+		case true:
+			changed = ( !this.selected || !this.partsel );
+			this.selected = true;
+			this.partsel = true;
+			break;
+		case undefined:
+			changed = ( this.selected || !this.partsel );
+			this.selected = false;
+			this.partsel = true;
+			break;
+		default:
+			_assert(false, "invalid state: " + state);
+		}
+		// this.debug("fixSelection3AfterLoad() _changeSelectStatusAttrs()", state, changed);
+		if( changed ){
+			this.renderStatus();
+		}
+		return changed;
+	},
+	/**
+	 * Fix selection status, after this node was (de)selected in multi-hier mode.
+	 * This includes (de)selecting all children.
+	 */
+	fixSelection3AfterClick: function() {
+		var flag = this.isSelected();
+
+//		this.debug("fixSelection3AfterClick()");
+
+		this.visit(function(node){
+			node._changeSelectStatusAttrs(flag);
+		});
+		this.fixSelection3FromEndNodes();
+	},
+	/**
+	 * Fix selection status for multi-hier mode.
+	 * Only end-nodes are considered to update the descendants branch and parents.
+	 * Should be called after this node has loaded new children or after
+	 * children have been modified using the API.
+	 */
+	fixSelection3FromEndNodes: function() {
+//		this.debug("fixSelection3FromEndNodes()");
+		_assert(this.tree.options.selectMode === 3, "expected selectMode 3");
+
+		// Visit all end nodes and adjust their parent's `selected` and `partsel`
+		// attributes. Return selection state true, false, or undefined.
+		function _walk(node){
+			var i, l, child, s, state, allSelected,someSelected,
+				children = node.children;
+
+			if( children && children.length ){
+				// check all children recursively
+				allSelected = true;
+				someSelected = false;
+
+				for( i=0, l=children.length; i<l; i++ ){
+					child = children[i];
+					// the selection state of a node is not relevant; we need the end-nodes
+					s = _walk(child);
+					if( s !== false ) {
+						someSelected = true;
+					}
+					if( s !== true ) {
+						allSelected = false;
+					}
+				}
+				state = allSelected ? true : (someSelected ? undefined : false);
+			}else{
+				// This is an end-node: simply report the status
+//				state = ( node.unselectable ) ? undefined : !!node.selected;
+				state = !!node.selected;
+			}
+			node._changeSelectStatusAttrs(state);
+			return state;
+		}
+		_walk(this);
+
+		// Update parent's state
+		this.visitParents(function(node){
+			var i, l, child, state,
+				children = node.children,
+				allSelected = true,
+				someSelected = false;
+
+			for( i=0, l=children.length; i<l; i++ ){
+				child = children[i];
+				// When fixing the parents, we trust the sibling status (i.e.
+				// we don't recurse)
+				if( child.selected || child.partsel ) {
+					someSelected = true;
+				}
+				if( !child.unselectable && !child.selected ) {
+					allSelected = false;
+				}
+			}
+			state = allSelected ? true : (someSelected ? undefined : false);
+			node._changeSelectStatusAttrs(state);
+		});
+	},
+	// TODO: focus()
+	/**
+	 * Update node data. If dict contains 'children', then also replace
+	 * the hole sub tree.
+	 * @param {NodeData} dict
+	 *
+	 * @see FancytreeNode#addChildren
+	 * @see FancytreeNode#applyPatch
+	 */
+	fromDict: function(dict) {
+		// copy all other attributes to this.data.xxx
+		for(var name in dict){
+			if(NODE_ATTR_MAP[name]){
+				// node.NAME = dict.NAME
+				this[name] = dict[name];
+			}else if(name === "data"){
+				// node.data += dict.data
+				$.extend(this.data, dict.data);
+			}else if(!$.isFunction(dict[name]) && !NONE_NODE_DATA_MAP[name]){
+				// node.data.NAME = dict.NAME
+				this.data[name] = dict[name];
+			}
+		}
+		if(dict.children){
+			// recursively set children and render
+			this.removeChildren();
+			this.addChildren(dict.children);
+		}
+		this.renderTitle();
+/*
+		var children = dict.children;
+		if(children === undefined){
+			this.data = $.extend(this.data, dict);
+			this.render();
+			return;
+		}
+		dict = $.extend({}, dict);
+		dict.children = undefined;
+		this.data = $.extend(this.data, dict);
+		this.removeChildren();
+		this.addChild(children);
+*/
+	},
+	/** Return the list of child nodes (undefined for unexpanded lazy nodes).
+	 * @returns {FancytreeNode[] | undefined}
+	 */
+	getChildren: function() {
+		if(this.hasChildren() === undefined){ // TODO: only required for lazy nodes?
+			return undefined; // Lazy node: unloaded, currently loading, or load error
+		}
+		return this.children;
+	},
+	/** Return the first child node or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getFirstChild: function() {
+		return this.children ? this.children[0] : null;
+	},
+	/** Return the 0-based child index.
+	 * @returns {int}
+	 */
+	getIndex: function() {
+//		return this.parent.children.indexOf(this);
+		return $.inArray(this, this.parent.children); // indexOf doesn't work in IE7
+	},
+	/** Return the hierarchical child index (1-based, e.g. '3.2.4').
+	 * @returns {string}
+	 */
+	getIndexHier: function(separator) {
+		separator = separator || ".";
+		var res = [];
+		$.each(this.getParentList(false, true), function(i, o){
+			res.push(o.getIndex() + 1);
+		});
+		return res.join(separator);
+	},
+	/** Return the parent keys separated by options.keyPathSeparator, e.g. "id_1/id_17/id_32".
+	 * @param {boolean} [excludeSelf=false]
+	 * @returns {string}
+	 */
+	getKeyPath: function(excludeSelf) {
+		var path = [],
+			sep = this.tree.options.keyPathSeparator;
+		this.visitParents(function(n){
+			if(n.parent){
+				path.unshift(n.key);
+			}
+		}, !excludeSelf);
+		return sep + path.join(sep);
+	},
+	/** Return the last child of this node or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getLastChild: function() {
+		return this.children ? this.children[this.children.length - 1] : null;
+	},
+	/** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .
+	 * @returns {int}
+	 */
+	getLevel: function() {
+		var level = 0,
+			dtn = this.parent;
+		while( dtn ) {
+			level++;
+			dtn = dtn.parent;
+		}
+		return level;
+	},
+	/** Return the successor node (under the same parent) or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getNextSibling: function() {
+		// TODO: use indexOf, if available: (not in IE6)
+		if( this.parent ){
+			var i, l,
+				ac = this.parent.children;
+
+			for(i=0, l=ac.length-1; i<l; i++){ // up to length-2, so next(last) = null
+				if( ac[i] === this ){
+					return ac[i+1];
+				}
+			}
+		}
+		return null;
+	},
+	/** Return the parent node (null for the system root node).
+	 * @returns {FancytreeNode | null}
+	 */
+	getParent: function() {
+		// TODO: return null for top-level nodes?
+		return this.parent;
+	},
+	/** Return an array of all parent nodes (top-down).
+	 * @param {boolean} [includeRoot=false] Include the invisible system root node.
+	 * @param {boolean} [includeSelf=false] Include the node itself.
+	 * @returns {FancytreeNode[]}
+	 */
+	getParentList: function(includeRoot, includeSelf) {
+		var l = [],
+			dtn = includeSelf ? this : this.parent;
+		while( dtn ) {
+			if( includeRoot || dtn.parent ){
+				l.unshift(dtn);
+			}
+			dtn = dtn.parent;
+		}
+		return l;
+	},
+	/** Return the predecessor node (under the same parent) or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getPrevSibling: function() {
+		if( this.parent ){
+			var i, l,
+				ac = this.parent.children;
+
+			for(i=1, l=ac.length; i<l; i++){ // start with 1, so prev(first) = null
+				if( ac[i] === this ){
+					return ac[i-1];
+				}
+			}
+		}
+		return null;
+	},
+	/** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).
+	 * @returns {boolean | undefined}
+	 */
+	hasChildren: function() {
+		if(this.lazy){
+			if(this.children == null ){
+				// null or undefined: Not yet loaded
+				return undefined;
+			}else if(this.children.length === 0){
+				// Loaded, but response was empty
+				return false;
+			}else if(this.children.length === 1 && this.children[0].isStatusNode() ){
+				// Currently loading or load error
+				return undefined;
+			}
+			return true;
+		}
+		return !!( this.children && this.children.length );
+	},
+	/** Return true if node has keyboard focus.
+	 * @returns {boolean}
+	 */
+	hasFocus: function() {
+		return (this.tree.hasFocus() && this.tree.focusNode === this);
+	},
+	/** Write to browser console if debugLevel >= 1 (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	info: function(msg){
+		if( this.tree.options.debugLevel >= 1 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("info", arguments);
+		}
+	},
+	/** Return true if node is active (see also FancytreeNode#isSelected).
+	 * @returns {boolean}
+	 */
+	isActive: function() {
+		return (this.tree.activeNode === this);
+	},
+	/** Return true if node is a direct child of otherNode.
+	 * @param {FancytreeNode} otherNode
+	 * @returns {boolean}
+	 */
+	isChildOf: function(otherNode) {
+		return (this.parent && this.parent === otherNode);
+	},
+	/** Return true, if node is a direct or indirect sub node of otherNode.
+	 * @param {FancytreeNode} otherNode
+	 * @returns {boolean}
+	 */
+	isDescendantOf: function(otherNode) {
+		if(!otherNode || otherNode.tree !== this.tree){
+			return false;
+		}
+		var p = this.parent;
+		while( p ) {
+			if( p === otherNode ){
+				return true;
+			}
+			p = p.parent;
+		}
+		return false;
+	},
+	/** Return true if node is expanded.
+	 * @returns {boolean}
+	 */
+	isExpanded: function() {
+		return !!this.expanded;
+	},
+	/** Return true if node is the first node of its parent's children.
+	 * @returns {boolean}
+	 */
+	isFirstSibling: function() {
+		var p = this.parent;
+		return !p || p.children[0] === this;
+	},
+	/** Return true if node is a folder, i.e. has the node.folder attribute set.
+	 * @returns {boolean}
+	 */
+	isFolder: function() {
+		return !!this.folder;
+	},
+	/** Return true if node is the last node of its parent's children.
+	 * @returns {boolean}
+	 */
+	isLastSibling: function() {
+		var p = this.parent;
+		return !p || p.children[p.children.length-1] === this;
+	},
+	/** Return true if node is lazy (even if data was already loaded)
+	 * @returns {boolean}
+	 */
+	isLazy: function() {
+		return !!this.lazy;
+	},
+	/** Return true if node is lazy and loaded. For non-lazy nodes always return true.
+	 * @returns {boolean}
+	 */
+	isLoaded: function() {
+		return !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node
+	},
+	/** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.
+	 * @returns {boolean}
+	 */
+	isLoading: function() {
+		return !!this._isLoading;
+	},
+	/*
+	 * @deprecated since v2.4.0:  Use isRootNode() instead
+	 */
+	isRoot: function() {
+		return this.isRootNode();
+	},
+	/** Return true if this is the (invisible) system root node.
+	 * @returns {boolean}
+	 * @since 2.4
+	 */
+	isRootNode: function() {
+		return (this.tree.rootNode === this);
+	},
+	/** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).
+	 * @returns {boolean}
+	 */
+	isSelected: function() {
+		return !!this.selected;
+	},
+	/** Return true if this node is a temporarily generated system node like
+	 * 'loading', or 'error' (node.statusNodeType contains the type).
+	 * @returns {boolean}
+	 */
+	isStatusNode: function() {
+		return !!this.statusNodeType;
+	},
+	/** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.
+	 * @returns {boolean}
+	 * @since 2.4
+	 */
+	isTopLevel: function() {
+		return (this.tree.rootNode === this.parent);
+	},
+	/** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.
+	 * @returns {boolean}
+	 */
+	isUndefined: function() {
+		return this.hasChildren() === undefined; // also checks if the only child is a status node
+	},
+	/** Return true if all parent nodes are expanded. Note: this does not check
+	 * whether the node is scrolled into the visible part of the screen.
+	 * @returns {boolean}
+	 */
+	isVisible: function() {
+		var i, l,
+			parents = this.getParentList(false, false);
+
+		for(i=0, l=parents.length; i<l; i++){
+			if( ! parents[i].expanded ){ return false; }
+		}
+		return true;
+	},
+	/** Deprecated.
+	 * @deprecated since 2014-02-16: use load() instead.
+	 */
+	lazyLoad: function(discard) {
+		this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.");
+		return this.load(discard);
+	},
+	/**
+	 * Load all children of a lazy node if neccessary. The *expanded* state is maintained.
+	 * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before.
+	 * @returns {$.Promise}
+	 */
+	load: function(forceReload) {
+		var res, source,
+			that = this;
+
+		_assert( this.isLazy(), "load() requires a lazy node" );
+		// _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" );
+		if( !forceReload && !this.isUndefined() ) {
+			return _getResolvedPromise(this);
+		}
+		if( this.isLoaded() ){
+			this.resetLazy(); // also collapses
+		}
+		// This method is also called by setExpanded() and loadKeyPath(), so we
+		// have to avoid recursion.
+		source = this.tree._triggerNodeEvent("lazyLoad", this);
+		if( source === false ) { // #69
+			return _getResolvedPromise(this);
+		}
+		_assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+		res = this.tree._callHook("nodeLoadChildren", this, source);
+		if( this.expanded ) {
+			res.always(function(){
+				that.render();
+			});
+		}
+		return res;
+	},
+	/** Expand all parents and optionally scroll into visible area as neccessary.
+	 * Promise is resolved, when lazy loading and animations are done.
+	 * @param {object} [opts] passed to `setExpanded()`.
+	 *     Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
+	 * @returns {$.Promise}
+	 */
+	makeVisible: function(opts) {
+		var i,
+			that = this,
+			deferreds = [],
+			dfd = new $.Deferred(),
+			parents = this.getParentList(false, false),
+			len = parents.length,
+			effects = !(opts && opts.noAnimation === true),
+			scroll = !(opts && opts.scrollIntoView === false);
+
+		// Expand bottom-up, so only the top node is animated
+		for(i = len - 1; i >= 0; i--){
+			// that.debug("pushexpand" + parents[i]);
+			deferreds.push(parents[i].setExpanded(true, opts));
+		}
+		$.when.apply($, deferreds).done(function(){
+			// All expands have finished
+			// that.debug("expand DONE", scroll);
+			if( scroll ){
+				that.scrollIntoView(effects).done(function(){
+					// that.debug("scroll DONE");
+					dfd.resolve();
+				});
+			} else {
+				dfd.resolve();
+			}
+		});
+		return dfd.promise();
+	},
+	/** Move this node to targetNode.
+	 *  @param {FancytreeNode} targetNode
+	 *  @param {string} mode <pre>
+	 *      'child': append this node as last child of targetNode.
+	 *               This is the default. To be compatble with the D'n'd
+	 *               hitMode, we also accept 'over'.
+	 *      'before': add this node as sibling before targetNode.
+	 *      'after': add this node as sibling after targetNode.</pre>
+	 *  @param {function} [map] optional callback(FancytreeNode) to allow modifcations
+	 */
+	moveTo: function(targetNode, mode, map) {
+		if(mode === undefined || mode === "over"){
+			mode = "child";
+		}
+		var pos,
+			prevParent = this.parent,
+			targetParent = (mode === "child") ? targetNode : targetNode.parent;
+
+		if(this === targetNode){
+			return;
+		}else if( !this.parent  ){
+			throw "Cannot move system root";
+		}else if( targetParent.isDescendantOf(this) ){
+			throw "Cannot move a node to its own descendant";
+		}
+		// Unlink this node from current parent
+		if( this.parent.children.length === 1 ) {
+			if( this.parent === targetParent ){
+				return; // #258
+			}
+			this.parent.children = this.parent.lazy ? [] : null;
+			this.parent.expanded = false;
+		} else {
+			pos = $.inArray(this, this.parent.children);
+			_assert(pos >= 0, "invalid source parent");
+			this.parent.children.splice(pos, 1);
+		}
+		// Remove from source DOM parent
+//		if(this.parent.ul){
+//			this.parent.ul.removeChild(this.li);
+//		}
+
+		// Insert this node to target parent's child list
+		this.parent = targetParent;
+		if( targetParent.hasChildren() ) {
+			switch(mode) {
+			case "child":
+				// Append to existing target children
+				targetParent.children.push(this);
+				break;
+			case "before":
+				// Insert this node before target node
+				pos = $.inArray(targetNode, targetParent.children);
+				_assert(pos >= 0, "invalid target parent");
+				targetParent.children.splice(pos, 0, this);
+				break;
+			case "after":
+				// Insert this node after target node
+				pos = $.inArray(targetNode, targetParent.children);
+				_assert(pos >= 0, "invalid target parent");
+				targetParent.children.splice(pos+1, 0, this);
+				break;
+			default:
+				throw "Invalid mode " + mode;
+			}
+		} else {
+			targetParent.children = [ this ];
+		}
+		// Parent has no <ul> tag yet:
+//		if( !targetParent.ul ) {
+//			// This is the parent's first child: create UL tag
+//			// (Hidden, because it will be
+//			targetParent.ul = document.createElement("ul");
+//			targetParent.ul.style.display = "none";
+//			targetParent.li.appendChild(targetParent.ul);
+//		}
+//		// Issue 319: Add to target DOM parent (only if node was already rendered(expanded))
+//		if(this.li){
+//			targetParent.ul.appendChild(this.li);
+//		}^
+
+		// Let caller modify the nodes
+		if( map ){
+			targetNode.visit(map, true);
+		}
+		// Handle cross-tree moves
+		if( this.tree !== targetNode.tree ) {
+			// Fix node.tree for all source nodes
+//			_assert(false, "Cross-tree move is not yet implemented.");
+			this.warn("Cross-tree moveTo is experimantal!");
+			this.visit(function(n){
+				// TODO: fix selection state and activation, ...
+				n.tree = targetNode.tree;
+			}, true);
+		}
+
+		// A collaposed node won't re-render children, so we have to remove it manually
+		// if( !targetParent.expanded ){
+		//   prevParent.ul.removeChild(this.li);
+		// }
+
+		// Update HTML markup
+		if( !prevParent.isDescendantOf(targetParent)) {
+			prevParent.render();
+		}
+		if( !targetParent.isDescendantOf(prevParent) && targetParent !== prevParent) {
+			targetParent.render();
+		}
+		// TODO: fix selection state
+		// TODO: fix active state
+
+/*
+		var tree = this.tree;
+		var opts = tree.options;
+		var pers = tree.persistence;
+
+
+		// Always expand, if it's below minExpandLevel
+//		tree.logDebug ("%s._addChildNode(%o), l=%o", this, ftnode, ftnode.getLevel());
+		if ( opts.minExpandLevel >= ftnode.getLevel() ) {
+//			tree.logDebug ("Force expand for %o", ftnode);
+			this.bExpanded = true;
+		}
+
+		// In multi-hier mode, update the parents selection state
+		// DT issue #82: only if not initializing, because the children may not exist yet
+//		if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )
+//			ftnode._fixSelectionState();
+
+		// In multi-hier mode, update the parents selection state
+		if( ftnode.bSelected && opts.selectMode==3 ) {
+			var p = this;
+			while( p ) {
+				if( !p.hasSubSel )
+					p._setSubSel(true);
+				p = p.parent;
+			}
+		}
+		// render this node and the new child
+		if ( tree.bEnableUpdate )
+			this.render();
+
+		return ftnode;
+
+*/
+	},
+	/** Set focus relative to this node and optionally activate.
+	 *
+	 * @param {number} where The keyCode that would normally trigger this move,
+	 *		e.g. `$.ui.keyCode.LEFT` would collapse the node if it
+	 *      is expanded or move to the parent oterwise.
+	 * @param {boolean} [activate=true]
+	 * @returns {$.Promise}
+	 */
+	// navigate: function(where, activate) {
+	// 	console.time("navigate")
+	// 	this._navigate(where, activate)
+	// 	console.timeEnd("navigate")
+	// },
+	navigate: function(where, activate) {
+		var i, parents,
+			handled = true,
+			KC = $.ui.keyCode,
+			sib = null;
+
+		// Navigate to node
+		function _goto(n){
+			if( n ){
+				try { n.makeVisible(); } catch(e) {} // #272
+				// Node may still be hidden by a filter
+				if( ! $(n.span).is(":visible") ) {
+					n.debug("Navigate: skipping hidden node");
+					n.navigate(where, activate);
+					return;
+				}
+				return activate === false ? n.setFocus() : n.setActive();
+			}
+		}
+
+		switch( where ) {
+			case KC.BACKSPACE:
+				if( this.parent && this.parent.parent ) {
+					_goto(this.parent);
+				}
+				break;
+			case KC.LEFT:
+				if( this.expanded ) {
+					this.setExpanded(false);
+					_goto(this);
+				} else if( this.parent && this.parent.parent ) {
+					_goto(this.parent);
+				}
+				break;
+			case KC.RIGHT:
+				if( !this.expanded && (this.children || this.lazy) ) {
+					this.setExpanded();
+					_goto(this);
+				} else if( this.children && this.children.length ) {
+					_goto(this.children[0]);
+				}
+				break;
+			case KC.UP:
+				sib = this.getPrevSibling();
+				// #359: skip hidden sibling nodes, preventing a _goto() recursion
+				while( sib && !$(sib.span).is(":visible") ) {
+					sib = sib.getPrevSibling();
+				}
+				while( sib && sib.expanded && sib.children && sib.children.length ) {
+					sib = sib.children[sib.children.length - 1];
+				}
+				if( !sib && this.parent && this.parent.parent ){
+					sib = this.parent;
+				}
+				_goto(sib);
+				break;
+			case KC.DOWN:
+				if( this.expanded && this.children && this.children.length ) {
+					sib = this.children[0];
+				} else {
+					parents = this.getParentList(false, true);
+					for(i=parents.length-1; i>=0; i--) {
+						sib = parents[i].getNextSibling();
+						// #359: skip hidden sibling nodes, preventing a _goto() recursion
+						while( sib && !$(sib.span).is(":visible") ) {
+							sib = sib.getNextSibling();
+						}
+						if( sib ){ break; }
+					}
+				}
+				_goto(sib);
+				break;
+			default:
+				handled = false;
+		}
+	},
+	/**
+	 * Remove this node (not allowed for system root).
+	 */
+	remove: function() {
+		return this.parent.removeChild(this);
+	},
+	/**
+	 * Remove childNode from list of direct children.
+	 * @param {FancytreeNode} childNode
+	 */
+	removeChild: function(childNode) {
+		return this.tree._callHook("nodeRemoveChild", this, childNode);
+	},
+	/**
+	 * Remove all child nodes and descendents. This converts the node into a leaf.<br>
+	 * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()
+	 * in order to trigger lazyLoad on next expand.
+	 */
+	removeChildren: function() {
+		return this.tree._callHook("nodeRemoveChildren", this);
+	},
+	/**
+	 * This method renders and updates all HTML markup that is required
+	 * to display this node in its current state.<br>
+	 * Note:
+	 * <ul>
+	 * <li>It should only be neccessary to call this method after the node object
+	 *     was modified by direct access to its properties, because the common
+	 *     API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)
+	 *     already handle this.
+	 * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}
+	 *     are implied. If changes are more local, calling only renderTitle() or
+	 *     renderStatus() may be sufficient and faster.
+	 * <li>If a node was created/removed, node.render() must be called <i>on the parent</i>.
+	 * </ul>
+	 *
+	 * @param {boolean} [force=false] re-render, even if html markup was already created
+	 * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+	 */
+	render: function(force, deep) {
+		return this.tree._callHook("nodeRender", this, force, deep);
+	},
+	/** Create HTML markup for the node's outer &lt;span> (expander, checkbox, icon, and title).
+	 * Implies {@link FancytreeNode#renderStatus}.
+	 * @see Fancytree_Hooks#nodeRenderTitle
+	 */
+	renderTitle: function() {
+		return this.tree._callHook("nodeRenderTitle", this);
+	},
+	/** Update element's CSS classes according to node state.
+	 * @see Fancytree_Hooks#nodeRenderStatus
+	 */
+	renderStatus: function() {
+		return this.tree._callHook("nodeRenderStatus", this);
+	},
+	/**
+	 * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
+	 * event is triggered on next expand.
+	 */
+	resetLazy: function() {
+		this.removeChildren();
+		this.expanded = false;
+		this.lazy = true;
+		this.children = undefined;
+		this.renderStatus();
+	},
+	/** Schedule activity for delayed execution (cancel any pending request).
+	 *  scheduleAction('cancel') will only cancel a pending request (if any).
+	 * @param {string} mode
+	 * @param {number} ms
+	 */
+	scheduleAction: function(mode, ms) {
+		if( this.tree.timer ) {
+			clearTimeout(this.tree.timer);
+//            this.tree.debug("clearTimeout(%o)", this.tree.timer);
+		}
+		this.tree.timer = null;
+		var self = this; // required for closures
+		switch (mode) {
+		case "cancel":
+			// Simply made sure that timer was cleared
+			break;
+		case "expand":
+			this.tree.timer = setTimeout(function(){
+				self.tree.debug("setTimeout: trigger expand");
+				self.setExpanded(true);
+			}, ms);
+			break;
+		case "activate":
+			this.tree.timer = setTimeout(function(){
+				self.tree.debug("setTimeout: trigger activate");
+				self.setActive(true);
+			}, ms);
+			break;
+		default:
+			throw "Invalid mode " + mode;
+		}
+//        this.tree.debug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer);
+	},
+	/**
+	 *
+	 * @param {boolean | PlainObject} [effects=false] animation options.
+	 * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in
+	 *     any case, even if `this` is outside the scroll pane.
+	 * @returns {$.Promise}
+	 */
+	scrollIntoView: function(effects, options) {
+		if( options !== undefined && _isNode(options) ) {
+			this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.");
+			options = {topNode: options};
+		}
+		// this.$scrollParent = (this.options.scrollParent === "auto") ? $ul.scrollParent() : $(this.options.scrollParent);
+		// this.$scrollParent = this.$scrollParent.length ? this.$scrollParent || this.$container;
+
+		var topNodeY, nodeY, horzScrollbarHeight, containerOffsetTop,
+			opts = $.extend({
+				effects: (effects === true) ? {duration: 200, queue: false} : effects,
+				scrollOfs: this.tree.options.scrollOfs,
+				scrollParent: this.tree.options.scrollParent || this.tree.$container,
+				topNode: null
+			}, options),
+			dfd = new $.Deferred(),
+			that = this,
+			nodeHeight = $(this.span).height(),
+			$container = $(opts.scrollParent),
+			topOfs = opts.scrollOfs.top || 0,
+			bottomOfs = opts.scrollOfs.bottom || 0,
+			containerHeight = $container.height(),// - topOfs - bottomOfs,
+			scrollTop = $container.scrollTop(),
+			$animateTarget = $container,
+			isParentWindow = $container[0] === window,
+			topNode = opts.topNode || null,
+			newScrollTop = null;
+
+		// this.debug("scrollIntoView(), scrollTop=", scrollTop, opts.scrollOfs);
+//		_assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets
+		if( !$(this.span).is(":visible") ) {
+			// We cannot calc offsets for hidden elements
+			this.warn("scrollIntoView(): node is invisible.");
+			return _getResolvedPromise();
+		}
+		if( isParentWindow ) {
+			nodeY = $(this.span).offset().top;
+			topNodeY = (topNode && topNode.span) ? $(topNode.span).offset().top : 0;
+			$animateTarget = $("html,body");
+
+		} else {
+			_assert($container[0] !== document && $container[0] !== document.body, "scrollParent should be an simple element or `window`, not document or body.");
+
+			containerOffsetTop = $container.offset().top,
+			nodeY = $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent
+			topNodeY = topNode ? $(topNode.span).offset().top - containerOffsetTop  + scrollTop : 0;
+			horzScrollbarHeight = Math.max(0, ($container.innerHeight() - $container[0].clientHeight));
+			containerHeight -= horzScrollbarHeight;
+		}
+
+		// this.debug("    scrollIntoView(), nodeY=", nodeY, "containerHeight=", containerHeight);
+		if( nodeY < (scrollTop + topOfs) ){
+			// Node is above visible container area
+			newScrollTop = nodeY - topOfs;
+			// this.debug("    scrollIntoView(), UPPER newScrollTop=", newScrollTop);
+
+		}else if((nodeY + nodeHeight) > (scrollTop + containerHeight - bottomOfs)){
+			newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;
+			// this.debug("    scrollIntoView(), LOWER newScrollTop=", newScrollTop);
+			// If a topNode was passed, make sure that it is never scrolled
+			// outside the upper border
+			if(topNode){
+				_assert(topNode.isRootNode() || $(topNode.span).is(":visible"), "topNode must be visible");
+				if( topNodeY < newScrollTop ){
+					newScrollTop = topNodeY - topOfs;
+					// this.debug("    scrollIntoView(), TOP newScrollTop=", newScrollTop);
+				}
+			}
+		}
+
+		if(newScrollTop !== null){
+			// this.debug("    scrollIntoView(), SET newScrollTop=", newScrollTop);
+			if(opts.effects){
+				opts.effects.complete = function(){
+					dfd.resolveWith(that);
+				};
+				$animateTarget.stop(true).animate({
+					scrollTop: newScrollTop
+				}, opts.effects);
+			}else{
+				$animateTarget[0].scrollTop = newScrollTop;
+				dfd.resolveWith(this);
+			}
+		}else{
+			dfd.resolveWith(this);
+		}
+		return dfd.promise();
+	},
+
+	/**Activate this node.
+	 * @param {boolean} [flag=true] pass false to deactivate
+	 * @param {object} [opts] additional options. Defaults to {noEvents: false}
+	 * @returns {$.Promise}
+	 */
+	setActive: function(flag, opts){
+		return this.tree._callHook("nodeSetActive", this, flag, opts);
+	},
+	/**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.
+	 * @param {boolean} [flag=true] pass false to collapse
+	 * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+	 * @returns {$.Promise}
+	 */
+	setExpanded: function(flag, opts){
+		return this.tree._callHook("nodeSetExpanded", this, flag, opts);
+	},
+	/**Set keyboard focus to this node.
+	 * @param {boolean} [flag=true] pass false to blur
+	 * @see Fancytree#setFocus
+	 */
+	setFocus: function(flag){
+		return this.tree._callHook("nodeSetFocus", this, flag);
+	},
+	/**Select this node, i.e. check the checkbox.
+	 * @param {boolean} [flag=true] pass false to deselect
+	 */
+	setSelected: function(flag){
+		return this.tree._callHook("nodeSetSelected", this, flag);
+	},
+	/**Mark a lazy node as 'error', 'loading', or 'ok'.
+	 * @param {string} status 'error', 'ok'
+	 * @param {string} [message]
+	 * @param {string} [details]
+	 */
+	setStatus: function(status, message, details){
+		return this.tree._callHook("nodeSetStatus", this, status, message, details);
+	},
+	/**Rename this node.
+	 * @param {string} title
+	 */
+	setTitle: function(title){
+		this.title = title;
+		this.renderTitle();
+	},
+	/**Sort child list by title.
+	 * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).
+	 * @param {boolean} [deep=false] pass true to sort all descendant nodes
+	 */
+	sortChildren: function(cmp, deep) {
+		var i,l,
+			cl = this.children;
+
+		if( !cl ){
+			return;
+		}
+		cmp = cmp || function(a, b) {
+			var x = a.title.toLowerCase(),
+				y = b.title.toLowerCase();
+			return x === y ? 0 : x > y ? 1 : -1;
+			};
+		cl.sort(cmp);
+		if( deep ){
+			for(i=0, l=cl.length; i<l; i++){
+				if( cl[i].children ){
+					cl[i].sortChildren(cmp, "$norender$");
+				}
+			}
+		}
+		if( deep !== "$norender$" ){
+			this.render();
+		}
+	},
+	/** Convert node (or whole branch) into a plain object.
+	 *
+	 * The result is compatible with node.addChildren().
+	 *
+	 * @param {boolean} [recursive=false] include child nodes
+	 * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications
+	 * @returns {NodeData}
+	 */
+	toDict: function(recursive, callback) {
+		var i, l, node,
+			dict = {},
+			self = this;
+
+		$.each(NODE_ATTRS, function(i, a){
+			if(self[a] || self[a] === false){
+				dict[a] = self[a];
+			}
+		});
+		if(!$.isEmptyObject(this.data)){
+			dict.data = $.extend({}, this.data);
+			if($.isEmptyObject(dict.data)){
+				delete dict.data;
+			}
+		}
+		if( callback ){
+			callback(dict, self);
+		}
+		if( recursive ) {
+			if(this.hasChildren()){
+				dict.children = [];
+				for(i=0, l=this.children.length; i<l; i++ ){
+					node = this.children[i];
+					if( !node.isStatusNode() ){
+						dict.children.push(node.toDict(true, callback));
+					}
+				}
+			}else{
+//                dict.children = null;
+			}
+		}
+		return dict;
+	},
+	/** Flip expanded status.  */
+	toggleExpanded: function(){
+		return this.tree._callHook("nodeToggleExpanded", this);
+	},
+	/** Flip selection status.  */
+	toggleSelected: function(){
+		return this.tree._callHook("nodeToggleSelected", this);
+	},
+	toString: function() {
+		return "<FancytreeNode(#" + this.key + ", '" + this.title + "')>";
+	},
+	/** Call fn(node) for all child nodes.<br>
+	 * Stop iteration, if fn() returns false. Skip current branch, if fn() returns "skip".<br>
+	 * Return false if iteration was stopped.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and
+	 *     its children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {boolean}
+	 */
+	visit: function(fn, includeSelf) {
+		var i, l,
+			res = true,
+			children = this.children;
+
+		if( includeSelf === true ) {
+			res = fn(this);
+			if( res === false || res === "skip" ){
+				return res;
+			}
+		}
+		if(children){
+			for(i=0, l=children.length; i<l; i++){
+				res = children[i].visit(fn, true);
+				if( res === false ){
+					break;
+				}
+			}
+		}
+		return res;
+	},
+	/** Call fn(node) for all child nodes and recursively load lazy children.<br>
+	 * <b>Note:</b> If you need this method, you probably should consider to review
+	 * your architecture! Recursivley loading nodes is a perfect way for lazy
+	 * programmers to flood the server with requests ;-)
+	 *
+	 * @param {function} [fn] optional callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and
+	 *     its children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {$.Promise}
+	 * @since 2.4
+	 */
+	visitAndLoad: function(fn, includeSelf, _recursion) {
+		var dfd, res, loaders,
+			node = this;
+
+		// node.debug("visitAndLoad");
+		if( fn && includeSelf === true ) {
+			res = fn(node);
+			if( res === false || res === "skip" ) {
+				return _recursion ? res : _getResolvedPromise();
+			}
+		}
+		if( !node.children && !node.lazy ) {
+			return _getResolvedPromise();
+		}
+		dfd = new $.Deferred();
+		loaders = [];
+		// node.debug("load()...");
+		node.load().done(function(){
+			// node.debug("load()... done.");
+			for(var i=0, l=node.children.length; i<l; i++){
+				res = node.children[i].visitAndLoad(fn, true, true);
+				if( res === false ) {
+					dfd.reject();
+					break;
+				} else if ( res !== "skip" ) {
+					loaders.push(res); // Add promise to the list
+				}
+			}
+			$.when.apply(this, loaders).then(function(){
+				dfd.resolve();
+			});
+		});
+		return dfd.promise();
+	},
+	/** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
+	 * Stop iteration, if fn() returns false.<br>
+	 * Return false if iteration was stopped.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {boolean}
+	 */
+	visitParents: function(fn, includeSelf) {
+		// Visit parent nodes (bottom up)
+		if(includeSelf && fn(this) === false){
+			return false;
+		}
+		var p = this.parent;
+		while( p ) {
+			if(fn(p) === false){
+				return false;
+			}
+			p = p.parent;
+		}
+		return true;
+	},
+	/** Write warning to browser console (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	warn: function(msg){
+		Array.prototype.unshift.call(arguments, this.toString());
+		consoleApply("warn", arguments);
+	}
+};
+
+
+/* *****************************************************************************
+ * Fancytree
+ */
+/**
+ * Construct a new tree object.
+ *
+ * @class Fancytree
+ * @classdesc The controller behind a fancytree.
+ * This class also contains 'hook methods': see {@link Fancytree_Hooks}.
+ *
+ * @param {Widget} widget
+ *
+ * @property {string} _id Automatically generated unique tree instance ID, e.g. "1".
+ * @property {string} _ns Automatically generated unique tree namespace, e.g. ".fancytree-1".
+ * @property {FancytreeNode} activeNode Currently active node or null.
+ * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.
+ *     Typically "li", but "tr" for table extension.
+ * @property {jQueryObject} $container Outer &lt;ul> element (or &lt;table> element for ext-table).
+ * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)
+ * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.
+ * @property {object} ext Hash of all active plugin instances.
+ * @property {FancytreeNode} focusNode Currently focused node or null.
+ * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)
+ * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.
+ *     Typically "li", but "tr" for table extension.
+ * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.
+ * @property {FancytreeNode} rootNode Invisible system root node.
+ * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.
+ *     Typically "span", but "tr" for table extension.
+ * @property {object} widget Base widget instance.
+ */
+function Fancytree(widget) {
+	this.widget = widget;
+	this.$div = widget.element;
+	this.options = widget.options;
+	if( this.options ) {
+		if(  $.isFunction(this.options.lazyload ) && !$.isFunction(this.options.lazyLoad) ) {
+			this.options.lazyLoad = function() {
+				FT.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead.");
+				return widget.options.lazyload.apply(this, arguments);
+			};
+		}
+		if( $.isFunction(this.options.loaderror) ) {
+			$.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead.");
+		}
+		if( this.options.fx !== undefined ) {
+			FT.warn("The 'fx' options was replaced by 'toggleEffect' since 2014-11-30.");
+		}
+	}
+	this.ext = {}; // Active extension instances
+	// allow to init tree.data.foo from <div data-foo=''>
+	this.data = _getElementDataAsDict(this.$div);
+	// TODO: use widget.uuid instead?
+	this._id = $.ui.fancytree._nextId++;
+	// TODO: use widget.eventNamespace instead?
+	this._ns = ".fancytree-" + this._id; // append for namespaced events
+	this.activeNode = null;
+	this.focusNode = null;
+	this._hasFocus = null;
+	this.lastSelectedNode = null;
+	this.systemFocusElement = null;
+	this.lastQuicksearchTerm = "";
+	this.lastQuicksearchTime = 0;
+
+	this.statusClassPropName = "span";
+	this.ariaPropName = "li";
+	this.nodeContainerAttrName = "li";
+
+	// Remove previous markup if any
+	this.$div.find(">ul.fancytree-container").remove();
+
+	// Create a node without parent.
+	var fakeParent = { tree: this },
+		$ul;
+	this.rootNode = new FancytreeNode(fakeParent, {
+		title: "root",
+		key: "root_" + this._id,
+		children: null,
+		expanded: true
+	});
+	this.rootNode.parent = null;
+
+	// Create root markup
+	$ul = $("<ul>", {
+		"class": "ui-fancytree fancytree-container fancytree-plain"
+	}).appendTo(this.$div);
+	this.$container = $ul;
+	this.rootNode.ul = $ul[0];
+
+	if(this.options.debugLevel == null){
+		this.options.debugLevel = FT.debugLevel;
+	}
+	// Add container to the TAB chain
+	// See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+	this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1");
+	if(this.options.aria){
+		this.$container
+			.attr("role", "tree")
+			.attr("aria-multiselectable", true);
+	}
+}
+
+
+Fancytree.prototype = /** @lends Fancytree# */{
+	/* Return a context object that can be re-used for _callHook().
+	 * @param {Fancytree | FancytreeNode | EventData} obj
+	 * @param {Event} originalEvent
+	 * @param {Object} extra
+	 * @returns {EventData}
+	 */
+	_makeHookContext: function(obj, originalEvent, extra) {
+		var ctx, tree;
+		if(obj.node !== undefined){
+			// obj is already a context object
+			if(originalEvent && obj.originalEvent !== originalEvent){
+				$.error("invalid args");
+			}
+			ctx = obj;
+		}else if(obj.tree){
+			// obj is a FancytreeNode
+			tree = obj.tree;
+			ctx = { node: obj, tree: tree, widget: tree.widget, options: tree.widget.options, originalEvent: originalEvent };
+		}else if(obj.widget){
+			// obj is a Fancytree
+			ctx = { node: null, tree: obj, widget: obj.widget, options: obj.widget.options, originalEvent: originalEvent };
+		}else{
+			$.error("invalid args");
+		}
+		if(extra){
+			$.extend(ctx, extra);
+		}
+		return ctx;
+	},
+	/* Trigger a hook function: funcName(ctx, [...]).
+	 *
+	 * @param {string} funcName
+	 * @param {Fancytree|FancytreeNode|EventData} contextObject
+	 * @param {any}  [_extraArgs] optional additional arguments
+	 * @returns {any}
+	 */
+	_callHook: function(funcName, contextObject, _extraArgs) {
+		var ctx = this._makeHookContext(contextObject),
+			fn = this[funcName],
+			args = Array.prototype.slice.call(arguments, 2);
+		if(!$.isFunction(fn)){
+			$.error("_callHook('" + funcName + "') is not a function");
+		}
+		args.unshift(ctx);
+//		this.debug("_hook", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);
+		return fn.apply(this, args);
+	},
+	/* Check if current extensions dependencies are met and throw an error if not.
+	 *
+	 * This method may be called inside the `treeInit` hook for custom extensions.
+	 *
+	 * @param {string} extension name of the required extension
+	 * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present
+	 * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)
+	 * @param {string} [message] optional error message (defaults to a descriptve error message)
+	 */
+	_requireExtension: function(name, required, before, message) {
+		before = !!before;
+		var thisName = this._local.name,
+			extList = this.options.extensions,
+			isBefore = $.inArray(name, extList) < $.inArray(thisName, extList),
+			isMissing = required && this.ext[name] == null,
+			badOrder = !isMissing && before != null && (before !== isBefore);
+
+		_assert(thisName && thisName !== name, "invalid or same name");
+
+		if( isMissing || badOrder ){
+			if( !message ){
+				if( isMissing || required ){
+					message = "'" + thisName + "' extension requires '" + name + "'";
+					if( badOrder ){
+						message += " to be registered " + (before ? "before" : "after") + " itself";
+					}
+				}else{
+					message = "If used together, `" + name + "` must be registered " + (before ? "before" : "after") + " `" + thisName + "`";
+				}
+			}
+			$.error(message);
+			return false;
+		}
+		return true;
+	},
+	/** Activate node with a given key and fire focus and activate events.
+	 *
+	 * A prevously activated node will be deactivated.
+	 * If activeVisible option is set, all parents will be expanded as necessary.
+	 * Pass key = false, to deactivate the current node only.
+	 * @param {string} key
+	 * @returns {FancytreeNode} activated node (null, if not found)
+	 */
+	activateKey: function(key) {
+		var node = this.getNodeByKey(key);
+		if(node){
+			node.setActive();
+		}else if(this.activeNode){
+			this.activeNode.setActive(false);
+		}
+		return node;
+	},
+	/** (experimental)
+	 *
+	 * @param {Array} patchList array of [key, NodePatch] arrays
+	 * @returns {$.Promise} resolved, when all patches have been applied
+	 * @see TreePatch
+	 */
+	applyPatch: function(patchList) {
+		var dfd, i, p2, key, patch, node,
+			patchCount = patchList.length,
+			deferredList = [];
+
+		for(i=0; i<patchCount; i++){
+			p2 = patchList[i];
+			_assert(p2.length === 2, "patchList must be an array of length-2-arrays");
+			key = p2[0];
+			patch = p2[1];
+			node = (key === null) ? this.rootNode : this.getNodeByKey(key);
+			if(node){
+				dfd = new $.Deferred();
+				deferredList.push(dfd);
+				node.applyPatch(patch).always(_makeResolveFunc(dfd, node));
+			}else{
+				this.warn("could not find node with key '" + key + "'");
+			}
+		}
+		// Return a promise that is resolved, when ALL patches were applied
+		return $.when.apply($, deferredList).promise();
+	},
+	/* TODO: implement in dnd extension
+	cancelDrag: function() {
+		var dd = $.ui.ddmanager.current;
+		if(dd){
+			dd.cancel();
+		}
+	},
+   */
+   /** Return the number of nodes.
+	* @returns {integer}
+	*/
+	count: function() {
+		return this.rootNode.countChildren();
+	},
+	/** Write to browser console if debugLevel >= 2 (prepending tree name)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	debug: function(msg){
+		if( this.options.debugLevel >= 2 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("log", arguments);
+		}
+	},
+	// TODO: disable()
+	// TODO: enable()
+	// TODO: enableUpdate()
+
+	/**Find all nodes that matches condition.
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode[]} array of nodes (may be empty)
+	 * @see FancytreeNode#findAll
+	 * @since 2.12
+	 */
+	findAll: function(match) {
+		return this.rootNode.findAll(match);
+	},
+	/**Find first node that matches condition.
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode} matching node or null
+	 * @see FancytreeNode#findFirst
+	 * @since 2.12
+	 */
+	findFirst: function(match) {
+		return this.rootNode.findFirst(match);
+	},
+	/** Find the next visible node that starts with `match`, starting at `startNode`
+	 * and wrap-around at the end.
+	 *
+	 * @param {string|function} match
+	 * @param {FancytreeNode} [startNode] defaults to first node
+	 * @returns {FancytreeNode} matching node or null
+	 */
+	findNextNode: function(match, startNode, visibleOnly) {
+		var stopNode = null,
+			parentChildren = startNode.parent.children,
+			matchingNode = null,
+			walkVisible = function(parent, idx, fn) {
+				var i, grandParent,
+					parentChildren = parent.children,
+					siblingCount = parentChildren.length,
+					node = parentChildren[idx];
+				// visit node itself
+				if( node && fn(node) === false ) {
+					return false;
+				}
+				// visit descendants
+				if( node && node.children && node.expanded ) {
+					if( walkVisible(node, 0, fn) === false ) {
+						return false;
+					}
+				}
+				// visit subsequent siblings
+				for( i = idx + 1; i < siblingCount; i++ ) {
+					if( walkVisible(parent, i, fn) === false ) {
+						return false;
+					}
+				}
+				// visit parent's subsequent siblings
+				grandParent = parent.parent;
+				if( grandParent ) {
+					return walkVisible(grandParent, grandParent.children.indexOf(parent) + 1, fn);
+				} else {
+					// wrap-around: restart with first node
+					return walkVisible(parent, 0, fn);
+				}
+			};
+
+		match = (typeof match === "string") ? _makeNodeTitleStartMatcher(match) : match;
+		startNode = startNode || this.getFirstChild();
+
+		walkVisible(startNode.parent, parentChildren.indexOf(startNode), function(node){
+			// Stop iteration if we see the start node a second time
+			if( node === stopNode ) {
+				return false;
+			}
+			stopNode = stopNode || node;
+			// Ignore nodes hidden by a filter
+			if( ! $(node.span).is(":visible") ) {
+				node.debug("quicksearch: skipping hidden node");
+				return;
+			}
+			// Test if we found a match, but search for a second match if this
+			// was the currently active node
+			if( match(node) ) {
+				// node.debug("quicksearch match " + node.title, startNode);
+				matchingNode = node;
+				if( matchingNode !== startNode ) {
+					return false;
+				}
+			}
+		});
+		return matchingNode;
+	},
+	// TODO: fromDict
+	/**
+	 * Generate INPUT elements that can be submitted with html forms.
+	 *
+	 * In selectMode 3 only the topmost selected nodes are considered, unless
+	 * `opts.stopOnParents: false` is passed.
+	 *
+	 * @param {boolean | string} [selected=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID[]')
+	 * @param {boolean | string} [active=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID_active')
+	 * @param {object} [opts] default { stopOnParents: true }
+	 */
+	generateFormElements: function(selected, active, opts) {
+		// TODO: test case
+		opts = opts || {};
+
+		var nodeList,
+			selectedName = (typeof selected === "string") ? selected : "ft_" + this._id + "[]",
+			activeName = (typeof active === "string") ? active : "ft_" + this._id + "_active",
+			id = "fancytree_result_" + this._id,
+			$result = $("#" + id),
+			stopOnParents = this.options.selectMode === 3 && opts.stopOnParents !== false;
+
+		if($result.length){
+			$result.empty();
+		}else{
+			$result = $("<div>", {
+				id: id
+			}).hide().insertAfter(this.$container);
+		}
+		if(selected !== false){
+			nodeList = this.getSelectedNodes(stopOnParents);
+			$.each(nodeList, function(idx, node){
+				$result.append($("<input>", {
+					type: "checkbox",
+					name: selectedName,
+					value: node.key,
+					checked: true
+				}));
+			});
+		}
+		if(active !== false && this.activeNode){
+			$result.append($("<input>", {
+				type: "radio",
+				name: activeName,
+				value: this.activeNode.key,
+				checked: true
+			}));
+		}
+	},
+	/**
+	 * Return the currently active node or null.
+	 * @returns {FancytreeNode}
+	 */
+	getActiveNode: function() {
+		return this.activeNode;
+	},
+	/** Return the first top level node if any (not the invisible root node).
+	 * @returns {FancytreeNode | null}
+	 */
+	getFirstChild: function() {
+		return this.rootNode.getFirstChild();
+	},
+	/**
+	 * Return node that has keyboard focus or null.
+	 * @returns {FancytreeNode}
+	 */
+	getFocusNode: function() {
+		return this.focusNode;
+	},
+	/**
+	 * Return node with a given key or null if not found.
+	 * @param {string} key
+	 * @param {FancytreeNode} [searchRoot] only search below this node
+	 * @returns {FancytreeNode | null}
+	 */
+	getNodeByKey: function(key, searchRoot) {
+		// Search the DOM by element ID (assuming this is faster than traversing all nodes).
+		// $("#...") has problems, if the key contains '.', so we use getElementById()
+		var el, match;
+		if(!searchRoot){
+			el = document.getElementById(this.options.idPrefix + key);
+			if( el ){
+				return el.ftnode ? el.ftnode : null;
+			}
+		}
+		// Not found in the DOM, but still may be in an unrendered part of tree
+		// TODO: optimize with specialized loop
+		// TODO: consider keyMap?
+		searchRoot = searchRoot || this.rootNode;
+		match = null;
+		searchRoot.visit(function(node){
+//            window.console.log("getNodeByKey(" + key + "): ", node.key);
+			if(node.key === key) {
+				match = node;
+				return false;
+			}
+		}, true);
+		return match;
+	},
+	/** Return the invisible system root node.
+	 * @returns {FancytreeNode}
+	 */
+	getRootNode: function() {
+		return this.rootNode;
+	},
+	/**
+	 * Return an array of selected nodes.
+	 * @param {boolean} [stopOnParents=false] only return the topmost selected
+	 *     node (useful with selectMode 3)
+	 * @returns {FancytreeNode[]}
+	 */
+	getSelectedNodes: function(stopOnParents) {
+		var nodeList = [];
+		this.rootNode.visit(function(node){
+			if( node.selected ) {
+				nodeList.push(node);
+				if( stopOnParents === true ){
+					return "skip"; // stop processing this branch
+				}
+			}
+		});
+		return nodeList;
+	},
+	/** Return true if the tree control has keyboard focus
+	 * @returns {boolean}
+	 */
+	hasFocus: function(){
+		return !!this._hasFocus;
+	},
+	/** Write to browser console if debugLevel >= 1 (prepending tree name)
+	 * @param {*} msg string or object or array of such
+	 */
+	info: function(msg){
+		if( this.options.debugLevel >= 1 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("info", arguments);
+		}
+	},
+/*
+	TODO: isInitializing: function() {
+		return ( this.phase=="init" || this.phase=="postInit" );
+	},
+	TODO: isReloading: function() {
+		return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
+	},
+	TODO: isUserEvent: function() {
+		return ( this.phase=="userEvent" );
+	},
+*/
+
+	/**
+	 * Make sure that a node with a given ID is loaded, by traversing - and
+	 * loading - its parents. This method is ment for lazy hierarchies.
+	 * A callback is executed for every node as we go.
+	 * @example
+	 * tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){
+	 *   if(status === "loaded") {
+	 *     console.log("loaded intermiediate node " + node);
+	 *   }else if(status === "ok") {
+	 *     node.activate();
+	 *   }
+	 * });
+	 *
+	 * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')
+	 * @param {function} callback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error')
+	 * @returns {$.Promise}
+	 */
+	loadKeyPath: function(keyPathList, callback, _rootNode) {
+		var deferredList, dfd, i, path, key, loadMap, node, root, segList,
+			sep = this.options.keyPathSeparator,
+			self = this;
+
+		if(!$.isArray(keyPathList)){
+			keyPathList = [keyPathList];
+		}
+		// Pass 1: handle all path segments for nodes that are already loaded
+		// Collect distinct top-most lazy nodes in a map
+		loadMap = {};
+
+		for(i=0; i<keyPathList.length; i++){
+			root = _rootNode || this.rootNode;
+			path = keyPathList[i];
+			// strip leading slash
+			if(path.charAt(0) === sep){
+				path = path.substr(1);
+			}
+			// traverse and strip keys, until we hit a lazy, unloaded node
+			segList = path.split(sep);
+			while(segList.length){
+				key = segList.shift();
+//                node = _findDirectChild(root, key);
+				node = root._findDirectChild(key);
+				if(!node){
+					this.warn("loadKeyPath: key not found: " + key + " (parent: " + root + ")");
+					callback.call(this, key, "error");
+					break;
+				}else if(segList.length === 0){
+					callback.call(this, node, "ok");
+					break;
+				}else if(!node.lazy || (node.hasChildren() !== undefined )){
+					callback.call(this, node, "loaded");
+					root = node;
+				}else{
+					callback.call(this, node, "loaded");
+//                    segList.unshift(key);
+					if(loadMap[key]){
+						loadMap[key].push(segList.join(sep));
+					}else{
+						loadMap[key] = [segList.join(sep)];
+					}
+					break;
+				}
+			}
+		}
+//        alert("loadKeyPath: loadMap=" + JSON.stringify(loadMap));
+		// Now load all lazy nodes and continue itearation for remaining paths
+		deferredList = [];
+		// Avoid jshint warning 'Don't make functions within a loop.':
+		function __lazyload(key, node, dfd){
+			callback.call(self, node, "loading");
+			node.load().done(function(){
+				self.loadKeyPath.call(self, loadMap[key], callback, node).always(_makeResolveFunc(dfd, self));
+			}).fail(function(errMsg){
+				self.warn("loadKeyPath: error loading: " + key + " (parent: " + root + ")");
+				callback.call(self, node, "error");
+				dfd.reject();
+			});
+		}
+		for(key in loadMap){
+			node = root._findDirectChild(key);
+//            alert("loadKeyPath: lazy node(" + key + ") = " + node);
+			dfd = new $.Deferred();
+			deferredList.push(dfd);
+			__lazyload(key, node, dfd);
+		}
+		// Return a promise that is resolved, when ALL paths were loaded
+		return $.when.apply($, deferredList).promise();
+	},
+	/** Re-fire beforeActivate and activate events. */
+	reactivate: function(setFocus) {
+		var res,
+			node = this.activeNode;
+
+		if( !node ) {
+			return _getResolvedPromise();
+		}
+		this.activeNode = null; // Force re-activating
+		res = node.setActive();
+		if( setFocus ){
+			node.setFocus();
+		}
+		return res;
+	},
+	/** Reload tree from source and return a promise.
+	 * @param [source] optional new source (defaults to initial source data)
+	 * @returns {$.Promise}
+	 */
+	reload: function(source) {
+		this._callHook("treeClear", this);
+		return this._callHook("treeLoad", this, source);
+	},
+	/**Render tree (i.e. create DOM elements for all top-level nodes).
+	 * @param {boolean} [force=false] create DOM elemnts, even is parent is collapsed
+	 * @param {boolean} [deep=false]
+	 */
+	render: function(force, deep) {
+		return this.rootNode.render(force, deep);
+	},
+	// TODO: selectKey: function(key, select)
+	// TODO: serializeArray: function(stopOnParents)
+	/**
+	 * @param {boolean} [flag=true]
+	 */
+	setFocus: function(flag) {
+		return this._callHook("treeSetFocus", this, flag);
+	},
+	/**
+	 * Return all nodes as nested list of {@link NodeData}.
+	 *
+	 * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)
+	 * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications
+	 * @returns {Array | object}
+	 * @see FancytreeNode#toDict
+	 */
+	toDict: function(includeRoot, callback){
+		var res = this.rootNode.toDict(true, callback);
+		return includeRoot ? res : res.children;
+	},
+	/* Implicitly called for string conversions.
+	 * @returns {string}
+	 */
+	toString: function(){
+		return "<Fancytree(#" + this._id + ")>";
+	},
+	/* _trigger a widget event with additional node ctx.
+	 * @see EventData
+	 */
+	_triggerNodeEvent: function(type, node, originalEvent, extra) {
+//		this.debug("_trigger(" + type + "): '" + ctx.node.title + "'", ctx);
+		var ctx = this._makeHookContext(node, originalEvent, extra),
+			res = this.widget._trigger(type, originalEvent, ctx);
+		if(res !== false && ctx.result !== undefined){
+			return ctx.result;
+		}
+		return res;
+	},
+	/* _trigger a widget event with additional tree data. */
+	_triggerTreeEvent: function(type, originalEvent, extra) {
+//		this.debug("_trigger(" + type + ")", ctx);
+		var ctx = this._makeHookContext(this, originalEvent, extra),
+			res = this.widget._trigger(type, originalEvent, ctx);
+
+		if(res !== false && ctx.result !== undefined){
+			return ctx.result;
+		}
+		return res;
+	},
+	/** Call fn(node) for all nodes.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and children only.
+	 * @returns {boolean} false, if the iterator was stopped.
+	 */
+	visit: function(fn) {
+		return this.rootNode.visit(fn, false);
+	},
+	/** Write warning to browser console (prepending tree info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	warn: function(msg){
+		Array.prototype.unshift.call(arguments, this.toString());
+		consoleApply("warn", arguments);
+	}
+};
+
+/**
+ * These additional methods of the {@link Fancytree} class are 'hook functions'
+ * that can be used and overloaded by extensions.
+ * (See <a href="https://github.com/mar10/fancytree/wiki/TutorialExtensions">writing extensions</a>.)
+ * @mixin Fancytree_Hooks
+ */
+$.extend(Fancytree.prototype,
+	/** @lends Fancytree_Hooks# */
+	{
+	/** Default handling for mouse click events.
+	 *
+	 * @param {EventData} ctx
+	 */
+	nodeClick: function(ctx) {
+		var activate, expand,
+			// event = ctx.originalEvent,
+			targetType = ctx.targetType,
+			node = ctx.node;
+
+//	    this.debug("ftnode.onClick(" + event.type + "): ftnode:" + this + ", button:" + event.button + ", which: " + event.which, ctx);
+		// TODO: use switch
+		// TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)
+		if( targetType === "expander" ) {
+			if( node.isLoading() ) {
+				// #495: we probably got a click event while a lazy load is pending.
+				// The 'expanded' state is not yet set, so 'toggle' would expand
+				// and trigger lazyLoad again.
+				// It would be better to allow to collapse/expand the status node
+				// while loading (instead of ignoring), but that would require some
+				// more work.
+				node.debug("Got 2nd click while loading: ignored");
+				return;
+			}
+			// Clicking the expander icon always expands/collapses
+			this._callHook("nodeToggleExpanded", ctx);
+
+		} else if( targetType === "checkbox" ) {
+			// Clicking the checkbox always (de)selects
+			this._callHook("nodeToggleSelected", ctx);
+			if( ctx.options.focusOnSelect ) { // #358
+				this._callHook("nodeSetFocus", ctx, true);
+			}
+
+		} else {
+			// Honor `clickFolderMode` for
+			expand = false;
+			activate = true;
+			if( node.folder ) {
+				switch( ctx.options.clickFolderMode ) {
+				case 2: // expand only
+					expand = true;
+					activate = false;
+					break;
+				case 3: // expand and activate
+					activate = true;
+					expand = true; //!node.isExpanded();
+					break;
+				// else 1 or 4: just activate
+				}
+			}
+			if( activate ) {
+				this.nodeSetFocus(ctx);
+				this._callHook("nodeSetActive", ctx, true);
+			}
+			if( expand ) {
+				if(!activate){
+//                    this._callHook("nodeSetFocus", ctx);
+				}
+//				this._callHook("nodeSetExpanded", ctx, true);
+				this._callHook("nodeToggleExpanded", ctx);
+			}
+		}
+		// Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+		// if(event.target.localName === "a" && event.target.className === "fancytree-title"){
+		// 	event.preventDefault();
+		// }
+		// TODO: return promise?
+	},
+	/** Collapse all other  children of same parent.
+	 *
+	 * @param {EventData} ctx
+	 * @param {object} callOpts
+	 */
+	nodeCollapseSiblings: function(ctx, callOpts) {
+		// TODO: return promise?
+		var ac, i, l,
+			node = ctx.node;
+
+		if( node.parent ){
+			ac = node.parent.children;
+			for (i=0, l=ac.length; i<l; i++) {
+				if ( ac[i] !== node && ac[i].expanded ){
+					this._callHook("nodeSetExpanded", ac[i], false, callOpts);
+				}
+			}
+		}
+	},
+	/** Default handling for mouse douleclick events.
+	 * @param {EventData} ctx
+	 */
+	nodeDblclick: function(ctx) {
+		// TODO: return promise?
+		if( ctx.targetType === "title" && ctx.options.clickFolderMode === 4) {
+//			this.nodeSetFocus(ctx);
+//			this._callHook("nodeSetActive", ctx, true);
+			this._callHook("nodeToggleExpanded", ctx);
+		}
+		// TODO: prevent text selection on dblclicks
+		if( ctx.targetType === "title" ) {
+			ctx.originalEvent.preventDefault();
+		}
+	},
+	/** Default handling for mouse keydown events.
+	 *
+	 * NOTE: this may be called with node == null if tree (but no node) has focus.
+	 * @param {EventData} ctx
+	 */
+	nodeKeydown: function(ctx) {
+		// TODO: return promise?
+		var matchNode, stamp, res, focusNode,
+			event = ctx.originalEvent,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			which = event.which,
+			whichChar = String.fromCharCode(which),
+			clean = !(event.altKey || event.ctrlKey || event.metaKey || event.shiftKey),
+			$target = $(event.target),
+			handled = true,
+			activate = !(event.ctrlKey || !opts.autoActivate );
+
+//		(node || FT).debug("ftnode.nodeKeydown(" + event.type + "): ftnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+//		FT.debug("eventToString", which, '"' + String.fromCharCode(which) + '"', '"' + FT.eventToString(event) + '"');
+
+		// Set focus to active (or first node) if no other node has the focus yet
+		if( !node ){
+			focusNode = (this.getActiveNode() || this.getFirstChild());
+			if (focusNode){
+				focusNode.setFocus();
+				node = ctx.node = this.focusNode;
+				node.debug("Keydown force focus on active node");
+			}
+		}
+
+		if( opts.quicksearch && clean && /\w/.test(whichChar) && !$target.is(":input:enabled") ) {
+			// Allow to search for longer streaks if typed in quickly
+			stamp = new Date().getTime();
+			if( stamp - tree.lastQuicksearchTime > 500 ) {
+				tree.lastQuicksearchTerm = "";
+			}
+			tree.lastQuicksearchTime = stamp;
+			tree.lastQuicksearchTerm += whichChar;
+			// tree.debug("quicksearch find", tree.lastQuicksearchTerm);
+			matchNode = tree.findNextNode(tree.lastQuicksearchTerm, tree.getActiveNode());
+			if( matchNode ) {
+				matchNode.setActive();
+			}
+			event.preventDefault();
+			return;
+		}
+		switch( FT.eventToString(event) ) {
+			case "+":
+			case "=": // 187: '+' @ Chrome, Safari
+				tree.nodeSetExpanded(ctx, true);
+				break;
+			case "-":
+				tree.nodeSetExpanded(ctx, false);
+				break;
+			case "space":
+				if(opts.checkbox){
+					tree.nodeToggleSelected(ctx);
+				}else{
+					tree.nodeSetActive(ctx, true);
+				}
+				break;
+			case "return":
+				tree.nodeSetActive(ctx, true);
+				break;
+			case "backspace":
+			case "left":
+			case "right":
+			case "up":
+			case "down":
+				res = node.navigate(event.which, activate);
+				break;
+			default:
+				handled = false;
+		}
+		if(handled){
+			event.preventDefault();
+		}
+	},
+
+
+	// /** Default handling for mouse keypress events. */
+	// nodeKeypress: function(ctx) {
+	//     var event = ctx.originalEvent;
+	// },
+
+	// /** Trigger lazyLoad event (async). */
+	// nodeLazyLoad: function(ctx) {
+	//     var node = ctx.node;
+	//     if(this._triggerNodeEvent())
+	// },
+	/** Load child nodes (async).
+	 *
+	 * @param {EventData} ctx
+	 * @param {object[]|object|string|$.Promise|function} source
+	 * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)
+	 *     data was rendered.
+	 */
+	nodeLoadChildren: function(ctx, source) {
+		var ajax, delay, dfd,
+			tree = ctx.tree,
+			node = ctx.node;
+
+		if($.isFunction(source)){
+			source = source();
+		}
+		// TOTHINK: move to 'ajax' extension?
+		if(source.url){
+			// `source` is an Ajax options object
+			ajax = $.extend({}, ctx.options.ajax, source);
+			if(ajax.debugDelay){
+				// simulate a slow server
+				delay = ajax.debugDelay;
+				if($.isArray(delay)){ // random delay range [min..max]
+					delay = delay[0] + Math.random() * (delay[1] - delay[0]);
+				}
+
+				node.debug("nodeLoadChildren waiting debug delay " + Math.round(delay) + "ms");
+				ajax.debugDelay = false;
+				dfd = $.Deferred(function (dfd) {
+					setTimeout(function () {
+						$.ajax(ajax)
+							.done(function () {	dfd.resolveWith(this, arguments); })
+							.fail(function () {	dfd.rejectWith(this, arguments); });
+					}, delay);
+				});
+			}else{
+				dfd = $.ajax(ajax);
+			}
+
+			// Defer the deferred: we want to be able to reject, even if ajax
+			// resolved ok.
+			source = new $.Deferred();
+			dfd.done(function (data, textStatus, jqXHR) {
+				var errorObj, res;
+				if(this.dataType === "json" && typeof data === "string"){
+					$.error("Ajax request returned a string (did you get the JSON dataType wrong?).");
+				}
+				// postProcess is similar to the standard ajax dataFilter hook,
+				// but it is also called for JSONP
+				if( ctx.options.postProcess ){
+					res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, error: null, dataType: this.dataType});
+					if( res.error ) {
+						errorObj = $.isPlainObject(res.error) ? res.error : {message: res.error};
+						errorObj = tree._makeHookContext(node, null, errorObj);
+						source.rejectWith(this, [errorObj]);
+						return;
+					}
+					data = $.isArray(res) ? res : data;
+
+				} else if (data && data.hasOwnProperty("d") && ctx.options.enableAspx ) {
+					// Process ASPX WebMethod JSON object inside "d" property
+					data = (typeof data.d === "string") ? $.parseJSON(data.d) : data.d;
+				}
+				source.resolveWith(this, [data]);
+			}).fail(function (jqXHR, textStatus, errorThrown) {
+				var errorObj = tree._makeHookContext(node, null, {
+					error: jqXHR,
+					args: Array.prototype.slice.call(arguments),
+					message: errorThrown,
+					details: jqXHR.status + ": " + errorThrown
+				});
+				source.rejectWith(this, [errorObj]);
+			});
+		}
+		// #383: accept and convert ECMAScript 6 Promise
+		if( $.isFunction(source.then) && $.isFunction(source["catch"]) ) {
+			dfd = source;
+			source = new $.Deferred();
+			dfd.then(function(value){
+				source.resolve(value);
+			}, function(reason){
+				source.reject(reason);
+			});
+		}
+		if($.isFunction(source.promise)){
+			// `source` is a deferred, i.e. ajax request
+			_assert(!node.isLoading(), "recursive load");
+			// node._isLoading = true;
+			tree.nodeSetStatus(ctx, "loading");
+
+			source.done(function (children) {
+				tree.nodeSetStatus(ctx, "ok");
+			}).fail(function(error){
+				var ctxErr;
+				if (error.node && error.error && error.message) {
+					// error is already a context object
+					ctxErr = error;
+				} else {
+					ctxErr = tree._makeHookContext(node, null, {
+						error: error, // it can be jqXHR or any custom error
+						args: Array.prototype.slice.call(arguments),
+						message: error ? (error.message || error.toString()) : ""
+					});
+				}
+				if( tree._triggerNodeEvent("loadError", ctxErr, null) !== false ) {
+					tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details);
+				}
+			});
+		}
+		// $.when(source) resolves also for non-deferreds
+		return $.when(source).done(function(children){
+			var metaData;
+
+			if( $.isPlainObject(children) ){
+				// We got {foo: 'abc', children: [...]}
+				// Copy extra properties to tree.data.foo
+				_assert(node.isRootNode(), "source may only be an object for root nodes (expecting an array of child objects otherwise)");
+				_assert($.isArray(children.children), "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')");
+				metaData = children;
+				children = children.children;
+				delete metaData.children;
+				$.extend(tree.data, metaData);
+			}
+			_assert($.isArray(children), "expected array of children");
+			node._setChildren(children);
+			// trigger fancytreeloadchildren
+			tree._triggerNodeEvent("loadChildren", node);
+		// }).always(function(){
+		// 	node._isLoading = false;
+		});
+	},
+	/** [Not Implemented]  */
+	nodeLoadKeyPath: function(ctx, keyPathList) {
+		// TODO: implement and improve
+		// http://code.google.com/p/dynatree/issues/detail?id=222
+	},
+	/**
+	 * Remove a single direct child of ctx.node.
+	 * @param {EventData} ctx
+	 * @param {FancytreeNode} childNode dircect child of ctx.node
+	 */
+	nodeRemoveChild: function(ctx, childNode) {
+		var idx,
+			node = ctx.node,
+			opts = ctx.options,
+			subCtx = $.extend({}, ctx, {node: childNode}),
+			children = node.children;
+
+		// FT.debug("nodeRemoveChild()", node.toString(), childNode.toString());
+
+		if( children.length === 1 ) {
+			_assert(childNode === children[0], "invalid single child");
+			return this.nodeRemoveChildren(ctx);
+		}
+		if( this.activeNode && (childNode === this.activeNode || this.activeNode.isDescendantOf(childNode))){
+			this.activeNode.setActive(false); // TODO: don't fire events
+		}
+		if( this.focusNode && (childNode === this.focusNode || this.focusNode.isDescendantOf(childNode))){
+			this.focusNode = null;
+		}
+		// TODO: persist must take care to clear select and expand cookies
+		this.nodeRemoveMarkup(subCtx);
+		this.nodeRemoveChildren(subCtx);
+		idx = $.inArray(childNode, children);
+		_assert(idx >= 0, "invalid child");
+		// Unlink to support GC
+		childNode.visit(function(n){
+			n.parent = null;
+		}, true);
+		this._callHook("treeRegisterNode", this, false, childNode);
+		if ( opts.removeNode ){
+			opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx);
+		}
+		// remove from child list
+		children.splice(idx, 1);
+	},
+	/**Remove HTML markup for all descendents of ctx.node.
+	 * @param {EventData} ctx
+	 */
+	nodeRemoveChildMarkup: function(ctx) {
+		var node = ctx.node;
+
+		// FT.debug("nodeRemoveChildMarkup()", node.toString());
+		// TODO: Unlink attr.ftnode to support GC
+		if(node.ul){
+			if( node.isRootNode() ) {
+				$(node.ul).empty();
+			} else {
+				$(node.ul).remove();
+				node.ul = null;
+			}
+			node.visit(function(n){
+				n.li = n.ul = null;
+			});
+		}
+	},
+	/**Remove all descendants of ctx.node.
+	* @param {EventData} ctx
+	*/
+	nodeRemoveChildren: function(ctx) {
+		var subCtx,
+			tree = ctx.tree,
+			node = ctx.node,
+			children = node.children,
+			opts = ctx.options;
+
+		// FT.debug("nodeRemoveChildren()", node.toString());
+		if(!children){
+			return;
+		}
+		if( this.activeNode && this.activeNode.isDescendantOf(node)){
+			this.activeNode.setActive(false); // TODO: don't fire events
+		}
+		if( this.focusNode && this.focusNode.isDescendantOf(node)){
+			this.focusNode = null;
+		}
+		// TODO: persist must take care to clear select and expand cookies
+		this.nodeRemoveChildMarkup(ctx);
+		// Unlink children to support GC
+		// TODO: also delete this.children (not possible using visit())
+		subCtx = $.extend({}, ctx);
+		node.visit(function(n){
+			n.parent = null;
+			tree._callHook("treeRegisterNode", tree, false, n);
+			if ( opts.removeNode ){
+				subCtx.node = n;
+				opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx);
+			}
+		});
+		if( node.lazy ){
+			// 'undefined' would be interpreted as 'not yet loaded' for lazy nodes
+			node.children = [];
+		} else{
+			node.children = null;
+		}
+		if( !node.isRootNode() ) {
+			node.expanded = false;  // #449, #459
+		}
+		this.nodeRenderStatus(ctx);
+	},
+	/**Remove HTML markup for ctx.node and all its descendents.
+	 * @param {EventData} ctx
+	 */
+	nodeRemoveMarkup: function(ctx) {
+		var node = ctx.node;
+		// FT.debug("nodeRemoveMarkup()", node.toString());
+		// TODO: Unlink attr.ftnode to support GC
+		if(node.li){
+			$(node.li).remove();
+			node.li = null;
+		}
+		this.nodeRemoveChildMarkup(ctx);
+	},
+	/**
+	 * Create `&lt;li>&lt;span>..&lt;/span> .. &lt;/li>` tags for this node.
+	 *
+	 * This method takes care that all HTML markup is created that is required
+	 * to display this node in it's current state.
+	 *
+	 * Call this method to create new nodes, or after the strucuture
+	 * was changed (e.g. after moving this node or adding/removing children)
+	 * nodeRenderTitle() and nodeRenderStatus() are implied.
+	 *
+	 * Note: if a node was created/removed, nodeRender() must be called for the
+	 *       parent.
+	 * &lt;code>
+	 * &lt;li id='KEY' ftnode=NODE>
+	 *     &lt;span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>
+	 *         &lt;span class="fancytree-expander">&lt;/span>
+	 *         &lt;span class="fancytree-checkbox">&lt;/span> // only present in checkbox mode
+	 *         &lt;span class="fancytree-icon">&lt;/span>
+	 *         &lt;a href="#" class="fancytree-title"> Node 1 &lt;/a>
+	 *     &lt;/span>
+	 *     &lt;ul> // only present if node has children
+	 *         &lt;li id='KEY' ftnode=NODE> child1 ... &lt;/li>
+	 *         &lt;li id='KEY' ftnode=NODE> child2 ... &lt;/li>
+	 *     &lt;/ul>
+	 * &lt;/li>
+	 * &lt;/code>
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [force=false] re-render, even if html markup was already created
+	 * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+	 * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later
+	 */
+	nodeRender: function(ctx, force, deep, collapsed, _recursive) {
+		/* This method must take care of all cases where the current data mode
+		 * (i.e. node hierarchy) does not match the current markup.
+		 *
+		 * - node was not yet rendered:
+		 *   create markup
+		 * - node was rendered: exit fast
+		 * - children have been added
+		 * - children have been removed
+		 */
+		var childLI, childNode1, childNode2, i, l, next, subCtx,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			aria = opts.aria,
+			firstTime = false,
+			parent = node.parent,
+			isRootNode = !parent,
+			children = node.children,
+			successorLi = null;
+		// FT.debug("nodeRender(" + !!force + ", " + !!deep + ")", node.toString());
+
+		if( ! isRootNode && ! parent.ul ) {
+			// Calling node.collapse on a deep, unrendered node
+			return;
+		}
+		_assert(isRootNode || parent.ul, "parent UL must exist");
+
+		// Render the node
+		if( !isRootNode ){
+			// Discard markup on force-mode, or if it is not linked to parent <ul>
+			if(node.li && (force || (node.li.parentNode !== node.parent.ul) ) ){
+				if( node.li.parentNode === node.parent.ul ){
+					// #486: store following node, so we can insert the new markup there later
+					successorLi = node.li.nextSibling;
+				}else{
+					// May happen, when a top-level node was dropped over another
+					this.debug("Unlinking " + node + " (must be child of " + node.parent + ")");
+				}
+//	            this.debug("nodeRemoveMarkup...");
+				this.nodeRemoveMarkup(ctx);
+			}
+			// Create <li><span /> </li>
+//			node.debug("render...");
+			if( !node.li ) {
+//	            node.debug("render... really");
+				firstTime = true;
+				node.li = document.createElement("li");
+				node.li.ftnode = node;
+				if(aria){
+					// TODO: why doesn't this work:
+//					node.li.role = "treeitem";
+//                    $(node.li).attr("role", "treeitem")
+//                    .attr("aria-labelledby", "ftal_" + node.key);
+				}
+				if( node.key && opts.generateIds ){
+					node.li.id = opts.idPrefix + node.key;
+				}
+				node.span = document.createElement("span");
+				node.span.className = "fancytree-node";
+				if(aria){
+					$(node.span).attr("aria-labelledby", "ftal_" + node.key);
+				}
+				node.li.appendChild(node.span);
+
+				// Create inner HTML for the <span> (expander, checkbox, icon, and title)
+				this.nodeRenderTitle(ctx);
+
+				// Allow tweaking and binding, after node was created for the first time
+				if ( opts.createNode ){
+					opts.createNode.call(tree, {type: "createNode"}, ctx);
+				}
+			}else{
+//				this.nodeRenderTitle(ctx);
+				this.nodeRenderStatus(ctx);
+			}
+			// Allow tweaking after node state was rendered
+			if ( opts.renderNode ){
+				opts.renderNode.call(tree, {type: "renderNode"}, ctx);
+			}
+		}
+
+		// Visit child nodes
+		if( children ){
+			if( isRootNode || node.expanded || deep === true ) {
+				// Create a UL to hold the children
+				if( !node.ul ){
+					node.ul = document.createElement("ul");
+					if((collapsed === true && !_recursive) || !node.expanded){
+						// hide top UL, so we can use an animation to show it later
+						node.ul.style.display = "none";
+					}
+					if(aria){
+						$(node.ul).attr("role", "group");
+					}
+					if ( node.li ) { // issue #67
+						node.li.appendChild(node.ul);
+					} else {
+						node.tree.$div.append(node.ul);
+					}
+				}
+				// Add child markup
+				for(i=0, l=children.length; i<l; i++) {
+					subCtx = $.extend({}, ctx, {node: children[i]});
+					this.nodeRender(subCtx, force, deep, false, true);
+				}
+				// Remove <li> if nodes have moved to another parent
+				childLI = node.ul.firstChild;
+				while( childLI ){
+					childNode2 = childLI.ftnode;
+					if( childNode2 && childNode2.parent !== node ) {
+						node.debug("_fixParent: remove missing " + childNode2, childLI);
+						next = childLI.nextSibling;
+						childLI.parentNode.removeChild(childLI);
+						childLI = next;
+					}else{
+						childLI = childLI.nextSibling;
+					}
+				}
+				// Make sure, that <li> order matches node.children order.
+				childLI = node.ul.firstChild;
+				for(i=0, l=children.length-1; i<l; i++) {
+					childNode1 = children[i];
+					childNode2 = childLI.ftnode;
+					if( childNode1 !== childNode2 ) {
+						// node.debug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
+						node.ul.insertBefore(childNode1.li, childNode2.li);
+					} else {
+						childLI = childLI.nextSibling;
+					}
+				}
+			}
+		}else{
+			// No children: remove markup if any
+			if( node.ul ){
+//				alert("remove child markup for " + node);
+				this.warn("remove child markup for " + node);
+				this.nodeRemoveChildMarkup(ctx);
+			}
+		}
+		if( !isRootNode ){
+			// Update element classes according to node state
+			// this.nodeRenderStatus(ctx);
+			// Finally add the whole structure to the DOM, so the browser can render
+			if( firstTime ){
+				// #486: successorLi is set, if we re-rendered (i.e. discarded)
+				// existing markup, which  we want to insert at the same position.
+				// (null is equivalent to append)
+//				parent.ul.appendChild(node.li);
+				parent.ul.insertBefore(node.li, successorLi);
+			}
+		}
+	},
+	/** Create HTML inside the node's outer &lt;span> (i.e. expander, checkbox,
+	 * icon, and title).
+	 *
+	 * nodeRenderStatus() is implied.
+	 * @param {EventData} ctx
+	 * @param {string} [title] optinal new title
+	 */
+	nodeRenderTitle: function(ctx, title) {
+		// set node connector images, links and text
+		var id, iconSpanClass, nodeTitle, role, tabindex, tooltip,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			aria = opts.aria,
+			level = node.getLevel(),
+			ares = [],
+			iconSrc = node.data.icon;
+
+		if(title !== undefined){
+			node.title = title;
+		}
+		if(!node.span){
+			// Silently bail out if node was not rendered yet, assuming
+			// node.render() will be called as the node becomes visible
+			return;
+		}
+		// connector (expanded, expandable or simple)
+		// TODO: optimize this if clause
+		if( level < opts.minExpandLevel ) {
+			if( !node.lazy ) {
+				node.expanded = true;
+			}
+			if(level > 1){
+				if(aria){
+					ares.push("<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>");
+				}else{
+					ares.push("<span class='fancytree-expander fancytree-expander-fixed''></span>");
+				}
+			}
+			// .. else (i.e. for root level) skip expander/connector alltogether
+		} else {
+			if(aria){
+				ares.push("<span role='button' class='fancytree-expander'></span>");
+			}else{
+				ares.push("<span class='fancytree-expander'></span>");
+			}
+		}
+		// Checkbox mode
+		if( opts.checkbox && node.hideCheckbox !== true && !node.isStatusNode() ) {
+			if(aria){
+				ares.push("<span role='checkbox' class='fancytree-checkbox'></span>");
+			}else{
+				ares.push("<span class='fancytree-checkbox'></span>");
+			}
+		}
+		// folder or doctype icon
+		role = aria ? " role='img'" : "";
+		if( iconSrc === true || (iconSrc !== false && opts.icons !== false) ) {
+			// opts.icons defines the default behavior, node.icon == true/false can override this
+			if ( iconSrc && typeof iconSrc === "string" ) {
+				// node.icon is an image url
+				iconSrc = (iconSrc.charAt(0) === "/") ? iconSrc : ((opts.imagePath || "") + iconSrc);
+				ares.push("<img src='" + iconSrc + "' class='fancytree-icon' alt='' />");
+			} else {
+				// See if node.iconclass or opts.iconClass() define a class name
+				iconSpanClass = (opts.iconClass && opts.iconClass.call(tree, {type: "iconClass"}, ctx)) || node.data.iconclass || null;
+				if( iconSpanClass ) {
+					ares.push("<span " + role + " class='fancytree-custom-icon " + iconSpanClass +  "'></span>");
+				} else {
+					ares.push("<span " + role + " class='fancytree-icon'></span>");
+				}
+			}
+		}
+
+		// node title
+		nodeTitle = "";
+		if ( opts.renderTitle ){
+			nodeTitle = opts.renderTitle.call(tree, {type: "renderTitle"}, ctx) || "";
+		}
+		if(!nodeTitle){
+			tooltip = node.tooltip ? " title='" + FT.escapeHtml(node.tooltip) + "'" : "";
+			id = aria ? " id='ftal_" + node.key + "'" : "";
+			role = aria ? " role='treeitem'" : "";
+			tabindex = opts.titlesTabbable ? " tabindex='0'" : "";
+
+			nodeTitle = "<span " + role + " class='fancytree-title'" + id + tooltip + tabindex + ">" + node.title + "</span>";
+		}
+		ares.push(nodeTitle);
+		// Note: this will trigger focusout, if node had the focus
+		//$(node.span).html(ares.join("")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly
+		node.span.innerHTML = ares.join("");
+		// Update CSS classes
+		this.nodeRenderStatus(ctx);
+	},
+	/** Update element classes according to node state.
+	 * @param {EventData} ctx
+	 */
+	nodeRenderStatus: function(ctx) {
+		// Set classes for current status
+		var node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+//			nodeContainer = node[tree.nodeContainerAttrName],
+			hasChildren = node.hasChildren(),
+			isLastSib = node.isLastSibling(),
+			aria = opts.aria,
+//            $ariaElem = aria ? $(node[tree.ariaPropName]) : null,
+			$ariaElem = $(node.span).find(".fancytree-title"),
+			cn = opts._classNames,
+			cnList = [],
+			statusElem = node[tree.statusClassPropName];
+
+		if( !statusElem ){
+			// if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)
+			return;
+		}
+		// Build a list of class names that we will add to the node <span>
+		cnList.push(cn.node);
+		if( tree.activeNode === node ){
+			cnList.push(cn.active);
+//			$(">span.fancytree-title", statusElem).attr("tabindex", "0");
+//			tree.$container.removeAttr("tabindex");
+		// }else{
+//			$(">span.fancytree-title", statusElem).removeAttr("tabindex");
+//			tree.$container.attr("tabindex", "0");
+		}
+		if( tree.focusNode === node ){
+			cnList.push(cn.focused);
+			if(aria){
+//              $(">span.fancytree-title", statusElem).attr("tabindex", "0");
+//                $(">span.fancytree-title", statusElem).attr("tabindex", "-1");
+				// TODO: is this the right element for this attribute?
+				$ariaElem
+					.attr("aria-activedescendant", true);
+//					.attr("tabindex", "-1");
+			}
+		}else if(aria){
+//			$(">span.fancytree-title", statusElem).attr("tabindex", "-1");
+			$ariaElem
+				.removeAttr("aria-activedescendant");
+//				.removeAttr("tabindex");
+		}
+		if( node.expanded ){
+			cnList.push(cn.expanded);
+			if(aria){
+				$ariaElem.attr("aria-expanded", true);
+			}
+		}else if(aria){
+			$ariaElem.removeAttr("aria-expanded");
+		}
+		if( node.folder ){
+			cnList.push(cn.folder);
+		}
+		if( hasChildren !== false ){
+			cnList.push(cn.hasChildren);
+		}
+		// TODO: required?
+		if( isLastSib ){
+			cnList.push(cn.lastsib);
+		}
+		if( node.lazy && node.children == null ){
+			cnList.push(cn.lazy);
+		}
+		if( node.partsel ){
+			cnList.push(cn.partsel);
+		}
+		if( node.unselectable ){
+			cnList.push(cn.unselectable);
+		}
+		if( node._isLoading ){
+			cnList.push(cn.loading);
+		}
+		if( node._error ){
+			cnList.push(cn.error);
+		}
+		if( node.selected ){
+			cnList.push(cn.selected);
+			if(aria){
+				$ariaElem.attr("aria-selected", true);
+			}
+		}else if(aria){
+			$ariaElem.attr("aria-selected", false);
+		}
+		if( node.extraClasses ){
+			cnList.push(node.extraClasses);
+		}
+		// IE6 doesn't correctly evaluate multiple class names,
+		// so we create combined class names that can be used in the CSS
+		if( hasChildren === false ){
+			cnList.push(cn.combinedExpanderPrefix + "n" +
+					(isLastSib ? "l" : "")
+					);
+		}else{
+			cnList.push(cn.combinedExpanderPrefix +
+					(node.expanded ? "e" : "c") +
+					(node.lazy && node.children == null ? "d" : "") +
+					(isLastSib ? "l" : "")
+					);
+		}
+		cnList.push(cn.combinedIconPrefix +
+				(node.expanded ? "e" : "c") +
+				(node.folder ? "f" : "")
+				);
+//        node.span.className = cnList.join(" ");
+		statusElem.className = cnList.join(" ");
+
+		// TODO: we should not set this in the <span> tag also, if we set it here:
+		// Maybe most (all) of the classes should be set in LI instead of SPAN?
+		if(node.li){
+			node.li.className = isLastSib ? cn.lastsib : "";
+		}
+	},
+	/** Activate node.
+	 * flag defaults to true.
+	 * If flag is true, the node is activated (must be a synchronous operation)
+	 * If flag is false, the node is deactivated (must be a synchronous operation)
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+	 * @returns {$.Promise}
+	 */
+	nodeSetActive: function(ctx, flag, callOpts) {
+		// Handle user click / [space] / [enter], according to clickFolderMode.
+		callOpts = callOpts || {};
+		var subCtx,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			noEvents = (callOpts.noEvents === true),
+			noFocus = (callOpts.noFocus === true),
+			isActive = (node === tree.activeNode);
+
+		// flag defaults to true
+		flag = (flag !== false);
+		// node.debug("nodeSetActive", flag);
+
+		if(isActive === flag){
+			// Nothing to do
+			return _getResolvedPromise(node);
+		}else if(flag && !noEvents && this._triggerNodeEvent("beforeActivate", node, ctx.originalEvent) === false ){
+			// Callback returned false
+			return _getRejectedPromise(node, ["rejected"]);
+		}
+		if(flag){
+			if(tree.activeNode){
+				_assert(tree.activeNode !== node, "node was active (inconsistency)");
+				subCtx = $.extend({}, ctx, {node: tree.activeNode});
+				tree.nodeSetActive(subCtx, false);
+				_assert(tree.activeNode === null, "deactivate was out of sync?");
+			}
+			if(opts.activeVisible){
+				// tree.nodeMakeVisible(ctx);
+				node.makeVisible({scrollIntoView: false}); // nodeSetFocus will scroll
+			}
+			tree.activeNode = node;
+			tree.nodeRenderStatus(ctx);
+			if( !noFocus ) {
+				tree.nodeSetFocus(ctx);
+			}
+			if( !noEvents ) {
+				tree._triggerNodeEvent("activate", node, ctx.originalEvent);
+			}
+		}else{
+			_assert(tree.activeNode === node, "node was not active (inconsistency)");
+			tree.activeNode = null;
+			this.nodeRenderStatus(ctx);
+			if( !noEvents ) {
+				ctx.tree._triggerNodeEvent("deactivate", node, ctx.originalEvent);
+			}
+		}
+		return _getResolvedPromise(node);
+	},
+	/** Expand or collapse node, return Deferred.promise.
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+	 * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)
+	 *     data was retrieved, rendered, and the expand animation finshed.
+	 */
+	nodeSetExpanded: function(ctx, flag, callOpts) {
+		callOpts = callOpts || {};
+		var _afterLoad, dfd, i, l, parents, prevAC,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			noAnimation = (callOpts.noAnimation === true),
+			noEvents = (callOpts.noEvents === true);
+
+		// flag defaults to true
+		flag = (flag !== false);
+
+		// node.debug("nodeSetExpanded(" + flag + ")");
+
+		if((node.expanded && flag) || (!node.expanded && !flag)){
+			// Nothing to do
+			// node.debug("nodeSetExpanded(" + flag + "): nothing to do");
+			return _getResolvedPromise(node);
+		}else if(flag && !node.lazy && !node.hasChildren() ){
+			// Prevent expanding of empty nodes
+			// return _getRejectedPromise(node, ["empty"]);
+			return _getResolvedPromise(node);
+		}else if( !flag && node.getLevel() < opts.minExpandLevel ) {
+			// Prevent collapsing locked levels
+			return _getRejectedPromise(node, ["locked"]);
+		}else if ( !noEvents && this._triggerNodeEvent("beforeExpand", node, ctx.originalEvent) === false ){
+			// Callback returned false
+			return _getRejectedPromise(node, ["rejected"]);
+		}
+		// If this node inside a collpased node, no animation and scrolling is needed
+		if( !noAnimation && !node.isVisible() ) {
+			noAnimation = callOpts.noAnimation = true;
+		}
+
+		dfd = new $.Deferred();
+
+		// Auto-collapse mode: collapse all siblings
+		if( flag && !node.expanded && opts.autoCollapse ) {
+			parents = node.getParentList(false, true);
+			prevAC = opts.autoCollapse;
+			try{
+				opts.autoCollapse = false;
+				for(i=0, l=parents.length; i<l; i++){
+					// TODO: should return promise?
+					this._callHook("nodeCollapseSiblings", parents[i], callOpts);
+				}
+			}finally{
+				opts.autoCollapse = prevAC;
+			}
+		}
+		// Trigger expand/collapse after expanding
+		dfd.done(function(){
+			var	lastChild = node.getLastChild();
+			if( flag && opts.autoScroll && !noAnimation && lastChild ) {
+				// Scroll down to last child, but keep current node visible
+				lastChild.scrollIntoView(true, {topNode: node}).always(function(){
+					if( !noEvents ) {
+						ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+					}
+				});
+			} else {
+				if( !noEvents ) {
+					ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+				}
+			}
+		});
+		// vvv Code below is executed after loading finished:
+		_afterLoad = function(callback){
+			var isVisible, isExpanded,
+				effect = opts.toggleEffect;
+
+			node.expanded = flag;
+			// Create required markup, but make sure the top UL is hidden, so we
+			// can animate later
+			tree._callHook("nodeRender", ctx, false, false, true);
+
+			// If the currently active node is now hidden, deactivate it
+			// if( opts.activeVisible && this.activeNode && ! this.activeNode.isVisible() ) {
+			//     this.activeNode.deactivate();
+			// }
+
+			// Expanding a lazy node: set 'loading...' and call callback
+			// if( bExpand && this.data.isLazy && this.childList === null && !this._isLoading ) {
+			//     this._loadContent();
+			//     return;
+			// }
+			// Hide children, if node is collapsed
+			if( node.ul ) {
+				isVisible = (node.ul.style.display !== "none");
+				isExpanded = !!node.expanded;
+				if ( isVisible === isExpanded ) {
+					node.warn("nodeSetExpanded: UL.style.display already set");
+
+				} else if ( !effect || noAnimation ) {
+					node.ul.style.display = ( node.expanded || !parent ) ? "" : "none";
+
+				} else {
+					// The UI toggle() effect works with the ext-wide extension,
+					// while jQuery.animate() has problems when the title span
+					// has positon: absolute
+
+					// duration = opts.fx.duration || 200;
+					// easing = opts.fx.easing;
+					// $(node.ul).animate(opts.fx, duration, easing, function(){
+
+					// node.debug("nodeSetExpanded: animate start...");
+					$(node.ul).toggle(effect.effect, effect.options, effect.duration, function(){
+						// node.debug("nodeSetExpanded: animate done");
+						callback();
+					});
+					return;
+				}
+			}
+			callback();
+		};
+		// ^^^ Code above is executed after loading finshed.
+
+		// Load lazy nodes, if any. Then continue with _afterLoad()
+		if(flag && node.lazy && node.hasChildren() === undefined){
+			// node.debug("nodeSetExpanded: load start...");
+			node.load().done(function(){
+				// node.debug("nodeSetExpanded: load done");
+				if(dfd.notifyWith){ // requires jQuery 1.6+
+					dfd.notifyWith(node, ["loaded"]);
+				}
+				_afterLoad(function () { dfd.resolveWith(node); });
+			}).fail(function(errMsg){
+				_afterLoad(function () { dfd.rejectWith(node, ["load failed (" + errMsg + ")"]); });
+			});
+/*
+			var source = tree._triggerNodeEvent("lazyLoad", node, ctx.originalEvent);
+			_assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+			node.debug("nodeSetExpanded: load start...");
+			this._callHook("nodeLoadChildren", ctx, source).done(function(){
+				node.debug("nodeSetExpanded: load done");
+				if(dfd.notifyWith){ // requires jQuery 1.6+
+					dfd.notifyWith(node, ["loaded"]);
+				}
+				_afterLoad.call(tree);
+			}).fail(function(errMsg){
+				dfd.rejectWith(node, ["load failed (" + errMsg + ")"]);
+			});
+*/
+		}else{
+			_afterLoad(function () { dfd.resolveWith(node); });
+		}
+		// node.debug("nodeSetExpanded: returns");
+		return dfd.promise();
+	},
+	/** Focus or blur this node.
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	nodeSetFocus: function(ctx, flag) {
+		// ctx.node.debug("nodeSetFocus(" + flag + ")");
+		var ctx2,
+			tree = ctx.tree,
+			node = ctx.node;
+
+		flag = (flag !== false);
+
+		// Blur previous node if any
+		if(tree.focusNode){
+			if(tree.focusNode === node && flag){
+				// node.debug("nodeSetFocus(" + flag + "): nothing to do");
+				return;
+			}
+			ctx2 = $.extend({}, ctx, {node: tree.focusNode});
+			tree.focusNode = null;
+			this._triggerNodeEvent("blur", ctx2);
+			this._callHook("nodeRenderStatus", ctx2);
+		}
+		// Set focus to container and node
+		if(flag){
+			if( !this.hasFocus() ){
+				node.debug("nodeSetFocus: forcing container focus");
+				this._callHook("treeSetFocus", ctx, true, {calledByNode: true});
+			}
+			node.makeVisible({scrollIntoView: false});
+			tree.focusNode = node;
+//			node.debug("FOCUS...");
+//			$(node.span).find(".fancytree-title").focus();
+			this._triggerNodeEvent("focus", ctx);
+//          if(ctx.options.autoActivate){
+//              tree.nodeSetActive(ctx, true);
+//          }
+			if(ctx.options.autoScroll){
+				node.scrollIntoView();
+			}
+			this._callHook("nodeRenderStatus", ctx);
+		}
+	},
+	/** (De)Select node, return new status (sync).
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	nodeSetSelected: function(ctx, flag) {
+		var node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options;
+		// flag defaults to true
+		flag = (flag !== false);
+
+		node.debug("nodeSetSelected(" + flag + ")", ctx);
+		if( node.unselectable){
+			return;
+		}
+		// TODO: !!node.expanded is nicer, but doesn't pass jshint
+		// https://github.com/jshint/jshint/issues/455
+//        if( !!node.expanded === !!flag){
+		if((node.selected && flag) || (!node.selected && !flag)){
+			return !!node.selected;
+		}else if ( this._triggerNodeEvent("beforeSelect", node, ctx.originalEvent) === false ){
+			return !!node.selected;
+		}
+		if(flag && opts.selectMode === 1){
+			// single selection mode
+			if(tree.lastSelectedNode){
+				tree.lastSelectedNode.setSelected(false);
+			}
+		}else if(opts.selectMode === 3){
+			// multi.hier selection mode
+			node.selected = flag;
+//			this._fixSelectionState(node);
+			node.fixSelection3AfterClick();
+		}
+		node.selected = flag;
+		this.nodeRenderStatus(ctx);
+		tree.lastSelectedNode = flag ? node : null;
+		tree._triggerNodeEvent("select", ctx);
+	},
+	/** Show node status (ok, loading, error) using styles and a dummy child node.
+	 *
+	 * @param {EventData} ctx
+	 * @param status
+	 * @param message
+	 * @param details
+	 * @since 2.3
+	 */
+	nodeSetStatus: function(ctx, status, message, details) {
+		var node = ctx.node,
+			tree = ctx.tree;
+			// cn = ctx.options._classNames;
+
+		function _clearStatusNode() {
+			// Remove dedicated dummy node, if any
+			var firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				try{
+					// I've seen exceptions here with loadKeyPath...
+					if(node.ul){
+						node.ul.removeChild(firstChild.li);
+						firstChild.li = null; // avoid leaks (DT issue 215)
+					}
+				}catch(e){}
+				if( node.children.length === 1 ){
+					node.children = [];
+				}else{
+					node.children.shift();
+				}
+			}
+		}
+		function _setStatusNode(data, type) {
+			// Create/modify the dedicated dummy node for 'loading...' or
+			// 'error!' status. (only called for direct child of the invisible
+			// system root)
+			var firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				$.extend(firstChild, data);
+				// tree._callHook("nodeRender", firstChild);
+				tree._callHook("nodeRenderTitle", firstChild);
+			} else {
+				data.key = "_statusNode";
+				node._setChildren([data]);
+				node.children[0].statusNodeType = type;
+				tree.render();
+			}
+			return node.children[0];
+		}
+
+		switch( status ){
+		case "ok":
+			_clearStatusNode();
+			// $(node.span).removeClass(cn.loading).removeClass(cn.error);
+			node._isLoading = false;
+			node._error = null;
+			node.renderStatus();
+			break;
+		case "loading":
+			// $(node.span).removeClass(cn.error).addClass(cn.loading);
+			if( !node.parent ) {
+				_setStatusNode({
+					title: tree.options.strings.loading + (message ? " (" + message + ") " : ""),
+					tooltip: details,
+					extraClasses: "fancytree-statusnode-wait"
+				}, status);
+			}
+			node._isLoading = true;
+			node._error = null;
+			node.renderStatus();
+			break;
+		case "error":
+			// $(node.span).removeClass(cn.loading).addClass(cn.error);
+			_setStatusNode({
+				title: tree.options.strings.loadError + (message ? " (" + message + ") " : ""),
+				tooltip: details,
+				extraClasses: "fancytree-statusnode-error"
+			}, status);
+			node._isLoading = false;
+			node._error = { message: message, details: details };
+			node.renderStatus();
+			break;
+		default:
+			$.error("invalid node status " + status);
+		}
+	},
+	/**
+	 *
+	 * @param {EventData} ctx
+	 */
+	nodeToggleExpanded: function(ctx) {
+		return this.nodeSetExpanded(ctx, !ctx.node.expanded);
+	},
+	/**
+	 * @param {EventData} ctx
+	 */
+	nodeToggleSelected: function(ctx) {
+		return this.nodeSetSelected(ctx, !ctx.node.selected);
+	},
+	/** Remove all nodes.
+	 * @param {EventData} ctx
+	 */
+	treeClear: function(ctx) {
+		var tree = ctx.tree;
+		tree.activeNode = null;
+		tree.focusNode = null;
+		tree.$div.find(">ul.fancytree-container").empty();
+		// TODO: call destructors and remove reference loops
+		tree.rootNode.children = null;
+	},
+	/** Widget was created (called only once, even it re-initialized).
+	 * @param {EventData} ctx
+	 */
+	treeCreate: function(ctx) {
+	},
+	/** Widget was destroyed.
+	 * @param {EventData} ctx
+	 */
+	treeDestroy: function(ctx) {
+		this.$div.find(">ul.fancytree-container").remove();
+		this.$source && this.$source.removeClass("ui-helper-hidden");
+	},
+	/** Widget was (re-)initialized.
+	 * @param {EventData} ctx
+	 */
+	treeInit: function(ctx) {
+		//this.debug("Fancytree.treeInit()");
+		this.treeLoad(ctx);
+	},
+	/** Parse Fancytree from source, as configured in the options.
+	 * @param {EventData} ctx
+	 * @param {object} [source] optional new source (use last data otherwise)
+	 */
+	treeLoad: function(ctx, source) {
+		var type, $ul,
+			tree = ctx.tree,
+			$container = ctx.widget.element,
+			dfd,
+			// calling context for root node
+			rootCtx = $.extend({}, ctx, {node: this.rootNode});
+
+		if(tree.rootNode.children){
+			this.treeClear(ctx);
+		}
+		source = source || this.options.source;
+
+		if(!source){
+			type = $container.data("type") || "html";
+			switch(type){
+			case "html":
+				$ul = $container.find(">ul:first");
+				$ul.addClass("ui-fancytree-source ui-helper-hidden");
+				source = $.ui.fancytree.parseHtml($ul);
+				// allow to init tree.data.foo from <ul data-foo=''>
+				this.data = $.extend(this.data, _getElementDataAsDict($ul));
+				break;
+			case "json":
+	//            $().addClass("ui-helper-hidden");
+				source = $.parseJSON($container.text());
+				if(source.children){
+					if(source.title){tree.title = source.title;}
+					source = source.children;
+				}
+				break;
+			default:
+				$.error("Invalid data-type: " + type);
+			}
+		}else if(typeof source === "string"){
+			// TODO: source is an element ID
+			$.error("Not implemented");
+		}
+
+		// Trigger fancytreeinit after nodes have been loaded
+		dfd = this.nodeLoadChildren(rootCtx, source).done(function(){
+			tree.render();
+			if( ctx.options.selectMode === 3 ){
+				tree.rootNode.fixSelection3FromEndNodes();
+			}
+			if( tree.activeNode && tree.options.activeVisible ) {
+				tree.activeNode.makeVisible();
+			}
+			tree._triggerTreeEvent("init", null, { status: true });
+		}).fail(function(){
+			tree.render();
+			tree._triggerTreeEvent("init", null, { status: false });
+		});
+		return dfd;
+	},
+	/** Node was inserted into or removed from the tree.
+	 * @param {EventData} ctx
+	 * @param {boolean} add
+	 * @param {FancytreeNode} node
+	 */
+	treeRegisterNode: function(ctx, add, node) {
+	},
+	/** Widget got focus.
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	treeSetFocus: function(ctx, flag, callOpts) {
+		flag = (flag !== false);
+
+		// this.debug("treeSetFocus(" + flag + "), callOpts: " + callOpts, this.hasFocus());
+		// this.debug("    focusNode: " + this.focusNode);
+		// this.debug("    activeNode: " + this.activeNode);
+		if( flag !== this.hasFocus() ){
+			this._hasFocus = flag;
+			if( !flag && this.focusNode ) {
+				// Node also looses focus if widget blurs
+				this.focusNode.setFocus(false);
+			}
+			this.$container.toggleClass("fancytree-treefocus", flag);
+			this._triggerTreeEvent(flag ? "focusTree" : "blurTree");
+		}
+	}
+});
+
+
+/* ******************************************************************************
+ * jQuery UI widget boilerplate
+ */
+
+/**
+ * The plugin (derrived from <a href=" http://api.jqueryui.com/jQuery.widget/">jQuery.Widget</a>).<br>
+ * This constructor is not called directly. Use `$(selector).fancytree({})`
+ * to initialize the plugin instead.<br>
+ * <pre class="sh_javascript sunlight-highlight-javascript">// Access widget methods and members:
+ * var tree = $("#tree").fancytree("getTree");
+ * var node = $("#tree").fancytree("getActiveNode", "1234");
+ * </pre>
+ *
+ * @mixin Fancytree_Widget
+ */
+
+$.widget("ui.fancytree",
+	/** @lends Fancytree_Widget# */
+	{
+	/**These options will be used as defaults
+	 * @type {FancytreeOptions}
+	 */
+	options:
+	{
+		activeVisible: true,
+		ajax: {
+			type: "GET",
+			cache: false, // false: Append random '_' argument to the request url to prevent caching.
+//          timeout: 0, // >0: Make sure we get an ajax error if server is unreachable
+			dataType: "json" // Expect json format and pass json object to callbacks.
+		},  //
+		aria: false, // TODO: default to true
+		autoActivate: true,
+		autoCollapse: false,
+//      autoFocus: false,
+		autoScroll: false,
+		checkbox: false,
+		/**defines click behavior*/
+		clickFolderMode: 4,
+		debugLevel: null, // 0..2 (null: use global setting $.ui.fancytree.debugInfo)
+		disabled: false, // TODO: required anymore?
+		enableAspx: true, // TODO: document
+		extensions: [],
+		// fx: { height: "toggle", duration: 200 },
+		// toggleEffect: { effect: "drop", options: {direction: "left"}, duration: 200 },
+		// toggleEffect: { effect: "slide", options: {direction: "up"}, duration: 200 },
+		toggleEffect: { effect: "blind", options: {direction: "vertical", scale: "box"}, duration: 200 },
+		generateIds: false,
+		icons: true,
+		idPrefix: "ft_",
+		focusOnSelect: false,
+		keyboard: true,
+		keyPathSeparator: "/",
+		minExpandLevel: 1,
+		quicksearch: false,
+		scrollOfs: {top: 0, bottom: 0},
+		scrollParent: null,
+		selectMode: 2,
+		strings: {
+			loading: "Loading&#8230;",
+			loadError: "Load error!"
+		},
+		tabbable: true,
+		titlesTabbable: false,
+		_classNames: {
+			node: "fancytree-node",
+			folder: "fancytree-folder",
+			combinedExpanderPrefix: "fancytree-exp-",
+			combinedIconPrefix: "fancytree-ico-",
+			hasChildren: "fancytree-has-children",
+			active: "fancytree-active",
+			selected: "fancytree-selected",
+			expanded: "fancytree-expanded",
+			lazy: "fancytree-lazy",
+			focused: "fancytree-focused",
+			partsel: "fancytree-partsel",
+			unselectable: "fancytree-unselectable",
+			lastsib: "fancytree-lastsib",
+			loading: "fancytree-loading",
+			error: "fancytree-error"
+		},
+		// events
+		lazyLoad: null,
+		postProcess: null
+	},
+	/* Set up the widget, Called on first $().fancytree() */
+	_create: function() {
+		this.tree = new Fancytree(this);
+
+		this.$source = this.source || this.element.data("type") === "json" ? this.element
+			: this.element.find(">ul:first");
+		// Subclass Fancytree instance with all enabled extensions
+		var extension, extName, i,
+			extensions = this.options.extensions,
+			base = this.tree;
+
+		for(i=0; i<extensions.length; i++){
+			extName = extensions[i];
+			extension = $.ui.fancytree._extensions[extName];
+			if(!extension){
+				$.error("Could not apply extension '" + extName + "' (it is not registered, did you forget to include it?)");
+			}
+			// Add extension options as tree.options.EXTENSION
+//			_assert(!this.tree.options[extName], "Extension name must not exist as option name: " + extName);
+			this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);
+			// Add a namespace tree.ext.EXTENSION, to hold instance data
+			_assert(this.tree.ext[extName] === undefined, "Extension name must not exist as Fancytree.ext attribute: '" + extName + "'");
+//			this.tree[extName] = extension;
+			this.tree.ext[extName] = {};
+			// Subclass Fancytree methods using proxies.
+			_subclassObject(this.tree, base, extension, extName);
+			// current extension becomes base for the next extension
+			base = extension;
+		}
+		//
+		this.tree._callHook("treeCreate", this.tree);
+		// Note: 'fancytreecreate' event is fired by widget base class
+//        this.tree._triggerTreeEvent("create");
+	},
+
+	/* Called on every $().fancytree() */
+	_init: function() {
+		this.tree._callHook("treeInit", this.tree);
+		// TODO: currently we call bind after treeInit, because treeInit
+		// might change tree.$container.
+		// It would be better, to move ebent binding into hooks altogether
+		this._bind();
+	},
+
+	/* Use the _setOption method to respond to changes to options */
+	_setOption: function(key, value) {
+		var callDefault = true,
+			rerender = false;
+		switch( key ) {
+		case "aria":
+		case "checkbox":
+		case "icons":
+		case "minExpandLevel":
+		case "tabbable":
+//		case "nolink":
+			this.tree._callHook("treeCreate", this.tree);
+			rerender = true;
+			break;
+		case "source":
+			callDefault = false;
+			this.tree._callHook("treeLoad", this.tree, value);
+			break;
+		}
+		this.tree.debug("set option " + key + "=" + value + " <" + typeof(value) + ">");
+		if(callDefault){
+			// In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget
+			$.Widget.prototype._setOption.apply(this, arguments);
+			// TODO: In jQuery UI 1.9 and above, you use the _super method instead
+//          this._super( "_setOption", key, value );
+		}
+		if(rerender){
+			this.tree.render(true, false);  // force, not-deep
+		}
+	},
+
+	/** Use the destroy method to clean up any modifications your widget has made to the DOM */
+	destroy: function() {
+		this._unbind();
+		this.tree._callHook("treeDestroy", this.tree);
+		// In jQuery UI 1.8, you must invoke the destroy method from the base widget
+		$.Widget.prototype.destroy.call(this);
+		// TODO: delete tree and nodes to make garbage collect easier?
+		// TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method
+	},
+
+	// -------------------------------------------------------------------------
+
+	/* Remove all event handlers for our namespace */
+	_unbind: function() {
+		var ns = this.tree._ns;
+		this.element.unbind(ns);
+		this.tree.$container.unbind(ns);
+		$(document).unbind(ns);
+	},
+	/* Add mouse and kyboard handlers to the container */
+	_bind: function() {
+		var that = this,
+			opts = this.options,
+			tree = this.tree,
+			ns = tree._ns
+			// selstartEvent = ( $.support.selectstart ? "selectstart" : "mousedown" )
+			;
+
+		// Remove all previuous handlers for this tree
+		this._unbind();
+
+		//alert("keydown" + ns + "foc=" + tree.hasFocus() + tree.$container);
+		// tree.debug("bind events; container: ", tree.$container);
+		tree.$container.on("focusin" + ns + " focusout" + ns, function(event){
+			var node = FT.getNode(event),
+				flag = (event.type === "focusin");
+			// tree.debug("Tree container got event " + event.type, node, event);
+			// tree.treeOnFocusInOut.call(tree, event);
+			if(node){
+				// For example clicking into an <input> that is part of a node
+				tree._callHook("nodeSetFocus", node, flag);
+			}else{
+				tree._callHook("treeSetFocus", tree, flag);
+			}
+		}).on("selectstart" + ns, "span.fancytree-title", function(event){
+			// prevent mouse-drags to select text ranges
+			// tree.debug("<span title> got event " + event.type);
+			event.preventDefault();
+		}).on("keydown" + ns, function(event){
+			// TODO: also bind keyup and keypress
+			// tree.debug("got event " + event.type + ", hasFocus:" + tree.hasFocus());
+			// if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){
+			if(opts.disabled || opts.keyboard === false ){
+				return true;
+			}
+			var res,
+				node = tree.focusNode, // node may be null
+				ctx = tree._makeHookContext(node || tree, event),
+				prevPhase = tree.phase;
+
+			try {
+				tree.phase = "userEvent";
+				// If a 'fancytreekeydown' handler returns false, skip the default
+				// handling (implemented by tree.nodeKeydown()).
+				if(node){
+					res = tree._triggerNodeEvent("keydown", node, event);
+				}else{
+					res = tree._triggerTreeEvent("keydown", event);
+				}
+				if ( res === "preventNav" ){
+					res = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls
+				} else if ( res !== false ){
+					res = tree._callHook("nodeKeydown", ctx);
+				}
+				return res;
+			} finally {
+				tree.phase = prevPhase;
+			}
+		}).on("click" + ns + " dblclick" + ns, function(event){
+			// that.tree.debug("event(" + event + "): !");
+			if(opts.disabled){
+				return true;
+			}
+			var ctx,
+				et = FT.getEventTarget(event),
+				node = et.node,
+				tree = that.tree,
+				prevPhase = tree.phase;
+
+			// that.tree.debug("event(" + event.type + "): node: ", node);
+			if( !node ){
+				return true;  // Allow bubbling of other events
+			}
+			ctx = tree._makeHookContext(node, event);
+//			that.tree.debug("event(" + event.type + "): node: ", node);
+			try {
+				tree.phase = "userEvent";
+				switch(event.type) {
+				case "click":
+					ctx.targetType = et.type;
+					return ( tree._triggerNodeEvent("click", ctx, event) === false ) ? false : tree._callHook("nodeClick", ctx);
+				case "dblclick":
+					ctx.targetType = et.type;
+					return ( tree._triggerNodeEvent("dblclick", ctx, event) === false ) ? false : tree._callHook("nodeDblclick", ctx);
+				}
+//             } catch(e) {
+// //                var _ = null; // DT issue 117 // TODO
+//                 $.error(e);
+			} finally {
+				tree.phase = prevPhase;
+			}
+		});
+	},
+	/** Return the active node or null.
+	 * @returns {FancytreeNode}
+	 */
+	getActiveNode: function() {
+		return this.tree.activeNode;
+	},
+	/** Return the matching node or null.
+	 * @param {string} key
+	 * @returns {FancytreeNode}
+	 */
+	getNodeByKey: function(key) {
+		return this.tree.getNodeByKey(key);
+	},
+	/** Return the invisible system root node.
+	 * @returns {FancytreeNode}
+	 */
+	getRootNode: function() {
+		return this.tree.rootNode;
+	},
+	/** Return the current tree instance.
+	 * @returns {Fancytree}
+	 */
+	getTree: function() {
+		return this.tree;
+	}
+});
+
+// $.ui.fancytree was created by the widget factory. Create a local shortcut:
+FT = $.ui.fancytree;
+
+/**
+ * Static members in the `$.ui.fancytree` namespace.<br>
+ * <br>
+ * <pre class="sh_javascript sunlight-highlight-javascript">// Access static members:
+ * var node = $.ui.fancytree.getNode(element);
+ * alert($.ui.fancytree.version);
+ * </pre>
+ *
+ * @mixin Fancytree_Static
+ */
+$.extend($.ui.fancytree,
+	/** @lends Fancytree_Static# */
+	{
+	/** @type {string} */
+	version: "2.13.0",      // Set to semver by 'grunt release'
+	/** @type {string} */
+	buildType: "production", // Set to 'production' by 'grunt build'
+	/** @type {int} */
+	debugLevel: 1,            // Set to 1 by 'grunt build'
+							  // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
+
+	_nextId: 1,
+	_nextNodeKey: 1,
+	_extensions: {},
+	// focusTree: null,
+
+	/** Expose class object as $.ui.fancytree._FancytreeClass */
+	_FancytreeClass: Fancytree,
+	/** Expose class object as $.ui.fancytree._FancytreeNodeClass */
+	_FancytreeNodeClass: FancytreeNode,
+	/* Feature checks to provide backwards compatibility */
+	jquerySupports: {
+		// http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+		positionMyOfs: isVersionAtLeast($.ui.version, 1, 9)
+		},
+	/** Throw an error if condition fails (debug method).
+	 * @param {boolean} cond
+	 * @param {string} msg
+	 */
+	assert: function(cond, msg){
+		return _assert(cond, msg);
+	},
+	/** Return a function that executes *fn* at most every *timeout* ms.
+	 * @param {integer} timeout
+	 * @param {function} fn
+	 * @param {boolean} [invokeAsap=false]
+	 * @param {any} [ctx]
+	 */
+	debounce: function(timeout, fn, invokeAsap, ctx) {
+		var timer;
+		if(arguments.length === 3 && typeof invokeAsap !== "boolean") {
+			ctx = invokeAsap;
+			invokeAsap = false;
+		}
+		return function() {
+			var args = arguments;
+			ctx = ctx || this;
+			invokeAsap && !timer && fn.apply(ctx, args);
+			clearTimeout(timer);
+			timer = setTimeout(function() {
+				invokeAsap || fn.apply(ctx, args);
+				timer = null;
+			}, timeout);
+		};
+	},
+	/** Write message to console if debugLevel >= 2
+	 * @param {string} msg
+	 */
+	debug: function(msg){
+		/*jshint expr:true */
+		($.ui.fancytree.debugLevel >= 2) && consoleApply("log", arguments);
+	},
+	/** Write error message to console.
+	 * @param {string} msg
+	 */
+	error: function(msg){
+		consoleApply("error", arguments);
+	},
+	/** Convert &lt;, &gt;, &amp;, &quot;, &#39;, &#x2F; to the equivalent entities.
+	 *
+	 * @param {string} s
+	 * @returns {string}
+	 */
+	escapeHtml: function(s){
+		return ("" + s).replace(/[&<>"'\/]/g, function (s) {
+			return ENTITY_MAP[s];
+		});
+	},
+	/** Make jQuery.position() arguments backwards compatible, i.e. if
+	 * jQuery UI version <= 1.8, convert
+	 *   { my: "left+3 center", at: "left bottom", of: $target }
+	 * to
+	 *   { my: "left center", at: "left bottom", of: $target, offset: "3  0" }
+	 *
+	 * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+	 * and http://jsfiddle.net/mar10/6xtu9a4e/
+	 */
+	fixPositionOptions: function(opts) {
+		if( opts.offset || ("" + opts.my + opts.at ).indexOf("%") >= 0 ) {
+		   $.error("expected new position syntax (but '%' is not supported)");
+		}
+		if( ! $.ui.fancytree.jquerySupports.positionMyOfs ) {
+			var // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]
+				myParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.my),
+				atParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.at),
+				// convert to numbers
+				dx = (myParts[2] ? (+myParts[2]) : 0) + (atParts[2] ? (+atParts[2]) : 0),
+				dy = (myParts[4] ? (+myParts[4]) : 0) + (atParts[4] ? (+atParts[4]) : 0);
+
+			opts = $.extend({}, opts, { // make a copy and overwrite
+				my: myParts[1] + " " + myParts[3],
+				at: atParts[1] + " " + atParts[3]
+			});
+			if( dx || dy ) {
+				opts.offset = "" + dx + " " + dy;
+			}
+		}
+		return opts;
+	},
+	/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+	 *
+	 * @param {Event} event Mouse event, e.g. click, ...
+	 * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+	 */
+	getEventTargetType: function(event){
+		return this.getEventTarget(event).type;
+	},
+	/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+	 *
+	 * @param {Event} event Mouse event, e.g. click, ...
+	 * @returns {object} Return a {node: FancytreeNode, type: TYPE} object
+	 *     TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+	 */
+	getEventTarget: function(event){
+		var tcn = event && event.target ? event.target.className : "",
+			res = {node: this.getNode(event.target), type: undefined};
+		// We use a fast version of $(res.node).hasClass()
+		// See http://jsperf.com/test-for-classname/2
+		if( /\bfancytree-title\b/.test(tcn) ){
+			res.type = "title";
+		}else if( /\bfancytree-expander\b/.test(tcn) ){
+			res.type = (res.node.hasChildren() === false ? "prefix" : "expander");
+		}else if( /\bfancytree-checkbox\b/.test(tcn) || /\bfancytree-radio\b/.test(tcn) ){
+			res.type = "checkbox";
+		}else if( /\bfancytree-icon\b/.test(tcn) ){
+			res.type = "icon";
+		}else if( /\bfancytree-node\b/.test(tcn) ){
+			// Somewhere near the title
+			res.type = "title";
+		}else if( event && event.target && $(event.target).closest(".fancytree-title").length ) {
+			// #228: clicking an embedded element inside a title
+			res.type = "title";
+		}
+		return res;
+	},
+	/** Return a FancytreeNode instance from element, event, or jQuery object.
+	 *
+	 * @param {Element | jQueryObject | Event} el
+	 * @returns {FancytreeNode} matching node or null
+	 */
+	getNode: function(el){
+		if(el instanceof FancytreeNode){
+			return el; // el already was a FancytreeNode
+		}else if(el.selector !== undefined){
+			el = el[0]; // el was a jQuery object: use the DOM element
+		}else if(el.originalEvent !== undefined){
+			el = el.target; // el was an Event
+		}
+		while( el ) {
+			if(el.ftnode) {
+				return el.ftnode;
+			}
+			el = el.parentNode;
+		}
+		return null;
+	},
+	/** Return a Fancytree instance, from element, index, event, or jQueryObject.
+	 *
+	 * @param {Element | jQueryObject | Event | integer | string} [el]
+	 * @returns {Fancytree} matching tree or null
+	 * @example
+	 * $.ui.fancytree.getTree();   // Get first Fancytree instance on page
+	 * $.ui.fancytree.getTree(1);  // Get second Fancytree instance on page
+	 * $.ui.fancytree.getTree("#tree"); // Get tree for this matching element
+	 *
+	 * @since 2.13
+	 */
+	getTree: function(el){
+		var widget;
+
+		if( el instanceof Fancytree ) {
+			return el; // el already was a Fancytree
+		}
+		if( el === undefined ) {
+			el = 0;  // get first tree
+		}
+		if( typeof el === "number" ) {
+			el = $(".fancytree-container").eq(el); // el was an integer: return nth instance
+		} else if( typeof el === "string" ) {
+			el = $(el).eq(0); // el was a selector: use first match
+		} else if( el.selector !== undefined ) {
+			el = el.eq(0); // el was a jQuery object: use the first DOM element
+		} else if( el.originalEvent !== undefined ) {
+			el = $(el.target); // el was an Event
+		}
+		el = el.closest(":ui-fancytree");
+		widget = el.data("ui-fancytree") || el.data("fancytree"); // the latter is required by jQuery <= 1.8
+		return widget ? widget.tree : null;
+	},
+	/** Write message to console if debugLevel >= 1
+	 * @param {string} msg
+	 */
+	info: function(msg){
+		/*jshint expr:true */
+		($.ui.fancytree.debugLevel >= 1) && consoleApply("info", arguments);
+	},
+	/** Convert a keydown or mouse event to a canonical string like 'ctrl+a', 'ctrl+shift+f2', 'shift+leftdblclick'.
+	 * This is especially handy for switch-statements in event handlers.
+	 * @param {event}
+	 * @returns {string}
+	 */
+	eventToString: function(event) {
+		// Poor-man's hotkeys. See here for a complete implementation:
+		//   https://github.com/jeresig/jquery.hotkeys
+		var which = event.which,
+			et = event.type,
+			s = [];
+
+		if( event.altKey ) { s.push("alt"); }
+		if( event.ctrlKey ) { s.push("ctrl"); }
+		if( event.metaKey ) { s.push("meta"); }
+		if( event.shiftKey ) { s.push("shift"); }
+
+		if( et === "click" || et === "dblclick" ) {
+			s.push(MOUSE_BUTTONS[event.button] + et);
+		} else {
+			if( !IGNORE_KEYCODES[which] ) {
+				s.push( SPECIAL_KEYCODES[which] || String.fromCharCode(which).toLowerCase() );
+			}
+		}
+		return s.join("+");
+	},
+	/* @deprecated: use eventToString(event) instead.
+	 */
+	keyEventToString: function(event) {
+		this.warn("keyEventToString() is deprecated: use eventToString()");
+		return this.eventToString(event);
+	},
+	/**
+	 * Parse tree data from HTML <ul> markup
+	 *
+	 * @param {jQueryObject} $ul
+	 * @returns {NodeData[]}
+	 */
+	parseHtml: function($ul) {
+		// TODO: understand this:
+		/*jshint validthis:true */
+		var classes, className, extraClasses, i, iPos, l, tmp, tmp2,
+			$children = $ul.find(">li"),
+			children = [];
+
+		$children.each(function() {
+			var allData, lowerCaseAttr,
+				$li = $(this),
+				$liSpan = $li.find(">span:first", this),
+				$liA = $liSpan.length ? null : $li.find(">a:first"),
+				d = { tooltip: null, data: {} };
+
+			if( $liSpan.length ) {
+				d.title = $liSpan.html();
+
+			} else if( $liA && $liA.length ) {
+				// If a <li><a> tag is specified, use it literally and extract href/target.
+				d.title = $liA.html();
+				d.data.href = $liA.attr("href");
+				d.data.target = $liA.attr("target");
+				d.tooltip = $liA.attr("title");
+
+			} else {
+				// If only a <li> tag is specified, use the trimmed string up to
+				// the next child <ul> tag.
+				d.title = $li.html();
+				iPos = d.title.search(/<ul/i);
+				if( iPos >= 0 ){
+					d.title = d.title.substring(0, iPos);
+				}
+			}
+			d.title = $.trim(d.title);
+
+			// Make sure all fields exist
+			for(i=0, l=CLASS_ATTRS.length; i<l; i++){
+				d[CLASS_ATTRS[i]] = undefined;
+			}
+			// Initialize to `true`, if class is set and collect extraClasses
+			classes = this.className.split(" ");
+			extraClasses = [];
+			for(i=0, l=classes.length; i<l; i++){
+				className = classes[i];
+				if(CLASS_ATTR_MAP[className]){
+					d[className] = true;
+				}else{
+					extraClasses.push(className);
+				}
+			}
+			d.extraClasses = extraClasses.join(" ");
+
+			// Parse node options from ID, title and class attributes
+			tmp = $li.attr("title");
+			if( tmp ){
+				d.tooltip = tmp; // overrides <a title='...'>
+			}
+			tmp = $li.attr("id");
+			if( tmp ){
+				d.key = tmp;
+			}
+			// Add <li data-NAME='...'> as node.data.NAME
+			allData = _getElementDataAsDict($li);
+			if( allData && !$.isEmptyObject(allData) ) {
+				// #507: convert data-hidecheckbox (lower case) to hideCheckbox
+				for( lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP ) {
+					if( allData.hasOwnProperty(lowerCaseAttr) ) {
+						allData[NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]] = allData[lowerCaseAttr];
+						delete allData[lowerCaseAttr];
+					}
+				}
+				// #56: Allow to set special node.attributes from data-...
+				for(i=0, l=NODE_ATTRS.length; i<l; i++){
+					tmp = NODE_ATTRS[i];
+					tmp2 = allData[tmp];
+					if( tmp2 != null ) {
+						delete allData[tmp];
+						d[tmp] = tmp2;
+					}
+				}
+				// All other data-... goes to node.data...
+				$.extend(d.data, allData);
+			}
+			// Recursive reading of child nodes, if LI tag contains an UL tag
+			$ul = $li.find(">ul:first");
+			if( $ul.length ) {
+				d.children = $.ui.fancytree.parseHtml($ul);
+			}else{
+				d.children = d.lazy ? undefined : null;
+			}
+			children.push(d);
+//            FT.debug("parse ", d, children);
+		});
+		return children;
+	},
+	/** Add Fancytree extension definition to the list of globally available extensions.
+	 *
+	 * @param {object} definition
+	 */
+	registerExtension: function(definition){
+		_assert(definition.name != null, "extensions must have a `name` property.");
+		_assert(definition.version != null, "extensions must have a `version` property.");
+		$.ui.fancytree._extensions[definition.name] = definition;
+	},
+	/** Inverse of escapeHtml().
+	 *
+	 * @param {string} s
+	 * @returns {string}
+	 */
+	unescapeHtml: function(s){
+		var e = document.createElement("div");
+		e.innerHTML = s;
+		return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
+	},
+	/** Write warning message to console.
+	 * @param {string} msg
+	 */
+	warn: function(msg){
+		consoleApply("warn", arguments);
+	}
+});
+
+}(jQuery, window, document));
+
+// Extending Fancytree
+// ===================
+//
+// See also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code.
+//
+// Every extension should have a comment header containing some information
+// about the author, copyright and licensing. Also a pointer to the latest
+// source code.
+// Prefix with `/*!` so the comment is not removed by the minifier.
+
+/*!
+ * jquery.fancytree.childcounter.js
+ *
+ * Add a child counter bubble to tree nodes.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+// To keep the global namespace clean, we wrap everything in a closure
+
+;(function($, undefined) {
+
+// Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
+"use strict";
+
+// The [coding guidelines](http://contribute.jquery.org/style-guide/js/)
+// require jshint compliance.
+// But for this sample, we want to allow unused variables for demonstration purpose.
+
+/*jshint unused:false */
+
+
+// Adding methods
+// --------------
+
+// New member functions can be added to the `Fancytree` class.
+// This function will be available for every tree instance:
+//
+//     var tree = $("#tree").fancytree("getTree");
+//     tree.countSelected(false);
+
+$.ui.fancytree._FancytreeClass.prototype.countSelected = function(topOnly){
+	var tree = this,
+		treeOptions = tree.options;
+
+	return tree.getSelectedNodes(topOnly).length;
+};
+
+
+// The `FancytreeNode` class can also be easily extended. This would be called
+// like
+//     node.updateCounters();
+//
+// It is also good practice to add a docstring comment.
+/**
+ * [ext-childcounter] Update counter badges for `node` and its parents.
+ * May be called in the `loadChildren` event, to update parents of lazy loaded
+ * nodes.
+ * @alias FancytreeNode#updateCounters
+ * @requires jquery.fancytree.childcounters.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.updateCounters = function(){
+	var node = this,
+		$badge = $("span.fancytree-childcounter", node.span),
+		extOpts = node.tree.options.childcounter,
+		count = node.countChildren(extOpts.deep);
+
+	node.data.childCounter = count;
+	if( (count || !extOpts.hideZeros) && (!node.isExpanded() || !extOpts.hideExpanded) ) {
+		if( !$badge.length ) {
+			$badge = $("<span class='fancytree-childcounter'/>").appendTo($("span.fancytree-icon", node.span));
+		}
+		$badge.text(count);
+	} else {
+		$badge.remove();
+	}
+	if( extOpts.deep && !node.isTopLevel() && !node.isRoot() ) {
+		node.parent.updateCounters();
+	}
+};
+
+
+// Finally, we can extend the widget API and create functions that are called
+// like so:
+//
+//     $("#tree").fancytree("widgetMethod1", "abc");
+
+$.ui.fancytree.prototype.widgetMethod1 = function(arg1){
+	var tree = this.tree;
+	return arg1;
+};
+
+
+// Register a Fancytree extension
+// ------------------------------
+// A full blown extension, extension is available for all trees and can be
+// enabled like so (see also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html)):
+//
+//    <script src="../src/jquery.fancytree.js" type="text/javascript"></script>
+//    <script src="../src/jquery.fancytree.childcounter.js" type="text/javascript"></script>
+//    ...
+//
+//     $("#tree").fancytree({
+//         extensions: ["childcounter"],
+//         childcounter: {
+//             hideExpanded: true
+//         },
+//         ...
+//     });
+//
+
+
+/* 'childcounter' extension */
+$.ui.fancytree.registerExtension({
+// Every extension must be registered by a unique name.
+	name: "childcounter",
+// Version information should be compliant with [semver](http://semver.org)
+	version: "1.0.0",
+
+// Extension specific options and their defaults.
+// This options will be available as `tree.options.childcounter.hideExpanded`
+
+	options: {
+		deep: true,
+		hideZeros: true,
+		hideExpanded: false
+	},
+
+// Attributes other than `options` (or functions) can be defined here, and
+// will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`.
+// They can also be accessed as `this._local.foo` from within the extension
+// methods.
+	foo: 42,
+
+// Local functions are prefixed with an underscore '_'.
+// Callable as `this._local._appendCounter()`.
+
+	_appendCounter: function(bar){
+		var tree = this;
+	},
+
+// **Override virtual methods for this extension.**
+//
+// Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'.
+// with a `ctx` argument (see [EventData](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/global.html#EventData)
+// for details) and an extended calling context:<br>
+// `this`       : the Fancytree instance<br>
+// `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br>
+// `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
+//
+// See also the [complete list of available hook functions](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html).
+
+	/* Init */
+// `treeInit` is triggered when a tree is initalized. We can set up classes or
+// bind event handlers here...
+	treeInit: function(ctx){
+		var tree = this, // same as ctx.tree,
+			opts = ctx.options,
+			extOpts = ctx.options.childcounter;
+// Optionally check for dependencies with other extensions
+		/* this._requireExtension("glyph", false, false); */
+// Call the base implementation
+		this._superApply(arguments);
+// Add a class to the tree container
+		this.$container.addClass("fancytree-ext-childcounter");
+	},
+
+// Destroy this tree instance (we only call the default implementation, so
+// this method could as well be omitted).
+
+	treeDestroy: function(ctx){
+		this._superApply(arguments);
+	},
+
+// Overload the `renderTitle` hook, to append a counter badge
+	nodeRenderTitle: function(ctx, title) {
+		var node = ctx.node,
+			extOpts = ctx.options.childcounter,
+			count = (node.data.childCounter == null) ? node.countChildren(extOpts.deep) : +node.data.childCounter;
+// Let the base implementation render the title
+		this._superApply(arguments);
+// Append a counter badge
+		if( (count || ! extOpts.hideZeros) && (!node.isExpanded() || !extOpts.hideExpanded) ){
+			$("span.fancytree-icon", node.span).append($("<span class='fancytree-childcounter'/>").text(count));
+		}
+	},
+// Overload the `setExpanded` hook, so the counters are updated
+	nodeSetExpanded: function(ctx, flag, opts) {
+		var tree = ctx.tree,
+			node = ctx.node;
+// Let the base implementation expand/collapse the node, then redraw the title
+// after the animation has finished
+		return this._superApply(arguments).always(function(){
+			tree.nodeRenderTitle(ctx);
+		});
+	}
+
+// End of extension definition
+});
+// End of namespace closure
+}(jQuery));
+
+/*!
+ *
+ * jquery.fancytree.clones.js
+ * Support faster lookup of nodes by key and shared ref-ids.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+function _assert(cond, msg){
+	// TODO: see qunit.js extractStacktrace()
+	if(!cond){
+		msg = msg ? ": " + msg : "";
+		$.error("Assertion failed" + msg);
+	}
+}
+
+
+/* Return first occurrence of member from array. */
+function _removeArrayMember(arr, elem) {
+	// TODO: use Array.indexOf for IE >= 9
+	var i;
+	for (i = arr.length - 1; i >= 0; i--) {
+		if (arr[i] === elem) {
+			arr.splice(i, 1);
+			return true;
+		}
+	}
+	return false;
+}
+
+
+// /**
+//  * Calculate a 32 bit FNV-1a hash
+//  * Found here: https://gist.github.com/vaiorabbit/5657561
+//  * Ref.: http://isthe.com/chongo/tech/comp/fnv/
+//  *
+//  * @param {string} str the input value
+//  * @param {boolean} [asString=false] set to true to return the hash value as
+//  *     8-digit hex string instead of an integer
+//  * @param {integer} [seed] optionally pass the hash of the previous chunk
+//  * @returns {integer | string}
+//  */
+// function hashFnv32a(str, asString, seed) {
+// 	/*jshint bitwise:false */
+// 	var i, l,
+// 		hval = (seed === undefined) ? 0x811c9dc5 : seed;
+
+// 	for (i = 0, l = str.length; i < l; i++) {
+// 		hval ^= str.charCodeAt(i);
+// 		hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
+// 	}
+// 	if( asString ){
+// 		// Convert to 8 digit hex string
+// 		return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
+// 	}
+// 	return hval >>> 0;
+// }
+
+
+/**
+ * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
+ *
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+ * @see http://github.com/garycourt/murmurhash-js
+ * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
+ * @see http://sites.google.com/site/murmurhash/
+ *
+ * @param {string} key ASCII only
+ * @param {boolean} [asString=false]
+ * @param {number} seed Positive integer only
+ * @return {number} 32-bit positive integer hash
+ */
+function hashMurmur3(key, asString, seed) {
+	/*jshint bitwise:false */
+	var h1b, k1,
+		remainder = key.length & 3,
+		bytes = key.length - remainder,
+		h1 = seed,
+		c1 = 0xcc9e2d51,
+		c2 = 0x1b873593,
+		i = 0;
+
+	while (i < bytes) {
+		k1 =
+			((key.charCodeAt(i) & 0xff)) |
+			((key.charCodeAt(++i) & 0xff) << 8) |
+			((key.charCodeAt(++i) & 0xff) << 16) |
+			((key.charCodeAt(++i) & 0xff) << 24);
+		++i;
+
+		k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
+		k1 = (k1 << 15) | (k1 >>> 17);
+		k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
+
+		h1 ^= k1;
+		h1 = (h1 << 13) | (h1 >>> 19);
+		h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
+		h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
+	}
+
+	k1 = 0;
+
+	switch (remainder) {
+		/*jshint -W086:true */
+		case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
+		case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
+		case 1: k1 ^= (key.charCodeAt(i) & 0xff);
+
+		k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
+		k1 = (k1 << 15) | (k1 >>> 17);
+		k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
+		h1 ^= k1;
+	}
+
+	h1 ^= key.length;
+
+	h1 ^= h1 >>> 16;
+	h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
+	h1 ^= h1 >>> 13;
+	h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
+	h1 ^= h1 >>> 16;
+
+	if( asString ){
+		// Convert to 8 digit hex string
+		return ("0000000" + (h1 >>> 0).toString(16)).substr(-8);
+	}
+	return h1 >>> 0;
+}
+
+// console.info(hashMurmur3("costarring"));
+// console.info(hashMurmur3("costarring", true));
+// console.info(hashMurmur3("liquid"));
+// console.info(hashMurmur3("liquid", true));
+
+
+/*
+ * Return a unique key for node by calculationg the hash of the parents refKey-list
+ */
+function calcUniqueKey(node) {
+	var key,
+		path = $.map(node.getParentList(false, true), function(e){ return e.refKey || e.key; });
+	path = path.join("/");
+	key = "id_" + hashMurmur3(path, true);
+	// node.debug(path + " -> " + key);
+	return key;
+}
+
+
+/**
+ * [ext-clones] Return a list of clone-nodes or null.
+ * @param {boolean} [includeSelf=false]
+ * @returns {FancytreeNode[] | null}
+ *
+ * @alias FancytreeNode#getCloneList
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function(includeSelf){
+	var key,
+		tree = this.tree,
+		refList = tree.refMap[this.refKey] || null,
+		keyMap = tree.keyMap;
+
+	if( refList ) {
+		key = this.key;
+		// Convert key list to node list
+		if( includeSelf ) {
+			refList = $.map(refList, function(val){ return keyMap[val]; });
+		} else {
+			refList = $.map(refList, function(val){ return val === key ? null : keyMap[val]; });
+			if( refList.length < 1 ) {
+				refList = null;
+			}
+		}
+	}
+	return refList;
+};
+
+
+/**
+ * [ext-clones] Return true if this node has at least another clone with same refKey.
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#isClone
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.isClone = function(){
+	var refKey = this.refKey || null,
+		refList = refKey && this.tree.refMap[refKey] || null;
+	return !!(refList && refList.length > 1);
+};
+
+
+/**
+ * [ext-clones] Update key and/or refKey for an existing node.
+ * @param {string} key
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#reRegister
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function(key, refKey){
+	key = (key == null) ? null :  "" + key;
+	refKey = (refKey == null) ? null :  "" + refKey;
+	// this.debug("reRegister", key, refKey);
+
+	var tree = this.tree,
+		prevKey = this.key,
+		prevRefKey = this.refKey,
+		keyMap = tree.keyMap,
+		refMap = tree.refMap,
+		refList = refMap[prevRefKey] || null,
+//		curCloneKeys = refList ? node.getCloneList(true),
+		modified = false;
+
+	// Key has changed: update all references
+	if( key != null && key !== this.key ) {
+		if( keyMap[key] ) {
+			$.error("[ext-clones] reRegister(" + key + "): already exists: " + this);
+		}
+		// Update keyMap
+		delete keyMap[prevKey];
+		keyMap[key] = this;
+		// Update refMap
+		if( refList ) {
+			refMap[prevRefKey] = $.map(refList, function(e){
+				return e === prevKey ? key : e;
+			});
+		}
+		this.key = key;
+		modified = true;
+	}
+
+	// refKey has changed
+	if( refKey != null && refKey !== this.refKey ) {
+		// Remove previous refKeys
+		if( refList ){
+			if( refList.length === 1 ){
+				delete refMap[prevRefKey];
+			}else{
+				refMap[prevRefKey] = $.map(refList, function(e){
+					return e === prevKey ? null : e;
+				});
+			}
+		}
+		// Add refKey
+		if( refMap[refKey] ) {
+			refMap[refKey].append(key);
+		}else{
+			refMap[refKey] = [ this.key ];
+		}
+		this.refKey = refKey;
+		modified = true;
+	}
+	return modified;
+};
+
+
+/**
+ * [ext-clones] Return all nodes with a given refKey (null if not found).
+ * @param {string} refKey
+ * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node
+ * @returns {FancytreeNode[] | null}
+ * @alias Fancytree#getNodesByRef
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function(refKey, rootNode){
+	var keyMap = this.keyMap,
+		refList = this.refMap[refKey] || null;
+
+	if( refList ) {
+		// Convert key list to node list
+		if( rootNode ) {
+			refList = $.map(refList, function(val){
+				var node = keyMap[val];
+				return node.isDescendantOf(rootNode) ? node : null;
+			});
+		}else{
+			refList = $.map(refList, function(val){ return keyMap[val]; });
+		}
+		if( refList.length < 1 ) {
+			refList = null;
+		}
+	}
+	return refList;
+};
+
+
+/**
+ * [ext-clones] Replace a refKey with a new one.
+ * @param {string} oldRefKey
+ * @param {string} newRefKey
+ * @alias Fancytree#changeRefKey
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.changeRefKey = function(oldRefKey, newRefKey) {
+	var i, node,
+		keyMap = this.keyMap,
+		refList = this.refMap[oldRefKey] || null;
+
+	if (refList) {
+		for (i = 0; i < refList.length; i++) {
+			node = keyMap[refList[i]];
+			node.refKey = newRefKey;
+		}
+		delete this.refMap[oldRefKey];
+		this.refMap[newRefKey] = refList;
+	}
+};
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "clones",
+	version: "0.0.3",
+	// Default options for this extension.
+	options: {
+		highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
+		highlightClones: false       // set 'fancytree-clone' class on any node that has at least one clone
+	},
+
+	treeCreate: function(ctx){
+		this._superApply(arguments);
+		ctx.tree.refMap = {};
+		ctx.tree.keyMap = {};
+	},
+	treeInit: function(ctx){
+		this.$container.addClass("fancytree-ext-clones");
+		_assert(ctx.options.defaultKey == null);
+		// Generate unique / reproducible default keys
+		ctx.options.defaultKey = function(node){
+			return calcUniqueKey(node);
+		};
+		// The default implementation loads initial data
+		this._superApply(arguments);
+	},
+	treeClear: function(ctx){
+		ctx.tree.refMap = {};
+		ctx.tree.keyMap = {};
+		return this._superApply(arguments);
+	},
+	treeRegisterNode: function(ctx, add, node) {
+		var refList, len,
+			tree = ctx.tree,
+			keyMap = tree.keyMap,
+			refMap = tree.refMap,
+			key = node.key,
+			refKey = (node && node.refKey != null) ? "" + node.refKey : null;
+
+//		ctx.tree.debug("clones.treeRegisterNode", add, node);
+
+		if( key === "_statusNode" ){
+			return this._superApply(arguments);
+		}
+
+		if( add ) {
+			if( keyMap[node.key] != null ) {
+				$.error("clones.treeRegisterNode: node.key already exists: " + node);
+			}
+			keyMap[key] = node;
+			if( refKey ) {
+				refList = refMap[refKey];
+				if( refList ) {
+					refList.push(key);
+					if( refList.length === 2 && ctx.options.clones.highlightClones ) {
+						// Mark peer node, if it just became a clone (no need to
+						// mark current node, since it will be rendered later anyway)
+						keyMap[refList[0]].renderStatus();
+					}
+				} else {
+					refMap[refKey] = [key];
+				}
+				// node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]);
+			}
+		}else {
+			if( keyMap[key] == null ) {
+				$.error("clones.treeRegisterNode: node.key not registered: " + node.key);
+			}
+			delete keyMap[key];
+			if( refKey ) {
+				refList = refMap[refKey];
+				// node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]);
+				if( refList ) {
+					len = refList.length;
+					if( len <= 1 ){
+						_assert(len === 1);
+						_assert(refList[0] === key);
+						delete refMap[refKey];
+					}else{
+						_removeArrayMember(refList, key);
+						// Unmark peer node, if this was the only clone
+						if( len === 2 && ctx.options.clones.highlightClones ) {
+//							node.debug("clones.treeRegisterNode: last =>", node.getCloneList());
+							keyMap[refList[0]].renderStatus();
+						}
+					}
+					// node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]);
+				}
+			}
+		}
+		return this._superApply(arguments);
+	},
+	nodeRenderStatus: function(ctx) {
+		var $span, res,
+			node = ctx.node;
+
+		res = this._superApply(arguments);
+
+		if( ctx.options.clones.highlightClones ) {
+			$span = $(node[ctx.tree.statusClassPropName]);
+			// Only if span already exists
+			if( $span.length && node.isClone() ){
+//				node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones);
+				$span.addClass("fancytree-clone");
+			}
+		}
+		return res;
+	},
+	nodeSetActive: function(ctx, flag) {
+		var res,
+			scpn = ctx.tree.statusClassPropName,
+			node = ctx.node;
+
+		res = this._superApply(arguments);
+
+		if( ctx.options.clones.highlightActiveClones && node.isClone() ) {
+			$.each(node.getCloneList(true), function(idx, n){
+				// n.debug("clones.nodeSetActive: ", flag !== false);
+				$(n[scpn]).toggleClass("fancytree-active-clone", flag !== false);
+			});
+		}
+		return res;
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.dnd.js
+ *
+ * Drag-and-drop support.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+var didRegisterDnd = false,
+	classDropAccept = "fancytree-drop-accept",
+	classDropAfter = "fancytree-drop-after",
+	classDropBefore = "fancytree-drop-before",
+	classDropOver = "fancytree-drop-over",
+	classDropReject = "fancytree-drop-reject",
+	classDropTarget = "fancytree-drop-target";
+
+/* Convert number to string and prepend +/-; return empty string for 0.*/
+function offsetString(n){
+	return n === 0 ? "" : (( n > 0 ) ? ("+" + n) : ("" + n));
+}
+
+/* *****************************************************************************
+ * Drag and drop support
+ */
+function _initDragAndDrop(tree) {
+	var dnd = tree.options.dnd || null,
+		glyph = tree.options.glyph || null;
+
+	// Register 'connectToFancytree' option with ui.draggable
+	if( dnd ) {
+		_registerDnd();
+	}
+	// Attach ui.draggable to this Fancytree instance
+	if(dnd && dnd.dragStart ) {
+		tree.widget.element.draggable($.extend({
+			addClasses: false,
+			// DT issue 244: helper should be child of scrollParent:
+			appendTo: tree.$container,
+//			appendTo: "body",
+			containment: false,
+//			containment: "parent",
+			delay: 0,
+			distance: 4,
+			revert: false,
+			scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container
+			scrollSpeed: 7,
+			scrollSensitivity: 10,
+			// Delegate draggable.start, drag, and stop events to our handler
+			connectToFancytree: true,
+			// Let source tree create the helper element
+			helper: function(event) {
+				var $helper, $nodeTag, opts,
+					sourceNode = $.ui.fancytree.getNode(event.target);
+
+				if(!sourceNode){
+					// #405, DT issue 211: might happen, if dragging a table *header*
+					return "<div>ERROR?: helper requested but sourceNode not found</div>";
+				}
+				opts = sourceNode.tree.options.dnd;
+				$nodeTag = $(sourceNode.span);
+				// Only event and node argument is available
+				$helper = $("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>")
+					.css({zIndex: 3, position: "relative"}) // so it appears above ext-wide selection bar
+					.append($nodeTag.find("span.fancytree-title").clone());
+
+				// Attach node reference to helper object
+				$helper.data("ftSourceNode", sourceNode);
+
+				// Support glyph symbols instead of icons
+				if( glyph ) {
+					$helper.find(".fancytree-drag-helper-img")
+						.addClass(glyph.map.dragHelper);
+				}
+				// Allow to modify the helper, e.g. to add multi-node-drag feedback
+				if( opts.initHelper ) {
+					opts.initHelper.call(sourceNode.tree, sourceNode, {
+						node: sourceNode,
+						tree: sourceNode.tree,
+						originalEvent: event,
+						ui: { helper: $helper }
+					});
+				}
+				// We return an unconnected element, so `draggable` will add this
+				// to the parent specified as `appendTo` option
+				return $helper;
+			},
+			start: function(event, ui) {
+				var sourceNode = ui.helper.data("ftSourceNode");
+				return !!sourceNode; // Abort dragging if no node could be found
+			}
+		}, tree.options.dnd.draggable));
+	}
+	// Attach ui.droppable to this Fancytree instance
+	if(dnd && dnd.dragDrop) {
+		tree.widget.element.droppable($.extend({
+			addClasses: false,
+			tolerance: "intersect",
+			greedy: false
+/*
+			activate: function(event, ui) {
+				tree.debug("droppable - activate", event, ui, this);
+			},
+			create: function(event, ui) {
+				tree.debug("droppable - create", event, ui);
+			},
+			deactivate: function(event, ui) {
+				tree.debug("droppable - deactivate", event, ui);
+			},
+			drop: function(event, ui) {
+				tree.debug("droppable - drop", event, ui);
+			},
+			out: function(event, ui) {
+				tree.debug("droppable - out", event, ui);
+			},
+			over: function(event, ui) {
+				tree.debug("droppable - over", event, ui);
+			}
+*/
+		}, tree.options.dnd.droppable));
+	}
+}
+
+//--- Extend ui.draggable event handling --------------------------------------
+
+function _registerDnd() {
+	if(didRegisterDnd){
+		return;
+	}
+
+	// Register proxy-functions for draggable.start/drag/stop
+
+	$.ui.plugin.add("draggable", "connectToFancytree", {
+		start: function(event, ui) {
+			// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+			var draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
+				sourceNode = ui.helper.data("ftSourceNode") || null;
+
+			if(sourceNode) {
+				// Adjust helper offset, so cursor is slightly outside top/left corner
+				draggable.offset.click.top = -2;
+				draggable.offset.click.left = + 16;
+				// Trigger dragStart event
+				// TODO: when called as connectTo..., the return value is ignored(?)
+				return sourceNode.tree.ext.dnd._onDragEvent("start", sourceNode, null, event, ui, draggable);
+			}
+		},
+		drag: function(event, ui) {
+			var ctx, isHelper, logObject,
+				// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+				draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
+				sourceNode = ui.helper.data("ftSourceNode") || null,
+				prevTargetNode = ui.helper.data("ftTargetNode") || null,
+				targetNode = $.ui.fancytree.getNode(event.target),
+				dndOpts = sourceNode && sourceNode.tree.options.dnd;
+
+			// logObject = sourceNode || prevTargetNode || $.ui.fancytree;
+			// logObject.debug("Drag event:", event, event.shiftKey);
+			if(event.target && !targetNode){
+				// We got a drag event, but the targetNode could not be found
+				// at the event location. This may happen,
+				// 1. if the mouse jumped over the drag helper,
+				// 2. or if a non-fancytree element is dragged
+				// We ignore it:
+				isHelper = $(event.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length > 0;
+				if(isHelper){
+					logObject = sourceNode || prevTargetNode || $.ui.fancytree;
+					logObject.debug("Drag event over helper: ignored.");
+					return;
+				}
+			}
+			ui.helper.data("ftTargetNode", targetNode);
+
+			if( dndOpts && dndOpts.updateHelper ) {
+				ctx = sourceNode.tree._makeHookContext(sourceNode, event, {
+					otherNode: targetNode,
+					ui: ui,
+					draggable: draggable,
+					dropMarker: $("#fancytree-drop-marker")
+				});
+				dndOpts.updateHelper.call(sourceNode.tree, sourceNode, ctx);
+			}
+
+			// Leaving a tree node
+			if(prevTargetNode && prevTargetNode !== targetNode ) {
+				prevTargetNode.tree.ext.dnd._onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
+			}
+			if(targetNode){
+				if(!targetNode.tree.options.dnd.dragDrop) {
+					// not enabled as drop target
+				} else if(targetNode === prevTargetNode) {
+					// Moving over same node
+					targetNode.tree.ext.dnd._onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
+				}else{
+					// Entering this node first time
+					targetNode.tree.ext.dnd._onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
+				}
+			}
+			// else go ahead with standard event handling
+		},
+		stop: function(event, ui) {
+			var logObject,
+				// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10:
+				draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
+				sourceNode = ui.helper.data("ftSourceNode") || null,
+				targetNode = ui.helper.data("ftTargetNode") || null,
+				dropped = (event.type === "mouseup" && event.which === 1);
+
+			if(!dropped){
+				logObject = sourceNode || targetNode || $.ui.fancytree;
+				logObject.debug("Drag was cancelled");
+			}
+			if(targetNode) {
+				if(dropped){
+					targetNode.tree.ext.dnd._onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
+				}
+				targetNode.tree.ext.dnd._onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
+			}
+			if(sourceNode){
+				sourceNode.tree.ext.dnd._onDragEvent("stop", sourceNode, null, event, ui, draggable);
+			}
+		}
+	});
+
+	didRegisterDnd = true;
+}
+
+
+/* *****************************************************************************
+ *
+ */
+
+$.ui.fancytree.registerExtension({
+	name: "dnd",
+	version: "0.2.0",
+	// Default options for this extension.
+	options: {
+		// Make tree nodes accept draggables
+		autoExpandMS: 1000,  // Expand nodes after n milliseconds of hovering.
+		draggable: null,     // Additional options passed to jQuery draggable
+		droppable: null,     // Additional options passed to jQuery droppable
+		focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
+		preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+		preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
+		smartRevert: true,   // set draggable.revert = true if drop was rejected
+		// Events (drag support)
+		dragStart: null,     // Callback(sourceNode, data), return true, to enable dnd
+		dragStop: null,      // Callback(sourceNode, data)
+		initHelper: null,    // Callback(sourceNode, data)
+		updateHelper: null,  // Callback(sourceNode, data)
+		// Events (drop support)
+		dragEnter: null,  // Callback(targetNode, data)
+		dragOver: null,   // Callback(targetNode, data)
+		dragDrop: null,   // Callback(targetNode, data)
+		dragLeave: null   // Callback(targetNode, data)
+	},
+
+	treeInit: function(ctx){
+		var tree = ctx.tree;
+		this._superApply(arguments);
+		// issue #270: draggable eats mousedown events
+		if( tree.options.dnd.dragStart ){
+			tree.$container.on("mousedown", function(event){
+//				if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) {
+				if( ctx.options.dnd.focusOnClick ) {  // #270
+					var node = $.ui.fancytree.getNode(event);
+					if (node){
+						node.debug("Re-enable focus that was prevented by jQuery UI draggable.");
+						// node.setFocus();
+						// $(node.span).closest(":tabbable").focus();
+						// $(event.target).trigger("focus");
+						// $(event.target).closest(":tabbable").trigger("focus");
+					}
+					setTimeout(function() { // #300
+						$(event.target).closest(":tabbable").focus();
+					}, 10);
+				}
+			});
+		}
+		_initDragAndDrop(tree);
+	},
+	/* Display drop marker according to hitMode ('after', 'before', 'over'). */
+	_setDndStatus: function(sourceNode, targetNode, helper, hitMode, accept) {
+		var markerOffsetX = 0,
+			markerAt = "center",
+			instData = this._local,
+			glyph = this.options.glyph || null,
+			$source = sourceNode ? $(sourceNode.span) : null,
+			$target = $(targetNode.span);
+
+		if( !instData.$dropMarker ) {
+			instData.$dropMarker = $("<div id='fancytree-drop-marker'></div>")
+				.hide()
+				.css({"z-index": 1000})
+				.prependTo($(this.$div).parent());
+//                .prependTo("body");
+
+			if( glyph ) {
+				// instData.$dropMarker.addClass(glyph.map.dragHelper);
+				instData.$dropMarker
+					.addClass(glyph.map.dropMarker);
+			}
+		}
+		if( hitMode === "after" || hitMode === "before" || hitMode === "over" ){
+			switch(hitMode){
+			case "before":
+				markerAt = "top";
+				break;
+			case "after":
+				markerAt = "bottom";
+				break;
+			default:
+				markerOffsetX = 8;
+			}
+
+			instData.$dropMarker
+				.toggleClass(classDropAfter, hitMode === "after")
+				.toggleClass(classDropOver, hitMode === "over")
+				.toggleClass(classDropBefore, hitMode === "before")
+				.show()
+				.position($.ui.fancytree.fixPositionOptions({
+					my: "left" + offsetString(markerOffsetX) + " center",
+					at: "left " + markerAt,
+					of: $target
+					}));
+		} else {
+			instData.$dropMarker.hide();
+		}
+		if( $source ){
+			$source
+				.toggleClass(classDropAccept, accept === true)
+				.toggleClass(classDropReject, accept === false);
+		}
+		$target
+			.toggleClass(classDropTarget, hitMode === "after" || hitMode === "before" || hitMode === "over")
+			.toggleClass(classDropAfter, hitMode === "after")
+			.toggleClass(classDropBefore, hitMode === "before")
+			.toggleClass(classDropAccept, accept === true)
+			.toggleClass(classDropReject, accept === false);
+
+		helper
+			.toggleClass(classDropAccept, accept === true)
+			.toggleClass(classDropReject, accept === false);
+	},
+
+	/*
+	 * Handles drag'n'drop functionality.
+	 *
+	 * A standard jQuery drag-and-drop process may generate these calls:
+	 *
+	 * start:
+	 *     _onDragEvent("start", sourceNode, null, event, ui, draggable);
+	 * drag:
+	 *     _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
+	 * stop:
+	 *     _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("stop", sourceNode, null, event, ui, draggable);
+	 */
+	_onDragEvent: function(eventName, node, otherNode, event, ui, draggable) {
+		if(eventName !== "over"){
+			this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
+		}
+		var accept, nodeOfs, relPos, relPos2,
+			enterResponse, hitMode, r,
+			opts = this.options,
+			dnd = opts.dnd,
+			ctx = this._makeHookContext(node, event, {otherNode: otherNode, ui: ui, draggable: draggable}),
+			res = null,
+			that = this,
+			$nodeTag = $(node.span);
+
+		if( dnd.smartRevert ) {
+			draggable.options.revert = "invalid";
+		}
+
+		switch (eventName) {
+
+		case "start":
+			if( node.isStatusNode() ) {
+				res = false;
+			} else if(dnd.dragStart) {
+				res = dnd.dragStart(node, ctx);
+			}
+			if(res === false) {
+				this.debug("tree.dragStart() cancelled");
+				//draggable._clear();
+				// NOTE: the return value seems to be ignored (drag is not canceled, when false is returned)
+				// TODO: call this._cancelDrag()?
+				ui.helper.trigger("mouseup")
+					.hide();
+			} else {
+				$nodeTag.addClass("fancytree-drag-source");
+				// Register global handlers to allow cancel
+				$(document)
+					.on("keydown.fancytree-dnd,mousedown.fancytree-dnd", function(event){
+						// node.tree.debug("dnd global event", event.type, event.which);
+						if( event.type === "keydown" && event.which === $.ui.keyCode.ESCAPE ) {
+							that.ext.dnd._cancelDrag();
+						} else if( event.type === "mousedown" ) {
+							that.ext.dnd._cancelDrag();
+						}
+					});
+			}
+			break;
+
+		case "enter":
+			if(dnd.preventRecursiveMoves && node.isDescendantOf(otherNode)){
+				r = false;
+			}else{
+				r = dnd.dragEnter ? dnd.dragEnter(node, ctx) : null;
+			}
+			if(!r){
+				// convert null, undefined, false to false
+				res = false;
+			}else if ( $.isArray(r) ) {
+				// TODO: also accept passing an object of this format directly
+				res = {
+					over: ($.inArray("over", r) >= 0),
+					before: ($.inArray("before", r) >= 0),
+					after: ($.inArray("after", r) >= 0)
+				};
+			}else{
+				res = {
+					over: ((r === true) || (r === "over")),
+					before: ((r === true) || (r === "before")),
+					after: ((r === true) || (r === "after"))
+				};
+			}
+			ui.helper.data("enterResponse", res);
+			this.debug("helper.enterResponse: %o", res);
+			break;
+
+		case "over":
+			enterResponse = ui.helper.data("enterResponse");
+			hitMode = null;
+			if(enterResponse === false){
+				// Don't call dragOver if onEnter returned false.
+//                break;
+			} else if(typeof enterResponse === "string") {
+				// Use hitMode from onEnter if provided.
+				hitMode = enterResponse;
+			} else {
+				// Calculate hitMode from relative cursor position.
+				nodeOfs = $nodeTag.offset();
+				relPos = { x: event.pageX - nodeOfs.left,
+						   y: event.pageY - nodeOfs.top };
+				relPos2 = { x: relPos.x / $nodeTag.width(),
+							y: relPos.y / $nodeTag.height() };
+
+				if( enterResponse.after && relPos2.y > 0.75 ){
+					hitMode = "after";
+				} else if(!enterResponse.over && enterResponse.after && relPos2.y > 0.5 ){
+					hitMode = "after";
+				} else if(enterResponse.before && relPos2.y <= 0.25) {
+					hitMode = "before";
+				} else if(!enterResponse.over && enterResponse.before && relPos2.y <= 0.5) {
+					hitMode = "before";
+				} else if(enterResponse.over) {
+					hitMode = "over";
+				}
+				// Prevent no-ops like 'before source node'
+				// TODO: these are no-ops when moving nodes, but not in copy mode
+				if( dnd.preventVoidMoves ){
+					if(node === otherNode){
+						this.debug("    drop over source node prevented");
+						hitMode = null;
+					}else if(hitMode === "before" && otherNode && node === otherNode.getNextSibling()){
+						this.debug("    drop after source node prevented");
+						hitMode = null;
+					}else if(hitMode === "after" && otherNode && node === otherNode.getPrevSibling()){
+						this.debug("    drop before source node prevented");
+						hitMode = null;
+					}else if(hitMode === "over" && otherNode && otherNode.parent === node && otherNode.isLastSibling() ){
+						this.debug("    drop last child over own parent prevented");
+						hitMode = null;
+					}
+				}
+//                this.debug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
+				ui.helper.data("hitMode", hitMode);
+			}
+			// Auto-expand node (only when 'over' the node, not 'before', or 'after')
+			if(hitMode === "over" && dnd.autoExpandMS && node.hasChildren() !== false && !node.expanded) {
+				node.scheduleAction("expand", dnd.autoExpandMS);
+			}
+			if(hitMode && dnd.dragOver){
+				// TODO: http://code.google.com/p/dynatree/source/detail?r=625
+				ctx.hitMode = hitMode;
+				res = dnd.dragOver(node, ctx);
+			}
+			accept = (res !== false && hitMode !== null);
+			if( dnd.smartRevert ) {
+				draggable.options.revert = !accept;
+			}
+			this._local._setDndStatus(otherNode, node, ui.helper, hitMode, accept);
+			break;
+
+		case "drop":
+			hitMode = ui.helper.data("hitMode");
+			if(hitMode && dnd.dragDrop){
+				ctx.hitMode = hitMode;
+				dnd.dragDrop(node, ctx);
+			}
+			break;
+
+		case "leave":
+			// Cancel pending expand request
+			node.scheduleAction("cancel");
+			ui.helper.data("enterResponse", null);
+			ui.helper.data("hitMode", null);
+			this._local._setDndStatus(otherNode, node, ui.helper, "out", undefined);
+			if(dnd.dragLeave){
+				dnd.dragLeave(node, ctx);
+			}
+			break;
+
+		case "stop":
+			$nodeTag.removeClass("fancytree-drag-source");
+			$(document).off(".fancytree-dnd");
+			if(dnd.dragStop){
+				dnd.dragStop(node, ctx);
+			}
+			break;
+
+		default:
+			$.error("Unsupported drag event: " + eventName);
+		}
+		return res;
+	},
+
+	_cancelDrag: function() {
+		 var dd = $.ui.ddmanager.current;
+		 if(dd){
+			 dd.cancel();
+		 }
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.edit.js
+ *
+ * Make node titles editable.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+
+var isMac = /Mac/.test(navigator.platform),
+	escapeHtml = $.ui.fancytree.escapeHtml,
+	unescapeHtml = $.ui.fancytree.unescapeHtml;
+
+/**
+ * [ext-edit] Start inline editing of current node title.
+ *
+ * @alias FancytreeNode#editStart
+ * @requires Fancytree
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.editStart = function(){
+	var $input,
+		node = this,
+		tree = this.tree,
+		local = tree.ext.edit,
+		instOpts = tree.options.edit,
+		$title = $(".fancytree-title", node.span),
+		eventData = {
+			node: node,
+			tree: tree,
+			options: tree.options,
+			isNew: $(node[tree.statusClassPropName]).hasClass("fancytree-edit-new"),
+			orgTitle: node.title,
+			input: null,
+			dirty: false
+			};
+
+	// beforeEdit may want to modify the title before editing
+	if( instOpts.beforeEdit.call(node, {type: "beforeEdit"}, eventData) === false ) {
+		return false;
+	}
+	$.ui.fancytree.assert(!local.currentNode, "recursive edit");
+	local.currentNode = this;
+	local.eventData = eventData;
+
+	// Disable standard Fancytree mouse- and key handling
+	tree.widget._unbind();
+	// #116: ext-dnd prevents the blur event, so we have to catch outer clicks
+	$(document).on("mousedown.fancytree-edit", function(event){
+		if( ! $(event.target).hasClass("fancytree-edit-input") ){
+			node.editEnd(true, event);
+		}
+	});
+
+	// Replace node with <input>
+	$input = $("<input />", {
+		"class": "fancytree-edit-input",
+		type: "text",
+		value: unescapeHtml(eventData.orgTitle)
+	});
+	local.eventData.input = $input;
+	if ( instOpts.adjustWidthOfs != null ) {
+		$input.width($title.width() + instOpts.adjustWidthOfs);
+	}
+	if ( instOpts.inputCss != null ) {
+		$input.css(instOpts.inputCss);
+	}
+
+	$title.html($input);
+
+	// Focus <input> and bind keyboard handler
+	$input
+		.focus()
+		.change(function(event){
+			$input.addClass("fancytree-edit-dirty");
+		}).keydown(function(event){
+			switch( event.which ) {
+			case $.ui.keyCode.ESCAPE:
+				node.editEnd(false, event);
+				break;
+			case $.ui.keyCode.ENTER:
+				node.editEnd(true, event);
+				return false; // so we don't start editmode on Mac
+			}
+			event.stopPropagation();
+		}).blur(function(event){
+			return node.editEnd(true, event);
+		});
+
+	instOpts.edit.call(node, {type: "edit"}, eventData);
+};
+
+
+/**
+ * [ext-edit] Stop inline editing.
+ * @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified)
+ * @alias FancytreeNode#editEnd
+ * @requires jquery.fancytree.edit.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function(applyChanges, _event){
+	var newVal,
+		node = this,
+		tree = this.tree,
+		local = tree.ext.edit,
+		eventData = local.eventData,
+		instOpts = tree.options.edit,
+		$title = $(".fancytree-title", node.span),
+		$input = $title.find("input.fancytree-edit-input");
+
+	// eventData.isNew = $(node[tree.statusClassPropName]).hasClass("fancytree-edit-new");
+
+	if( instOpts.trim ) {
+		$input.val($.trim($input.val()));
+	}
+	newVal = $input.val();
+	// eventData.dirty = $input.hasClass("fancytree-edit-dirty") || ;
+	eventData.dirty = ( newVal !== node.title );
+
+	// Find out, if saving is required
+	if( applyChanges === false ) {
+		// If true/false was passed, honor this (except in rename mode, if unchanged)
+		eventData.save = false;
+	} else if( eventData.isNew ) {
+		// In create mode, we save everyting, except for empty text
+		eventData.save = (newVal !== "");
+	} else {
+		// In rename mode, we save everyting, except for empty or unchanged text
+		eventData.save = eventData.dirty && (newVal !== "");
+	}
+	// Allow to break (keep editor open), modify input, or re-define data.save
+	if( instOpts.beforeClose.call(node, {type: "beforeClose"}, eventData) === false){
+		return false;
+	}
+	if( eventData.save && instOpts.save.call(node, {type: "save"}, eventData) === false){
+		return false;
+	}
+	$input
+		.removeClass("fancytree-edit-dirty")
+		.unbind();
+	// Unbind outer-click handler
+	$(document).off(".fancytree-edit");
+
+	if( eventData.save ) {
+		node.setTitle( escapeHtml(newVal) );
+		// $(node[tree.statusClassPropName]).removeClass("fancytree-edit-new");
+		node.setFocus();
+	}else{
+		if( eventData.isNew ) {
+			node.remove();
+			node = eventData.node = null;
+			local.relatedNode.setFocus();
+		} else {
+			node.renderTitle();
+			node.setFocus();
+		}
+	}
+	local.eventData = null;
+	local.currentNode = null;
+	local.relatedNode = null;
+	// Re-enable mouse and keyboard handling
+	tree.widget._bind();
+	// Set keyboard focus, even if setFocus() claims 'nothing to do'
+	$(tree.$container).focus();
+	eventData.input = null;
+	instOpts.close.call(node, {type: "close"}, eventData);
+	return true;
+};
+
+
+/**
+* [ext-edit] Create a new child or sibling node and start edit mode.
+*
+* @param {String} [mode='child'] 'before', 'after', or 'child'
+* @param {Object} [init] NodeData (or simple title string)
+* @alias FancytreeNode#editCreateNode
+* @requires jquery.fancytree.edit.js
+* @since 2.4
+*/
+$.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function(mode, init){
+	var newNode,
+		tree = this.tree,
+		self = this;
+
+	mode = mode || "child";
+	if( init == null ) {
+		init = { title: "" };
+	} else if( typeof init === "string" ) {
+		init = { title: init };
+	} else {
+		$.ui.fancytree.assert($.isPlainObject(init));
+	}
+	// Make sure node is expanded (and loaded) in 'child' mode
+	if( mode === "child" && !this.isExpanded() && this.hasChildren() !== false ) {
+		this.setExpanded().done(function(){
+			self.editCreateNode(mode, init);
+		});
+		return;
+	}
+	newNode = this.addNode(init, mode);
+	newNode.makeVisible(/*{noAnimation: true}*/).done(function(){
+		$(newNode[tree.statusClassPropName]).addClass("fancytree-edit-new");
+		self.tree.ext.edit.relatedNode = self;
+		newNode.editStart();
+	});
+};
+
+
+/**
+ * [ext-edit] Check if any node in this tree  in edit mode.
+ *
+ * @returns {FancytreeNode | null}
+ * @alias Fancytree#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.isEditing = function(){
+	return this.ext.edit.currentNode;
+};
+
+
+/**
+ * [ext-edit] Check if this node is in edit mode.
+ * @returns {Boolean} true if node is currently beeing edited
+ * @alias FancytreeNode#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function(){
+	return this.tree.ext.edit.currentNode === this;
+};
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "edit",
+	version: "0.2.0",
+	// Default options for this extension.
+	options: {
+		adjustWidthOfs: 4,   // null: don't adjust input size to content
+		allowEmpty: false,   // Prevent empty input
+		inputCss: {minWidth: "3em"},
+		triggerCancel: ["esc", "tab", "click"],
+		// triggerStart: ["f2", "dblclick", "shift+click", "mac+enter"],
+		triggerStart: ["f2", "shift+click", "mac+enter"],
+		trim: true,          // Trim whitespace before save
+		// Events:
+		beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available)
+		beforeEdit: $.noop,  // Return false to prevent edit mode
+		close: $.noop,       // Editor was removed
+		edit: $.noop,        // Editor was opened (available as data.input)
+//		keypress: $.noop,    // Not yet implemented
+		save: $.noop         // Save data.input.val() or return false to keep editor open
+	},
+	// Local attributes
+	currentNode: null,
+
+	treeInit: function(ctx){
+		this._superApply(arguments);
+		this.$container.addClass("fancytree-ext-edit");
+	},
+	nodeClick: function(ctx) {
+		if( $.inArray("shift+click", ctx.options.edit.triggerStart) >= 0 ){
+			if( ctx.originalEvent.shiftKey ){
+				ctx.node.editStart();
+				return false;
+			}
+		}
+		return this._superApply(arguments);
+	},
+	nodeDblclick: function(ctx) {
+		if( $.inArray("dblclick", ctx.options.edit.triggerStart) >= 0 ){
+			ctx.node.editStart();
+			return false;
+		}
+		return this._superApply(arguments);
+	},
+	nodeKeydown: function(ctx) {
+		switch( ctx.originalEvent.which ) {
+		case 113: // [F2]
+			if( $.inArray("f2", ctx.options.edit.triggerStart) >= 0 ){
+				ctx.node.editStart();
+				return false;
+			}
+			break;
+		case $.ui.keyCode.ENTER:
+			if( $.inArray("mac+enter", ctx.options.edit.triggerStart) >= 0 && isMac ){
+				ctx.node.editStart();
+				return false;
+			}
+			break;
+		}
+		return this._superApply(arguments);
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.filter.js
+ *
+ * Remove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+
+function _escapeRegex(str){
+	/*jshint regexdash:true */
+	return (str + "").replace(/([.?*+\^\$\[\]\\(){}|-])/g, "\\$1");
+}
+
+$.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function(filter, branchMode, opts){
+	var leavesOnly, match, re, re2,
+		count = 0,
+		filterOpts = this.options.filter,
+		hideMode = filterOpts.mode === "hide";
+
+	opts = opts || {};
+	leavesOnly = !!opts.leavesOnly && !branchMode;
+
+	// Default to 'match title substring (not case sensitive)'
+	if(typeof filter === "string"){
+		// console.log("rex", filter.split('').join('\\w*').replace(/\W/, ""))
+		if( filterOpts.fuzzy ) {
+			// See https://codereview.stackexchange.com/questions/23899/faster-javascript-fuzzy-string-matching-function/23905#23905
+			// and http://www.quora.com/How-is-the-fuzzy-search-algorithm-in-Sublime-Text-designed
+			// and http://www.dustindiaz.com/autocomplete-fuzzy-matching
+			match = filter.split("").reduce(function(a, b) {
+				return a + "[^" + b + "]*" + b;
+			});
+		} else {
+			match = _escapeRegex(filter); // make sure a '.' is treated literally
+		}
+		re = new RegExp(".*" + match + ".*", "i");
+		re2 = new RegExp(filter, "gi");
+		filter = function(node){
+			var res = !!re.test(node.title);
+			// node.debug("filter res", res, filterOpts.highlight)
+			if( res && filterOpts.highlight ) {
+				node.titleWithHighlight = node.title.replace(re2, function(s){
+					return "<mark>" + s + "</mark>";
+				});
+			// } else {
+			// 	delete node.titleWithHighlight;
+			}
+			return res;
+		};
+	}
+
+	this.enableFilter = true;
+	this.lastFilterArgs = arguments;
+
+	this.$div.addClass("fancytree-ext-filter");
+	if( hideMode ){
+		this.$div.addClass("fancytree-ext-filter-hide");
+	} else {
+		this.$div.addClass("fancytree-ext-filter-dimm");
+	}
+	// Reset current filter
+	this.visit(function(node){
+		delete node.match;
+		delete node.titleWithHighlight;
+		node.subMatchCount = 0;
+	});
+	// Adjust node.hide, .match, and .subMatchCount properties
+	this.visit(function(node){
+		if ((!leavesOnly || node.children == null) && filter(node)) {
+			count++;
+			node.match = true;
+			node.visitParents(function(p){
+				p.subMatchCount += 1;
+				if( opts.autoExpand && !p.expanded ) {
+					p.setExpanded(true, {noAnimation: true, noEvents: true, scrollIntoView: false});
+					p._filterAutoExpanded = true;
+				}
+			});
+			if( branchMode ) {
+				node.visit(function(p){
+					p.match = true;
+				});
+				return "skip";
+			}
+		}
+	});
+	// Redraw whole tree
+	this.render();
+	return count;
+};
+
+/**
+ * [ext-filter] Dimm or hide nodes.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false, leavesOnly: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterNodes
+ * @requires jquery.fancytree.filter.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.filterNodes = function(filter, opts) {
+	if( typeof opts === "boolean" ) {
+		opts = { leavesOnly: opts };
+		this.warn("Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19.");
+	}
+	return this._applyFilterImpl(filter, false, opts);
+};
+
+/**
+ * @deprecated
+ */
+$.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
+	this.warn("Fancytree.applyFilter() is deprecated since 2.1.0 / 2014-05-29. Use .filterNodes() instead.");
+	return this.filterNodes.apply(this, arguments);
+};
+
+/**
+ * [ext-filter] Dimm or hide whole branches.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterBranches
+ * @requires jquery.fancytree.filter.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.filterBranches = function(filter, opts){
+	return this._applyFilterImpl(filter, true, opts);
+};
+
+
+/**
+ * [ext-filter] Reset the filter.
+ *
+ * @alias Fancytree#clearFilter
+ * @requires jquery.fancytree.filter.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.clearFilter = function(){
+	this.visit(function(node){
+		if( node.match ) {  // #491
+			$(">span.fancytree-title", node.span).html(node.title);
+		}
+		delete node.match;
+		delete node.subMatchCount;
+		delete node.titleWithHighlight;
+		if ( node.$subMatchBadge ) {
+			node.$subMatchBadge.remove();
+			delete node.$subMatchBadge;
+		}
+		if( node._filterAutoExpanded && node.expanded ) {
+			node.setExpanded(false, {noAnimation: true, noEvents: true, scrollIntoView: false});
+		}
+		delete node._filterAutoExpanded;
+	});
+	this.enableFilter = false;
+	this.lastFilterArgs = null;
+	this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide");
+	this.render();
+};
+
+
+/**
+ * [ext-filter] Return true if a filter is currently applied.
+ *
+ * @returns {Boolean}
+ * @alias Fancytree#isFilterActive
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+$.ui.fancytree._FancytreeClass.prototype.isFilterActive = function(){
+	return !!this.enableFilter;
+};
+
+
+/**
+ * [ext-filter] Return true if this node is matched by current filter (or no filter is active).
+ *
+ * @returns {Boolean}
+ * @alias FancytreeNode#isMatched
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.isMatched = function(){
+	return !(this.tree.enableFilter && !this.match);
+};
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "filter",
+	version: "0.7.0",
+	// Default options for this extension.
+	options: {
+		autoApply: true,  // Re-apply last filter if lazy data is loaded
+		counter: true,  // Show a badge with number of matching child nodes near parent icons
+		fuzzy: false,  // Match single characters in order, e.g. 'fb' will match 'FooBar'
+		hideExpandedCounter: true,  // Hide counter badge, when parent is expanded
+		highlight: true,  // Highlight matches by wrapping inside <mark> tags
+		mode: "dimm"  // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
+	},
+	// treeCreate: function(ctx){
+	// 	this._superApply(arguments);
+	// 	console.log("create")
+	// 	ctx.tree.options.renderTitle = function(event, data) {
+	// 		var node = data.node;
+	// 		console.log("create n", node.titleWithHighlight, data.tree.enableFilter)
+	// 		if( node.titleWithHighlight && node.tree.enableFilter ) {
+	// 			return node.titleWithHighlight;
+	// 		}
+	// 	}
+	// },
+	// treeInit: function(ctx){
+	// 	this._superApply(arguments);
+	// },
+	nodeLoadChildren: function(ctx, source) {
+		return this._superApply(arguments).done(function() {
+			if( ctx.tree.enableFilter && ctx.tree.lastFilterArgs && ctx.options.filter.autoApply ) {
+				ctx.tree._applyFilterImpl.apply(ctx.tree, ctx.tree.lastFilterArgs);
+			}
+		});
+	},
+	nodeSetExpanded: function(ctx, flag, callOpts) {
+		delete ctx.node._filterAutoExpanded;
+		// Make sure counter badge is displayed again, when node is beeing collapsed
+		if( !flag && ctx.options.filter.hideExpandedCounter && ctx.node.$subMatchBadge ) {
+			ctx.node.$subMatchBadge.show();
+		}
+		return this._superApply(arguments);
+	},
+	nodeRenderStatus: function(ctx) {
+		// Set classes for current status
+		var res,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options.filter,
+			$span = $(node[tree.statusClassPropName]);
+
+		res = this._superApply(arguments);
+		// nothing to do, if node was not yet rendered
+		if( !$span.length || !tree.enableFilter ) {
+			return res;
+		}
+		$span
+			.toggleClass("fancytree-match", !!node.match)
+			.toggleClass("fancytree-submatch", !!node.subMatchCount)
+			.toggleClass("fancytree-hide", !(node.match || node.subMatchCount));
+		// Add/update counter badge
+		if( opts.counter && node.subMatchCount && (!node.isExpanded() || !opts.hideExpandedCounter) ) {
+			if( !node.$subMatchBadge ) {
+				node.$subMatchBadge = $("<span class='fancytree-childcounter'/>");
+				$("span.fancytree-icon", node.span).append(node.$subMatchBadge);
+			}
+			node.$subMatchBadge.show().text(node.subMatchCount);
+		} else if ( node.$subMatchBadge ) {
+			node.$subMatchBadge.hide();
+		}
+		// node.debug("nodeRenderStatus", node.titleWithHighlight, node.title)
+		if( node.titleWithHighlight ) {
+			$("span.fancytree-title", node.span).html(node.titleWithHighlight);
+		} else {
+			$("span.fancytree-title", node.span).html(node.title);
+		}
+		return res;
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.glyph.js
+ *
+ * Use glyph fonts as instead of icon sprites.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+
+function _getIcon(opts, type){
+	return opts.map[type];
+}
+
+$.ui.fancytree.registerExtension({
+	name: "glyph",
+	version: "0.3.0",
+	// Default options for this extension.
+	options: {
+		map: {
+			// Samples from Font Awesome 3.2
+			//   http://fortawesome.github.io/Font-Awesome/3.2.1/icons/
+			// See here for alternatives:
+			//   http://fortawesome.github.io/Font-Awesome/icons/
+			//   http://getbootstrap.com/components/
+			checkbox: "icon-check-empty",
+			checkboxSelected: "icon-check",
+			checkboxUnknown: "icon-check icon-muted",
+			error: "icon-exclamation-sign",
+			expanderClosed: "icon-caret-right",
+			expanderLazy: "icon-angle-right",
+			expanderOpen: "icon-caret-down",
+			noExpander: "",
+			dragHelper: "icon-caret-right",
+			dropMarker: "icon-caret-right",
+			// Default node icons.
+			// (Use tree.options.iconClass callback to define custom icons
+			// based on node data)
+			doc: "icon-file-alt",
+			docOpen: "icon-file-alt",
+			loading: "icon-refresh icon-spin",
+			folder: "icon-folder-close-alt",
+			folderOpen: "icon-folder-open-alt"
+		}
+	},
+
+	treeInit: function(ctx){
+		var tree = ctx.tree;
+		this._superApply(arguments);
+		tree.$container.addClass("fancytree-ext-glyph");
+	},
+	nodeRenderStatus: function(ctx) {
+		var icon, span,
+			node = ctx.node,
+			$span = $(node.span),
+			opts = ctx.options.glyph,
+			// callback = opts.icon,
+			map = opts.map
+			// $span = $(node.span)
+			;
+
+		this._superApply(arguments);
+
+		if( node.isRoot() ){
+			return;
+		}
+		span = $span.children("span.fancytree-expander").get(0);
+		if( span ){
+			if( node.isLoading() ){
+				icon = "loading";
+			}else if( node.expanded ){
+				icon = "expanderOpen";
+			}else if( node.isUndefined() ){
+				icon = "expanderLazy";
+			}else if( node.hasChildren() ){
+				icon = "expanderClosed";
+			}else{
+				icon = "noExpander";
+			}
+			span.className = "fancytree-expander " + map[icon];
+		}
+
+		if( node.tr ){
+			span = $("td", node.tr).find("span.fancytree-checkbox").get(0);
+		}else{
+			span = $span.children("span.fancytree-checkbox").get(0);
+		}
+		if( span ){
+			icon = node.selected ? "checkboxSelected" : (node.partsel ? "checkboxUnknown" : "checkbox");
+			span.className = "fancytree-checkbox " + map[icon];
+		}
+
+		// Icon (note that this does not match .fancytree-custom-icon, that might
+		// be set by opts.iconClass)
+		span = $span.children("span.fancytree-icon").get(0);
+		if( span ){
+			if( node.folder ){
+				icon = node.expanded ? _getIcon(opts, "folderOpen") : _getIcon(opts, "folder");
+			}else{
+				icon = node.expanded ? _getIcon(opts, "docOpen") : _getIcon(opts, "doc");
+			}
+			span.className = "fancytree-icon " + icon;
+		}
+	},
+	nodeSetStatus: function(ctx, status, message, details) {
+		var span,
+			opts = ctx.options.glyph,
+			node = ctx.node;
+
+		this._superApply(arguments);
+
+		if(node.parent){
+			span = $("span.fancytree-expander", node.span).get(0);
+		}else{
+			span = $(".fancytree-statusnode-wait, .fancytree-statusnode-error", node[this.nodeContainerAttrName])
+				.find("span.fancytree-expander").get(0);
+		}
+		if( status === "loading"){
+			// $("span.fancytree-expander", ctx.node.span).addClass(_getIcon(opts, "loading"));
+			span.className = "fancytree-expander " + _getIcon(opts, "loading");
+		}else if( status === "error"){
+			span.className = "fancytree-expander " + _getIcon(opts, "error");
+		}
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.gridnav.js
+ *
+ * Support keyboard navigation for trees with embedded input controls.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+
+// Allow these navigation keys even when input controls are focused
+
+var	KC = $.ui.keyCode,
+	// which keys are *not* handled by embedded control, but passed to tree
+	// navigation handler:
+	NAV_KEYS = {
+		"text": [KC.UP, KC.DOWN],
+		"checkbox": [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+		"radiobutton": [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+		"select-one": [KC.LEFT, KC.RIGHT],
+		"select-multiple": [KC.LEFT, KC.RIGHT]
+	};
+
+
+/* Calculate TD column index (considering colspans).*/
+function getColIdx($tr, $td) {
+	var colspan,
+		td = $td.get(0),
+		idx = 0;
+
+	$tr.children().each(function () {
+		if( this === td ) {
+			return false;
+		}
+		colspan = $(this).prop("colspan");
+		idx += colspan ? colspan : 1;
+	});
+	return idx;
+}
+
+
+/* Find TD at given column index (considering colspans).*/
+function findTdAtColIdx($tr, colIdx) {
+	var colspan,
+		res = null,
+		idx = 0;
+
+	$tr.children().each(function () {
+		if( idx >= colIdx ) {
+			res = $(this);
+			return false;
+		}
+		colspan = $(this).prop("colspan");
+		idx += colspan ? colspan : 1;
+	});
+	return res;
+}
+
+
+/* Find adjacent cell for a given direction. Skip empty cells and consider merged cells */
+function findNeighbourTd($target, keyCode){
+	var $tr, colIdx,
+		$td = $target.closest("td"),
+		$tdNext = null;
+
+	switch( keyCode ){
+		case KC.LEFT:
+			$tdNext = $td.prev();
+			break;
+		case KC.RIGHT:
+			$tdNext = $td.next();
+			break;
+		case KC.UP:
+		case KC.DOWN:
+			$tr = $td.parent();
+			colIdx = getColIdx($tr, $td);
+			while( true ) {
+				$tr = (keyCode === KC.UP) ? $tr.prev() : $tr.next();
+				if( !$tr.length ) {
+					break;
+				}
+				// Skip hidden rows
+				if( $tr.is(":hidden") ) {
+					continue;
+				}
+				// Find adjacent cell in the same column
+				$tdNext = findTdAtColIdx($tr, colIdx);
+				// Skip cells that don't conatain a focusable element
+				if( $tdNext && $tdNext.find(":input").length ) {
+					break;
+				}
+			}
+			break;
+	}
+	return $tdNext;
+}
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "gridnav",
+	version: "0.0.1",
+	// Default options for this extension.
+	options: {
+		autofocusInput:   false,  // Focus first embedded input if node gets activated
+		handleCursorKeys: true   // Allow UP/DOWN in inputs to move to prev/next node
+	},
+
+	treeInit: function(ctx){
+		// gridnav requires the table extension to be loaded before itself
+		this._requireExtension("table", true, true);
+		this._superApply(arguments);
+
+		this.$container.addClass("fancytree-ext-gridnav");
+
+		// Activate node if embedded input gets focus (due to a click)
+		this.$container.on("focusin", function(event){
+			var ctx2,
+				node = $.ui.fancytree.getNode(event.target);
+
+			if( node && !node.isActive() ){
+				// Call node.setActive(), but also pass the event
+				ctx2 = ctx.tree._makeHookContext(node, event);
+				ctx.tree._callHook("nodeSetActive", ctx2, true);
+			}
+		});
+	},
+	nodeSetActive: function(ctx, flag) {
+		var $outer,
+			opts = ctx.options.gridnav,
+			node = ctx.node,
+			event = ctx.originalEvent || {},
+			triggeredByInput = $(event.target).is(":input");
+
+		flag = (flag !== false);
+
+		this._superApply(arguments);
+
+		if( flag ){
+			if( ctx.options.titlesTabbable ){
+				if( !triggeredByInput ) {
+					$(node.span).find("span.fancytree-title").focus();
+					node.setFocus();
+				}
+				// If one node is tabbable, the container no longer needs to be
+				ctx.tree.$container.attr("tabindex", "-1");
+				// ctx.tree.$container.removeAttr("tabindex");
+			} else if( opts.autofocusInput && !triggeredByInput ){
+				// Set focus to input sub input (if node was clicked, but not
+				// when TAB was pressed )
+				$outer = $(node.tr || node.span);
+				$outer.find(":input:enabled:first").focus();
+			}
+		}
+	},
+	nodeKeydown: function(ctx) {
+		var inputType, handleKeys, $td,
+			opts = ctx.options.gridnav,
+			event = ctx.originalEvent,
+			$target = $(event.target);
+
+		// jQuery
+		inputType = $target.is(":input:enabled") ? $target.prop("type") : null;
+//		ctx.tree.debug("ext-gridnav nodeKeydown", event, inputType);
+
+		if( inputType && opts.handleCursorKeys ){
+			handleKeys = NAV_KEYS[inputType];
+			if( handleKeys && $.inArray(event.which, handleKeys) >= 0 ){
+				$td = findNeighbourTd($target, event.which);
+				// ctx.node.debug("ignore keydown in input", event.which, handleKeys);
+				if( $td && $td.length ) {
+					$td.find(":input:enabled").focus();
+					// Prevent Fancytree default navigation
+					return false;
+				}
+			}
+			return true;
+		}
+		// ctx.tree.debug("ext-gridnav NOT HANDLED", event, inputType);
+		return this._superApply(arguments);
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.persist.js
+ *
+ * Persist tree status in cookiesRemove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @depends: js-cookie or jquery-cookie
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+/* global Cookies:false */
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+var cookieGetter, cookieRemover, cookieSetter,
+	_assert = $.ui.fancytree.assert,
+	ACTIVE = "active",
+	EXPANDED = "expanded",
+	FOCUS = "focus",
+	SELECTED = "selected";
+
+if( typeof Cookies === "function" ) {
+	// Assume https://github.com/js-cookie/js-cookie
+	cookieSetter = Cookies.set;
+	cookieGetter = Cookies.get;
+	cookieRemover = Cookies.remove;
+} else {
+	// Fall back to https://github.com/carhartl/jquery-cookie
+	cookieSetter = cookieGetter = $.cookie;
+	cookieRemover = $.removeCookie;
+}
+
+/* Recursively load lazy nodes
+ * @param {string} mode 'load', 'expand', false
+ */
+function _loadLazyNodes(tree, local, keyList, mode, dfd) {
+	var i, key, l, node,
+		foundOne = false,
+		deferredList = [],
+		missingKeyList = [];
+
+	keyList = keyList || [];
+	dfd = dfd || $.Deferred();
+
+	for( i=0, l=keyList.length; i<l; i++ ) {
+		key = keyList[i];
+		node = tree.getNodeByKey(key);
+		if( node ) {
+			if( mode && node.isUndefined() ) {
+				foundOne = true;
+				tree.debug("_loadLazyNodes: " + node + " is lazy: loading...");
+				if( mode === "expand" ) {
+					deferredList.push(node.setExpanded());
+				} else {
+					deferredList.push(node.load());
+				}
+			} else {
+				tree.debug("_loadLazyNodes: " + node + " already loaded.");
+				node.setExpanded();
+			}
+		} else {
+			missingKeyList.push(key);
+			tree.debug("_loadLazyNodes: " + node + " was not yet found.");
+		}
+	}
+
+	$.when.apply($, deferredList).always(function(){
+		// All lazy-expands have finished
+		if( foundOne && missingKeyList.length > 0 ) {
+			// If we read new nodes from server, try to resolve yet-missing keys
+			_loadLazyNodes(tree, local, missingKeyList, mode, dfd);
+		} else {
+			if( missingKeyList.length ) {
+				tree.warn("_loadLazyNodes: could not load those keys: ", missingKeyList);
+				for( i=0, l=missingKeyList.length; i<l; i++ ) {
+					key = keyList[i];
+					local._appendKey(EXPANDED, keyList[i], false);
+				}
+			}
+			dfd.resolve();
+		}
+	});
+	return dfd;
+}
+
+
+/**
+ * [ext-persist] Remove persistence cookies of the given type(s).
+ * Called like
+ *     $("#tree").fancytree("getTree").clearCookies("active expanded focus selected");
+ *
+ * @alias Fancytree#clearCookies
+ * @requires jquery.fancytree.persist.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.clearCookies = function(types){
+	var local = this.ext.persist,
+		prefix = local.cookiePrefix;
+
+	types = types || "active expanded focus selected";
+	if(types.indexOf(ACTIVE) >= 0){
+		local._data(prefix + ACTIVE, null);
+	}
+	if(types.indexOf(EXPANDED) >= 0){
+		local._data(prefix + EXPANDED, null);
+	}
+	if(types.indexOf(FOCUS) >= 0){
+		local._data(prefix + FOCUS, null);
+	}
+	if(types.indexOf(SELECTED) >= 0){
+		local._data(prefix + SELECTED, null);
+	}
+};
+
+
+/**
+ * [ext-persist] Return persistence information from cookies
+ *
+ * Called like
+ *     $("#tree").fancytree("getTree").getPersistData();
+ *
+ * @alias Fancytree#getPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.getPersistData = function(){
+	var local = this.ext.persist,
+		prefix = local.cookiePrefix,
+		delim = local.cookieDelimiter,
+		res = {};
+
+	res[ACTIVE] = local._data(prefix + ACTIVE);
+	res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim);
+	res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim);
+	res[FOCUS] = local._data(prefix + FOCUS);
+	return res;
+};
+
+
+/* *****************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "persist",
+	version: "0.3.0",
+	// Default options for this extension.
+	options: {
+		cookieDelimiter: "~",
+		cookiePrefix: undefined, // 'fancytree-<treeId>-' by default
+		cookie: {
+			raw: false,
+			expires: "",
+			path: "",
+			domain: "",
+			secure: false
+		},
+		expandLazy: false,     // true: recursively expand and load lazy nodes
+		fireActivate: true,    // false: suppress `activate` event after active node was restored
+		overrideSource: true,  // true: cookie takes precedence over `source` data attributes.
+		store: "auto",         // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore
+		types: "active expanded focus selected"
+	},
+
+	/* Generic read/write string data to cookie, sessionStorage or localStorage. */
+	_data: function(key, value){
+		var ls = this._local.localStorage; // null, sessionStorage, or localStorage
+
+		if( value === undefined ) {
+			return ls ? ls.getItem(key) : cookieGetter(key);
+		} else if ( value === null ) {
+			if( ls ) {
+				ls.removeItem(key);
+			} else {
+				cookieRemover(key);
+			}
+		} else {
+			if( ls ) {
+				ls.setItem(key, value);
+			} else {
+				cookieSetter(key, value, this.options.persist.cookie);
+			}
+		}
+	},
+
+	/* Append `key` to a cookie. */
+	_appendKey: function(type, key, flag){
+		key = "" + key; // #90
+		var local = this._local,
+			instOpts = this.options.persist,
+			delim = instOpts.cookieDelimiter,
+			cookieName = local.cookiePrefix + type,
+			data = local._data(cookieName),
+			keyList = data ? data.split(delim) : [],
+			idx = $.inArray(key, keyList);
+		// Remove, even if we add a key,  so the key is always the last entry
+		if(idx >= 0){
+			keyList.splice(idx, 1);
+		}
+		// Append key to cookie
+		if(flag){
+			keyList.push(key);
+		}
+		local._data(cookieName, keyList.join(delim));
+	},
+
+	treeInit: function(ctx){
+		var tree = ctx.tree,
+			opts = ctx.options,
+			local = this._local,
+			instOpts = this.options.persist;
+
+		// For 'auto' or 'cookie' mode, the cookie plugin must be available
+		_assert((instOpts.store !== "auto" && instOpts.store !== "cookie") || cookieGetter,
+			"Missing required plugin for 'persist' extension: js.cookie.js or jquery.cookie.js");
+
+		local.cookiePrefix = instOpts.cookiePrefix || ("fancytree-" + tree._id + "-");
+		local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
+		local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
+		local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
+		local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
+		if( instOpts.store === "cookie" || !window.localStorage ) {
+			local.localStorage = null;
+		} else {
+			local.localStorage = (instOpts.store === "local") ? window.localStorage : window.sessionStorage;
+		}
+
+		// Bind init-handler to apply cookie state
+		tree.$div.bind("fancytreeinit", function(event){
+			var cookie, dfd, i, keyList, node,
+				prevFocus = local._data(local.cookiePrefix + FOCUS), // record this before node.setActive() overrides it;
+				noEvents = instOpts.fireActivate === false;
+
+			// tree.debug("document.cookie:", document.cookie);
+
+			cookie = local._data(local.cookiePrefix + EXPANDED);
+			keyList = cookie && cookie.split(instOpts.cookieDelimiter);
+
+			if( local.storeExpanded ) {
+				// Recursively load nested lazy nodes if expandLazy is 'expand' or 'load'
+				// Also remove expand-cookies for unmatched nodes
+				dfd = _loadLazyNodes(tree, local, keyList, instOpts.expandLazy ? "expand" : false , null);
+			} else {
+				// nothing to do
+				dfd = new $.Deferred().resolve();
+			}
+
+			dfd.done(function(){
+				if(local.storeSelected){
+					cookie = local._data(local.cookiePrefix + SELECTED);
+					if(cookie){
+						keyList = cookie.split(instOpts.cookieDelimiter);
+						for(i=0; i<keyList.length; i++){
+							node = tree.getNodeByKey(keyList[i]);
+							if(node){
+								if(node.selected === undefined || instOpts.overrideSource && (node.selected === false)){
+//									node.setSelected();
+									node.selected = true;
+									node.renderStatus();
+								}
+							}else{
+								// node is no longer member of the tree: remove from cookie also
+								local._appendKey(SELECTED, keyList[i], false);
+							}
+						}
+					}
+					// In selectMode 3 we have to fix the child nodes, since we
+					// only stored the selected *top* nodes
+					if( tree.options.selectMode === 3 ){
+						tree.visit(function(n){
+							if( n.selected ) {
+								n.fixSelection3AfterClick();
+								return "skip";
+							}
+						});
+					}
+				}
+				if(local.storeActive){
+					cookie = local._data(local.cookiePrefix + ACTIVE);
+					if(cookie && (opts.persist.overrideSource || !tree.activeNode)){
+						node = tree.getNodeByKey(cookie);
+						if(node){
+							node.debug("persist: set active", cookie);
+							// We only want to set the focus if the container
+							// had the keyboard focus before
+							node.setActive(true, {
+								noFocus: true,
+								noEvents: noEvents
+							});
+						}
+					}
+				}
+				if(local.storeFocus && prevFocus){
+					node = tree.getNodeByKey(prevFocus);
+					if(node){
+						// node.debug("persist: set focus", cookie);
+						if( tree.options.titlesTabbable ) {
+							$(node.span).find(".fancytree-title").focus();
+						} else {
+							$(tree.$container).focus();
+						}
+						// node.setFocus();
+					}
+				}
+				tree._triggerTreeEvent("restore", null, {});
+			});
+		});
+		// Init the tree
+		return this._superApply(arguments);
+	},
+	nodeSetActive: function(ctx, flag, opts) {
+		var res,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if(local.storeActive){
+			local._data(local.cookiePrefix + ACTIVE, this.activeNode ? this.activeNode.key : null);
+		}
+		return res;
+	},
+	nodeSetExpanded: function(ctx, flag, opts) {
+		var res,
+			node = ctx.node,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if(local.storeExpanded){
+			local._appendKey(EXPANDED, node.key, flag);
+		}
+		return res;
+	},
+	nodeSetFocus: function(ctx, flag) {
+		var res,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if( local.storeFocus ) {
+			local._data(local.cookiePrefix + FOCUS, this.focusNode ? this.focusNode.key : null);
+		}
+		return res;
+	},
+	nodeSetSelected: function(ctx, flag) {
+		var res, selNodes,
+			tree = ctx.tree,
+			node = ctx.node,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if(local.storeSelected){
+			if( tree.options.selectMode === 3 ){
+				// In selectMode 3 we only store the the selected *top* nodes.
+				// De-selecting a node may also de-select some parents, so we
+				// calculate the current status again
+				selNodes = $.map(tree.getSelectedNodes(true), function(n){
+					return n.key;
+				});
+				selNodes = selNodes.join(ctx.options.persist.cookieDelimiter);
+				local._data(local.cookiePrefix + SELECTED, selNodes);
+			} else {
+				// beforeSelect can prevent the change - flag doesn't reflect the node.selected state
+				local._appendKey(SELECTED, node.key, node.selected);
+			}
+		}
+		return res;
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.table.js
+ *
+ * Render tree as table (aka 'treegrid', 'tabletree').
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+function _assert(cond, msg){
+	msg = msg || "";
+	if(!cond){
+		$.error("Assertion failed " + msg);
+	}
+}
+
+function insertSiblingAfter(referenceNode, newNode) {
+	referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+}
+
+/* Show/hide all rows that are structural descendants of `parent`. */
+function setChildRowVisibility(parent, flag) {
+	parent.visit(function(node){
+		var tr = node.tr;
+		// currentFlag = node.hide ? false : flag; // fix for ext-filter
+		if(tr){
+			tr.style.display = (node.hide || !flag) ? "none" : "";
+		}
+		if(!node.expanded){
+			return "skip";
+		}
+	});
+}
+
+/* Find node that is rendered in previous row. */
+function findPrevRowNode(node){
+	var i, last, prev,
+		parent = node.parent,
+		siblings = parent ? parent.children : null;
+
+	if(siblings && siblings.length > 1 && siblings[0] !== node){
+		// use the lowest descendant of the preceeding sibling
+		i = $.inArray(node, siblings);
+		prev = siblings[i - 1];
+		_assert(prev.tr);
+		// descend to lowest child (with a <tr> tag)
+		while(prev.children){
+			last = prev.children[prev.children.length - 1];
+			if(!last.tr){
+				break;
+			}
+			prev = last;
+		}
+	}else{
+		// if there is no preceding sibling, use the direct parent
+		prev = parent;
+	}
+	return prev;
+}
+
+
+$.ui.fancytree.registerExtension({
+	name: "table",
+	version: "0.2.1",
+	// Default options for this extension.
+	options: {
+		checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
+		customStatus: false,	 // true: generate renderColumns events for status nodes
+		indentation: 16,         // indent every node level by 16px
+		nodeColumnIdx: 0         // render node expander, icon, and title to this column (default: #0)
+	},
+	// Overide virtual methods for this extension.
+	// `this`       : is this extension object
+	// `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+	treeInit: function(ctx){
+		var i, $row, tdRole,
+			tree = ctx.tree,
+			$table = tree.widget.element;
+
+		$table.addClass("fancytree-container fancytree-ext-table");
+		tree.tbody = $table.find("> tbody")[0];
+		tree.columnCount = $("thead >tr >th", $table).length;
+		$(tree.tbody).empty();
+
+		tree.rowFragment = document.createDocumentFragment();
+		$row = $("<tr />");
+		tdRole = "";
+		if(ctx.options.aria){
+			$row.attr("role", "row");
+			tdRole = " role='gridcell'";
+		}
+		for(i=0; i<tree.columnCount; i++) {
+			if(ctx.options.table.nodeColumnIdx === i){
+				$row.append("<td" + tdRole + "><span class='fancytree-node' /></td>");
+			}else{
+				$row.append("<td" + tdRole + " />");
+			}
+		}
+		tree.rowFragment.appendChild($row.get(0));
+
+		// Make sure that status classes are set on the node's <tr> elements
+		tree.statusClassPropName = "tr";
+		tree.ariaPropName = "tr";
+		this.nodeContainerAttrName = "tr";
+
+		// #489: make sure $container is set to <table>, even if ext-dnd is listed before ext-table
+		tree.$container = $table;
+
+		this._superApply(arguments);
+
+		// standard Fancytree created a root UL
+		$(tree.rootNode.ul).remove();
+		tree.rootNode.ul = null;
+//		tree.$container = $table;
+		// Add container to the TAB chain
+		this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1");
+		if(this.options.aria){
+			tree.$container
+				.attr("role", "treegrid")
+				.attr("aria-readonly", true);
+		}
+	},
+	/* Called by nodeRender to sync node order with tag order.*/
+//    nodeFixOrder: function(ctx) {
+//    },
+	nodeRemoveChildMarkup: function(ctx) {
+		var node = ctx.node;
+//		node.debug("nodeRemoveChildMarkup()");
+		node.visit(function(n){
+			if(n.tr){
+				$(n.tr).remove();
+				n.tr = null;
+			}
+		});
+	},
+	nodeRemoveMarkup: function(ctx) {
+		var node = ctx.node;
+//		node.debug("nodeRemoveMarkup()");
+		if(node.tr){
+			$(node.tr).remove();
+			node.tr = null;
+		}
+		this.nodeRemoveChildMarkup(ctx);
+	},
+	/* Override standard render. */
+	nodeRender: function(ctx, force, deep, collapsed, _recursive) {
+		var children, firstTr, i, l, newRow, prevNode, prevTr, subCtx,
+			tree = ctx.tree,
+			node = ctx.node,
+			opts = ctx.options,
+			isRootNode = !node.parent;
+
+		if( !_recursive ){
+			ctx.hasCollapsedParents = node.parent && !node.parent.expanded;
+		}
+		// $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr));
+		if( !isRootNode ){
+			if(!node.tr){
+				if( ctx.hasCollapsedParents && !deep ) {
+					// #166: we assume that the parent will be (recursively) rendered
+					// later anyway.
+					node.debug("nodeRender ignored due to unrendered parent");
+					return;
+				}
+				// Create new <tr> after previous row
+				newRow = tree.rowFragment.firstChild.cloneNode(true);
+				prevNode = findPrevRowNode(node);
+				// $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key);
+				_assert(prevNode);
+				if(collapsed === true && _recursive){
+					// hide all child rows, so we can use an animation to show it later
+					newRow.style.display = "none";
+				}else if(deep && ctx.hasCollapsedParents){
+					// also hide this row if deep === true but any parent is collapsed
+					newRow.style.display = "none";
+//					newRow.style.color = "red";
+				}
+				if(!prevNode.tr){
+					_assert(!prevNode.parent, "prev. row must have a tr, or is system root");
+					tree.tbody.appendChild(newRow);
+				}else{
+					insertSiblingAfter(prevNode.tr, newRow);
+				}
+				node.tr = newRow;
+				if( node.key && opts.generateIds ){
+					node.tr.id = opts.idPrefix + node.key;
+				}
+				node.tr.ftnode = node;
+				if(opts.aria){
+					// TODO: why doesn't this work:
+//                  node.li.role = "treeitem";
+					$(node.tr).attr("aria-labelledby", "ftal_" + node.key);
+				}
+				node.span = $("span.fancytree-node", node.tr).get(0);
+				// Set icon, link, and title (normally this is only required on initial render)
+				this.nodeRenderTitle(ctx);
+				// Allow tweaking, binding, after node was created for the first time
+//				tree._triggerNodeEvent("createNode", ctx);
+				if ( opts.createNode ){
+					opts.createNode.call(tree, {type: "createNode"}, ctx);
+				}
+			} else {
+				if( force ) {
+					// Set icon, link, and title (normally this is only required on initial render)
+					this.nodeRenderTitle(ctx); // triggers renderColumns()
+				} else {
+					// Update element classes according to node state
+					this.nodeRenderStatus(ctx);
+				}
+			}
+		}
+		// Allow tweaking after node state was rendered
+//		tree._triggerNodeEvent("renderNode", ctx);
+		if ( opts.renderNode ){
+			opts.renderNode.call(tree, {type: "renderNode"}, ctx);
+		}
+		// Visit child nodes
+		// Add child markup
+		children = node.children;
+		if(children && (isRootNode || deep || node.expanded)){
+			for(i=0, l=children.length; i<l; i++) {
+				subCtx = $.extend({}, ctx, {node: children[i]});
+				subCtx.hasCollapsedParents = subCtx.hasCollapsedParents || !node.expanded;
+				this.nodeRender(subCtx, force, deep, collapsed, true);
+			}
+		}
+		// Make sure, that <tr> order matches node.children order.
+		if(children && !_recursive){ // we only have to do it once, for the root branch
+			prevTr = node.tr || null;
+			firstTr = tree.tbody.firstChild;
+			// Iterate over all descendants
+			node.visit(function(n){
+				if(n.tr){
+					if(!n.parent.expanded && n.tr.style.display !== "none"){
+						// fix after a node was dropped over a collapsed
+						n.tr.style.display = "none";
+						setChildRowVisibility(n, false);
+					}
+					if(n.tr.previousSibling !== prevTr){
+						node.debug("_fixOrder: mismatch at node: " + n);
+						var nextTr = prevTr ? prevTr.nextSibling : firstTr;
+						tree.tbody.insertBefore(n.tr, nextTr);
+					}
+					prevTr = n.tr;
+				}
+			});
+		}
+		// Update element classes according to node state
+		// if(!isRootNode){
+		// 	this.nodeRenderStatus(ctx);
+		// }
+	},
+	nodeRenderTitle: function(ctx, title) {
+		var $cb,
+			node = ctx.node,
+			opts = ctx.options;
+
+		this._superApply(arguments);
+		// Move checkbox to custom column
+		if(opts.checkbox && opts.table.checkboxColumnIdx != null ){
+			$cb = $("span.fancytree-checkbox", node.span).detach();
+			$(node.tr).find("td").eq(+opts.table.checkboxColumnIdx).html($cb);
+		}
+		// Update element classes according to node state
+		if( ! node.isRoot() ){
+			this.nodeRenderStatus(ctx);
+		}
+		if( !opts.table.customStatus && node.isStatusNode() ) {
+			// default rendering for status node: leave other cells empty
+		} else if ( opts.renderColumns ) {
+			// Let user code write column content
+			opts.renderColumns.call(ctx.tree, {type: "renderColumns"}, ctx);
+		}
+	},
+	nodeRenderStatus: function(ctx) {
+		var indent,
+			node = ctx.node,
+			opts = ctx.options;
+
+		this._superApply(arguments);
+
+		$(node.tr).removeClass("fancytree-node");
+		// indent
+		indent = (node.getLevel() - 1) * opts.table.indentation;
+		$(node.span).css({paddingLeft: indent + "px"});  // #460
+		// $(node.span).css({marginLeft: indent + "px"});
+	 },
+	/* Expand node, return Deferred.promise. */
+	nodeSetExpanded: function(ctx, flag, opts) {
+		var dfd = new $.Deferred(),
+			subOpts = $.extend({}, opts, {noEvents: true, noAnimation: true});
+
+		opts = opts || {};
+
+		function _afterExpand(ok) {
+			flag = (flag !== false);
+			setChildRowVisibility(ctx.node, flag);
+			if( ok ) {
+				if( flag && ctx.options.autoScroll && !opts.noAnimation && ctx.node.hasChildren() ) {
+					// Scroll down to last child, but keep current node visible
+					ctx.node.getLastChild().scrollIntoView(true, {topNode: ctx.node}).always(function(){
+						if( !opts.noEvents ) {
+							ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+						}
+						dfd.resolveWith(ctx.node);
+					});
+				} else {
+					if( !opts.noEvents ) {
+						ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+					}
+					dfd.resolveWith(ctx.node);
+				}
+			} else {
+				if( !opts.noEvents ) {
+					ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+				}
+				dfd.rejectWith(ctx.node);
+			}
+		}
+		// Call base-expand with disabled  events and animation
+		this._super(ctx, flag, subOpts).done(function () {
+			_afterExpand(true);
+		}).fail(function () {
+			_afterExpand(false);
+		});
+		return dfd.promise();
+	},
+	nodeSetStatus: function(ctx, status, message, details) {
+		if(status === "ok"){
+			var node = ctx.node,
+				firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				$(firstChild.tr).remove();
+			}
+		}
+		return this._superApply(arguments);
+	},
+	treeClear: function(ctx) {
+		this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode));
+		return this._superApply(arguments);
+	},
+	treeDestroy: function(ctx) {
+		this.$container.find("tbody").empty();
+		this.$source && this.$source.removeClass("ui-helper-hidden");
+	}
+	/*,
+	treeSetFocus: function(ctx, flag) {
+//	        alert("treeSetFocus" + ctx.tree.$container);
+		ctx.tree.$container.focus();
+		$.ui.fancytree.focusTree = ctx.tree;
+	}*/
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.themeroller.js
+ *
+ * Enable jQuery UI ThemeRoller styles.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @see http://jqueryui.com/themeroller/
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "themeroller",
+	version: "0.0.1",
+	// Default options for this extension.
+	options: {
+		activeClass: "ui-state-active",
+		foccusClass: "ui-state-focus",
+		hoverClass: "ui-state-hover",
+		selectedClass: "ui-state-highlight"
+	},
+
+	treeInit: function(ctx){
+		this._superApply(arguments);
+		var $el = ctx.widget.element;
+
+		if($el[0].nodeName === "TABLE"){
+			$el.addClass("ui-widget ui-corner-all");
+			$el.find(">thead tr").addClass("ui-widget-header");
+			$el.find(">tbody").addClass("ui-widget-conent");
+		}else{
+			$el.addClass("ui-widget ui-widget-content ui-corner-all");
+		}
+
+		$el.delegate(".fancytree-node", "mouseenter mouseleave", function(event){
+			var node = $.ui.fancytree.getNode(event.target),
+				flag = (event.type === "mouseenter");
+			node.debug("hover: " + flag);
+			$(node.tr ? node.tr : node.span).toggleClass("ui-state-hover ui-corner-all", flag);
+		});
+	},
+	treeDestroy: function(ctx){
+		this._superApply(arguments);
+		ctx.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all");
+	},
+	nodeRenderStatus: function(ctx){
+		var node = ctx.node,
+			$el = $(node.tr ? node.tr : node.span);
+		this._superApply(arguments);
+/*
+		.ui-state-highlight: Class to be applied to highlighted or selected elements. Applies "highlight" container styles to an element and its child text, links, and icons.
+		.ui-state-error: Class to be applied to error messaging container elements. Applies "error" container styles to an element and its child text, links, and icons.
+		.ui-state-error-text: An additional class that applies just the error text color without background. Can be used on form labels for instance. Also applies error icon color to child icons.
+
+		.ui-state-default: Class to be applied to clickable button-like elements. Applies "clickable default" container styles to an element and its child text, links, and icons.
+		.ui-state-hover: Class to be applied on mouseover to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+		.ui-state-focus: Class to be applied on keyboard focus to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+		.ui-state-active: Class to be applied on mousedown to clickable button-like elements. Applies "clickable active" container styles to an element and its child text, links, and icons.
+*/
+		$el.toggleClass("ui-state-active", node.isActive());
+		$el.toggleClass("ui-state-focus", node.hasFocus());
+		$el.toggleClass("ui-state-highlight", node.isSelected());
+	}
+});
+}(jQuery, window, document));
+
+/*!
+ * jquery.fancytree.wide.js
+ * Support for 100% wide selection bars.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+var reNumUnit = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/; // split "1.5em" to ["1.5", "em"]
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+// var _assert = $.ui.fancytree.assert;
+
+/* Calculate inner width without scrollbar */
+// function realInnerWidth($el) {
+// 	// http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
+// //	inst.contWidth = parseFloat(this.$container.css("width"), 10);
+// 	// 'Client width without scrollbar' - 'padding'
+// 	return $el[0].clientWidth - ($el.innerWidth() -  parseFloat($el.css("width"), 10));
+// }
+
+/* Create a global embedded CSS style for the tree. */
+function defineHeadStyleElement(id, cssText) {
+	id = "fancytree-style-" + id;
+	var $headStyle = $("#" + id);
+
+	if( !cssText ) {
+		$headStyle.remove();
+		return null;
+	}
+	if( !$headStyle.length ) {
+		$headStyle = $("<style />")
+			.attr("id", id)
+			.addClass("fancytree-style")
+			.prop("type", "text/css")
+			.appendTo("head");
+	}
+	try {
+		$headStyle.html(cssText);
+	} catch ( e ) {
+		// fix for IE 6-8
+		$headStyle[0].styleSheet.cssText = cssText;
+	}
+	return $headStyle;
+}
+
+/* Calculate the CSS rules that indent title spans. */
+function renderLevelCss(containerId, depth, levelOfs, lineOfs, measureUnit) {
+	var i,
+		prefix = "#" + containerId + " span.fancytree-level-",
+		rules = [];
+
+	for(i = 0; i < depth; i++) {
+		rules.push(prefix + (i + 1) + " span.fancytree-title { padding-left: " +
+			(i * levelOfs + lineOfs) + measureUnit + "; }");
+	}
+	// Some UI animations wrap the UL inside a DIV and set position:relative on both.
+	// This breaks the left:0 and padding-left:nn settings of the title
+	rules.push("#" + containerId +
+		" div.ui-effects-wrapper ul li span.fancytree-title " +
+		"{ padding-left: 3px; position: static; width: auto; }");
+	return rules.join("\n");
+}
+
+
+// /**
+//  * [ext-wide] Recalculate the width of the selection bar after the tree container
+//  * was resized.<br>
+//  * May be called explicitly on container resize, since there is no resize event
+//  * for DIV tags.
+//  *
+//  * @alias Fancytree#wideUpdate
+//  * @requires jquery.fancytree.wide.js
+//  */
+// $.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){
+// 	var inst = this.ext.wide,
+// 		prevCw = inst.contWidth,
+// 		prevLo = inst.lineOfs;
+
+// 	inst.contWidth = realInnerWidth(this.$container);
+// 	// Each title is precceeded by 2 or 3 icons (16px + 3 margin)
+// 	//     + 1px title border and 3px title padding
+// 	// TODO: use code from treeInit() below
+// 	inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19;
+// 	if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) {
+// 		this.debug("wideUpdate: " + inst.contWidth);
+// 		this.visit(function(node){
+// 			node.tree._callHook("nodeRenderTitle", node);
+// 		});
+// 	}
+// };
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "wide",
+	version: "0.0.3",
+	// Default options for this extension.
+	options: {
+		iconWidth: null,  // Adjust this if @fancy-icon-width != "16px"
+		iconSpacing: null, // Adjust this if @fancy-icon-spacing != "3px"
+		levelOfs: null    // Adjust this if ul padding != "16px"
+	},
+
+	treeCreate: function(ctx){
+		this._superApply(arguments);
+		this.$container.addClass("fancytree-ext-wide");
+
+		var containerId, cssText, iconSpacingUnit, iconWidthUnit, levelOfsUnit,
+			instOpts = ctx.options.wide,
+			// css sniffing
+			$dummyLI = $("<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />")
+				.appendTo(ctx.tree.$container),
+			$dummyIcon = $dummyLI.find(".fancytree-icon"),
+			$dummyUL = $dummyLI.find("ul"),
+			// $dummyTitle = $dummyLI.find(".fancytree-title"),
+			iconSpacing = instOpts.iconSpacing || $dummyIcon.css("margin-left"),
+			iconWidth = instOpts.iconWidth || $dummyIcon.css("width"),
+			levelOfs = instOpts.levelOfs || $dummyUL.css("padding-left");
+
+		$dummyLI.remove();
+
+		iconSpacingUnit = iconSpacing.match(reNumUnit)[2];
+		iconSpacing = parseFloat(iconSpacing, 10);
+		iconWidthUnit = iconWidth.match(reNumUnit)[2];
+		iconWidth = parseFloat(iconWidth, 10);
+		levelOfsUnit = levelOfs.match(reNumUnit)[2];
+		if( iconSpacingUnit !== iconWidthUnit || levelOfsUnit !== iconWidthUnit ) {
+			$.error("iconWidth, iconSpacing, and levelOfs must have the same css measure unit");
+		}
+		this._local.measureUnit = iconWidthUnit;
+		this._local.levelOfs = parseFloat(levelOfs);
+		this._local.lineOfs = (1 + (ctx.options.checkbox ? 1 : 0) + (ctx.options.icons ? 1 : 0)) * (iconWidth + iconSpacing) + iconSpacing;
+		this._local.maxDepth = 10;
+
+		// Get/Set a unique Id on the container (if not already exists)
+		containerId = this.$container.uniqueId().attr("id");
+		// Generated css rules for some levels (extended on demand)
+		cssText = renderLevelCss(containerId, this._local.maxDepth,
+			this._local.levelOfs, this._local.lineOfs, this._local.measureUnit);
+		defineHeadStyleElement(containerId, cssText);
+	},
+	treeDestroy: function(ctx){
+		// Remove generated css rules
+		defineHeadStyleElement(this.$container.attr("id"), null);
+		return this._superApply(arguments);
+	},
+	nodeRenderStatus: function(ctx) {
+		var containerId, cssText, res,
+			node = ctx.node,
+			level = node.getLevel();
+
+		res = this._superApply(arguments);
+		// Generate some more level-n rules if required
+		if( level > this._local.maxDepth ) {
+			containerId = this.$container.attr("id");
+			this._local.maxDepth *= 2;
+			node.debug("Define global ext-wide css up to level " + this._local.maxDepth);
+			cssText = renderLevelCss(containerId, this._local.maxDepth,
+				this._local.levelOfs, this._local.lineOfs, this._local.measureUnit);
+			defineHeadStyleElement(containerId, cssText);
+		}
+		// Add level-n class to apply indentation padding.
+		// (Setting element style would not work, since it cannot easily be
+		// overriden while animations run)
+		$(node.span).addClass("fancytree-level-" + level);
+		return res;
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.min.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.min.js
new file mode 100644
index 00000000000..efb518cd71e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree-all.min.js
@@ -0,0 +1,47 @@
+/*! jQuery Fancytree Plugin - 2.13.0 - 2015-11-16T07:33
+  * https://github.com/mar10/fancytree
+  * Copyright (c) 2015 Martin Wendt; Licensed MIT */
+(function( factory ) {
+	if ( typeof define === "function" && define.amd ) {
+		define( [ "jquery" ], factory );
+	} else {
+		factory( jQuery );
+	}
+}(function( $ ) {
+
+!function(a,b,c,d){"use strict";function e(b,c){b||(c=c?": "+c:"",a.error("Fancytree assertion failed"+c))}function f(a,c){var d,e,f=b.console?b.console[a]:null;if(f)try{f.apply(b.console,c)}catch(g){for(e="",d=0;d<c.length;d++)e+=c[d];f(e)}}function g(a){return!(!a.tree||a.statusNodeType===d)}function h(b){var c,d,e,f=a.map(a.trim(b).split("."),function(a){return parseInt(a,10)}),g=a.map(Array.prototype.slice.call(arguments,1),function(a){return parseInt(a,10)});for(c=0;c<g.length;c++)if(d=f[c]||0,e=g[c]||0,d!==e)return d>e;return!0}function i(a,b,c,d,e){var f=function(){var c=b[a],f=d[a],g=b.ext[e],h=function(){return c.apply(b,arguments)},i=function(a){return c.apply(b,a)};return function(){var a=b._local,c=b._super,d=b._superApply;try{return b._local=g,b._super=h,b._superApply=i,f.apply(b,arguments)}finally{b._local=a,b._super=c,b._superApply=d}}}();return f}function j(b,c,d,e){for(var f in d)"function"==typeof d[f]?"function"==typeof b[f]?b[f]=i(f,b,c,d,e):"_"===f.charAt(0)?b.ext[e][f]=i(f,b,c,d,e):a.error("Could not override tree."+f+". Use prefix '_' to create tree."+e+"._"+f):"options"!==f&&(b.ext[e][f]=d[f])}function k(b,c){return b===d?a.Deferred(function(){this.resolve()}).promise():a.Deferred(function(){this.resolveWith(b,c)}).promise()}function l(b,c){return b===d?a.Deferred(function(){this.reject()}).promise():a.Deferred(function(){this.rejectWith(b,c)}).promise()}function m(a,b){return function(){a.resolveWith(b)}}function n(b){var c=a.extend({},b.data()),d=c.json;return delete c.fancytree,delete c.uiFancytree,d&&(delete c.json,c=a.extend(c,d)),c}function o(a){return a=a.toLowerCase(),function(b){return b.title.toLowerCase().indexOf(a)>=0}}function p(a){var b=new RegExp("^"+a,"i");return function(a){return b.test(a.title)}}function q(b,c){var d,f,g,h;for(this.parent=b,this.tree=b.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},d=0,f=B.length;f>d;d++)g=B[d],this[g]=c[g];c.data&&a.extend(this.data,c.data);for(g in c)C[g]||a.isFunction(c[g])||E[g]||(this.data[g]=c[g]);null==this.key?this.tree.options.defaultKey?(this.key=this.tree.options.defaultKey(this),e(this.key,"defaultKey() must return a unique key")):this.key="_"+u._nextNodeKey++:this.key=""+this.key,c.active&&(e(null===this.tree.activeNode,"only one active node allowed"),this.tree.activeNode=this),c.selected&&(this.tree.lastSelectedNode=this),h=c.children,h?h.length?this._setChildren(h):this.children=this.lazy?[]:null:this.children=null,this.tree._callHook("treeRegisterNode",this.tree,!0,this)}function r(b){this.widget=b,this.$div=b.element,this.options=b.options,this.options&&(a.isFunction(this.options.lazyload)&&!a.isFunction(this.options.lazyLoad)&&(this.options.lazyLoad=function(){return u.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."),b.options.lazyload.apply(this,arguments)}),a.isFunction(this.options.loaderror)&&a.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."),this.options.fx!==d&&u.warn("The 'fx' options was replaced by 'toggleEffect' since 2014-11-30.")),this.ext={},this.data=n(this.$div),this._id=a.ui.fancytree._nextId++,this._ns=".fancytree-"+this._id,this.activeNode=null,this.focusNode=null,this._hasFocus=null,this.lastSelectedNode=null,this.systemFocusElement=null,this.lastQuicksearchTerm="",this.lastQuicksearchTime=0,this.statusClassPropName="span",this.ariaPropName="li",this.nodeContainerAttrName="li",this.$div.find(">ul.fancytree-container").remove();var c,e={tree:this};this.rootNode=new q(e,{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,c=a("<ul>",{"class":"ui-fancytree fancytree-container fancytree-plain"}).appendTo(this.$div),this.$container=c,this.rootNode.ul=c[0],null==this.options.debugLevel&&(this.options.debugLevel=u.debugLevel),this.$container.attr("tabindex",this.options.tabbable?"0":"-1"),this.options.aria&&this.$container.attr("role","tree").attr("aria-multiselectable",!0)}if(a.ui&&a.ui.fancytree)return void a.ui.fancytree.warn("Fancytree: ignored duplicate include");e(a.ui,"Fancytree requires jQuery UI (http://jqueryui.com)");var s,t,u=null,v={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"},w={16:!0,17:!0,18:!0},x={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},y={0:"",1:"left",2:"middle",3:"right"},z="active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),A={},B="expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "),C={},D={},E={active:!0,children:!0,data:!0,focus:!0};for(s=0;s<z.length;s++)A[z[s]]=!0;for(s=0;s<B.length;s++)t=B[s],C[t]=!0,t!==t.toLowerCase()&&(D[t.toLowerCase()]=t);q.prototype={_findDirectChild:function(a){var b,c,d=this.children;if(d)if("string"==typeof a){for(b=0,c=d.length;c>b;b++)if(d[b].key===a)return d[b]}else{if("number"==typeof a)return this.children[a];if(a.parent===this)return a}return null},_setChildren:function(a){e(a&&(!this.children||0===this.children.length),"only init supported"),this.children=[];for(var b=0,c=a.length;c>b;b++)this.children.push(new q(this,a[b]))},addChildren:function(b,c){var d,f,g,h=null,i=[];for(a.isPlainObject(b)&&(b=[b]),this.children||(this.children=[]),d=0,f=b.length;f>d;d++)i.push(new q(this,b[d]));return h=i[0],null==c?this.children=this.children.concat(i):(c=this._findDirectChild(c),g=a.inArray(c,this.children),e(g>=0,"insertBefore must be an existing child"),this.children.splice.apply(this.children,[g,0].concat(i))),(!this.parent||this.parent.ul||this.tr)&&this.render(),3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),h},addNode:function(a,b){switch((b===d||"over"===b)&&(b="child"),b){case"after":return this.getParent().addChildren(a,this.getNextSibling());case"before":return this.getParent().addChildren(a,this);case"firstChild":var c=this.children?this.children[0]:null;return this.addChildren(a,c);case"child":case"over":return this.addChildren(a)}e(!1,"Invalid mode: "+b)},appendSibling:function(a){return this.addNode(a,"after")},applyPatch:function(b){if(null===b)return this.remove(),k(this);var c,d,e,f={children:!0,expanded:!0,parent:!0};for(c in b)e=b[c],f[c]||a.isFunction(e)||(C[c]?this[c]=e:this.data[c]=e);return b.hasOwnProperty("children")&&(this.removeChildren(),b.children&&this._setChildren(b.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),d=b.hasOwnProperty("expanded")?this.setExpanded(b.expanded):k(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(a,b,c){return a.addNode(this.toDict(!0,c),b)},countChildren:function(a){var b,c,d,e=this.children;if(!e)return 0;if(d=e.length,a!==!1)for(b=0,c=d;c>b;b++)d+=e[b].countChildren();return d},debug:function(){this.tree.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},findAll:function(b){b=a.isFunction(b)?b:o(b);var c=[];return this.visit(function(a){b(a)&&c.push(a)}),c},findFirst:function(b){b=a.isFunction(b)?b:o(b);var c=null;return this.visit(function(a){return b(a)?(c=a,!1):void 0}),c},_changeSelectStatusAttrs:function(a){var b=!1;switch(a){case!1:b=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:b=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case d:b=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:e(!1,"invalid state: "+a)}return b&&this.renderStatus(),b},fixSelection3AfterClick:function(){var a=this.isSelected();this.visit(function(b){b._changeSelectStatusAttrs(a)}),this.fixSelection3FromEndNodes()},fixSelection3FromEndNodes:function(){function a(b){var c,e,f,g,h,i,j,k=b.children;if(k&&k.length){for(i=!0,j=!1,c=0,e=k.length;e>c;c++)f=k[c],g=a(f),g!==!1&&(j=!0),g!==!0&&(i=!1);h=i?!0:j?d:!1}else h=!!b.selected;return b._changeSelectStatusAttrs(h),h}e(3===this.tree.options.selectMode,"expected selectMode 3"),a(this),this.visitParents(function(a){var b,c,e,f,g=a.children,h=!0,i=!1;for(b=0,c=g.length;c>b;b++)e=g[b],(e.selected||e.partsel)&&(i=!0),e.unselectable||e.selected||(h=!1);f=h?!0:i?d:!1,a._changeSelectStatusAttrs(f)})},fromDict:function(b){for(var c in b)C[c]?this[c]=b[c]:"data"===c?a.extend(this.data,b.data):a.isFunction(b[c])||E[c]||(this.data[c]=b[c]);b.children&&(this.removeChildren(),this.addChildren(b.children)),this.renderTitle()},getChildren:function(){return this.hasChildren()===d?d:this.children},getFirstChild:function(){return this.children?this.children[0]:null},getIndex:function(){return a.inArray(this,this.parent.children)},getIndexHier:function(b){b=b||".";var c=[];return a.each(this.getParentList(!1,!0),function(a,b){c.push(b.getIndex()+1)}),c.join(b)},getKeyPath:function(a){var b=[],c=this.tree.options.keyPathSeparator;return this.visitParents(function(a){a.parent&&b.unshift(a.key)},!a),c+b.join(c)},getLastChild:function(){return this.children?this.children[this.children.length-1]:null},getLevel:function(){for(var a=0,b=this.parent;b;)a++,b=b.parent;return a},getNextSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=0,b=c.length-1;b>a;a++)if(c[a]===this)return c[a+1]}return null},getParent:function(){return this.parent},getParentList:function(a,b){for(var c=[],d=b?this:this.parent;d;)(a||d.parent)&&c.unshift(d),d=d.parent;return c},getPrevSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=1,b=c.length;b>a;a++)if(c[a]===this)return c[a-1]}return null},hasChildren:function(){return this.lazy?null==this.children?d:0===this.children.length?!1:1===this.children.length&&this.children[0].isStatusNode()?d:!0:!(!this.children||!this.children.length)},hasFocus:function(){return this.tree.hasFocus()&&this.tree.focusNode===this},info:function(){this.tree.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),f("info",arguments))},isActive:function(){return this.tree.activeNode===this},isChildOf:function(a){return this.parent&&this.parent===a},isDescendantOf:function(a){if(!a||a.tree!==this.tree)return!1;for(var b=this.parent;b;){if(b===a)return!0;b=b.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var a=this.parent;return!a||a.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var a=this.parent;return!a||a.children[a.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||this.hasChildren()!==d},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return this.hasChildren()===d},isVisible:function(){var a,b,c=this.getParentList(!1,!1);for(a=0,b=c.length;b>a;a++)if(!c[a].expanded)return!1;return!0},lazyLoad:function(a){return this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."),this.load(a)},load:function(a){var b,c,d=this;return e(this.isLazy(),"load() requires a lazy node"),a||this.isUndefined()?(this.isLoaded()&&this.resetLazy(),c=this.tree._triggerNodeEvent("lazyLoad",this),c===!1?k(this):(e("boolean"!=typeof c,"lazyLoad event must return source in data.result"),b=this.tree._callHook("nodeLoadChildren",this,c),this.expanded&&b.always(function(){d.render()}),b)):k(this)},makeVisible:function(b){var c,d=this,e=[],f=new a.Deferred,g=this.getParentList(!1,!1),h=g.length,i=!(b&&b.noAnimation===!0),j=!(b&&b.scrollIntoView===!1);for(c=h-1;c>=0;c--)e.push(g[c].setExpanded(!0,b));return a.when.apply(a,e).done(function(){j?d.scrollIntoView(i).done(function(){f.resolve()}):f.resolve()}),f.promise()},moveTo:function(b,c,f){(c===d||"over"===c)&&(c="child");var g,h=this.parent,i="child"===c?b:b.parent;if(this!==b){if(!this.parent)throw"Cannot move system root";if(i.isDescendantOf(this))throw"Cannot move a node to its own descendant";if(1===this.parent.children.length){if(this.parent===i)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else g=a.inArray(this,this.parent.children),e(g>=0,"invalid source parent"),this.parent.children.splice(g,1);if(this.parent=i,i.hasChildren())switch(c){case"child":i.children.push(this);break;case"before":g=a.inArray(b,i.children),e(g>=0,"invalid target parent"),i.children.splice(g,0,this);break;case"after":g=a.inArray(b,i.children),e(g>=0,"invalid target parent"),i.children.splice(g+1,0,this);break;default:throw"Invalid mode "+c}else i.children=[this];f&&b.visit(f,!0),this.tree!==b.tree&&(this.warn("Cross-tree moveTo is experimantal!"),this.visit(function(a){a.tree=b.tree},!0)),h.isDescendantOf(i)||h.render(),i.isDescendantOf(h)||i===h||i.render()}},navigate:function(b,c){function d(d){if(d){try{d.makeVisible()}catch(e){}return a(d.span).is(":visible")?c===!1?d.setFocus():d.setActive():(d.debug("Navigate: skipping hidden node"),void d.navigate(b,c))}}var e,f,g=!0,h=a.ui.keyCode,i=null;switch(b){case h.BACKSPACE:this.parent&&this.parent.parent&&d(this.parent);break;case h.LEFT:this.expanded?(this.setExpanded(!1),d(this)):this.parent&&this.parent.parent&&d(this.parent);break;case h.RIGHT:this.expanded||!this.children&&!this.lazy?this.children&&this.children.length&&d(this.children[0]):(this.setExpanded(),d(this));break;case h.UP:for(i=this.getPrevSibling();i&&!a(i.span).is(":visible");)i=i.getPrevSibling();for(;i&&i.expanded&&i.children&&i.children.length;)i=i.children[i.children.length-1];!i&&this.parent&&this.parent.parent&&(i=this.parent),d(i);break;case h.DOWN:if(this.expanded&&this.children&&this.children.length)i=this.children[0];else for(f=this.getParentList(!1,!0),e=f.length-1;e>=0;e--){for(i=f[e].getNextSibling();i&&!a(i.span).is(":visible");)i=i.getNextSibling();if(i)break}d(i);break;default:g=!1}},remove:function(){return this.parent.removeChild(this)},removeChild:function(a){return this.tree._callHook("nodeRemoveChild",this,a)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},render:function(a,b){return this.tree._callHook("nodeRender",this,a,b)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},resetLazy:function(){this.removeChildren(),this.expanded=!1,this.lazy=!0,this.children=d,this.renderStatus()},scheduleAction:function(a,b){this.tree.timer&&clearTimeout(this.tree.timer),this.tree.timer=null;var c=this;switch(a){case"cancel":break;case"expand":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger expand"),c.setExpanded(!0)},b);break;case"activate":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger activate"),c.setActive(!0)},b);break;default:throw"Invalid mode "+a}},scrollIntoView:function(f,h){h!==d&&g(h)&&(this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."),h={topNode:h});var i,j,l,m,n=a.extend({effects:f===!0?{duration:200,queue:!1}:f,scrollOfs:this.tree.options.scrollOfs,scrollParent:this.tree.options.scrollParent||this.tree.$container,topNode:null},h),o=new a.Deferred,p=this,q=a(this.span).height(),r=a(n.scrollParent),s=n.scrollOfs.top||0,t=n.scrollOfs.bottom||0,u=r.height(),v=r.scrollTop(),w=r,x=r[0]===b,y=n.topNode||null,z=null;return a(this.span).is(":visible")?(x?(j=a(this.span).offset().top,i=y&&y.span?a(y.span).offset().top:0,w=a("html,body")):(e(r[0]!==c&&r[0]!==c.body,"scrollParent should be an simple element or `window`, not document or body."),m=r.offset().top,j=a(this.span).offset().top-m+v,i=y?a(y.span).offset().top-m+v:0,l=Math.max(0,r.innerHeight()-r[0].clientHeight),u-=l),v+s>j?z=j-s:j+q>v+u-t&&(z=j+q-u+t,y&&(e(y.isRootNode()||a(y.span).is(":visible"),"topNode must be visible"),z>i&&(z=i-s))),null!==z?n.effects?(n.effects.complete=function(){o.resolveWith(p)},w.stop(!0).animate({scrollTop:z},n.effects)):(w[0].scrollTop=z,o.resolveWith(this)):o.resolveWith(this),o.promise()):(this.warn("scrollIntoView(): node is invisible."),k())},setActive:function(a,b){return this.tree._callHook("nodeSetActive",this,a,b)},setExpanded:function(a,b){return this.tree._callHook("nodeSetExpanded",this,a,b)},setFocus:function(a){return this.tree._callHook("nodeSetFocus",this,a)},setSelected:function(a){return this.tree._callHook("nodeSetSelected",this,a)},setStatus:function(a,b,c){return this.tree._callHook("nodeSetStatus",this,a,b,c)},setTitle:function(a){this.title=a,this.renderTitle()},sortChildren:function(a,b){var c,d,e=this.children;if(e){if(a=a||function(a,b){var c=a.title.toLowerCase(),d=b.title.toLowerCase();return c===d?0:c>d?1:-1},e.sort(a),b)for(c=0,d=e.length;d>c;c++)e[c].children&&e[c].sortChildren(a,"$norender$");"$norender$"!==b&&this.render()}},toDict:function(b,c){var d,e,f,g={},h=this;if(a.each(B,function(a,b){(h[b]||h[b]===!1)&&(g[b]=h[b])}),a.isEmptyObject(this.data)||(g.data=a.extend({},this.data),a.isEmptyObject(g.data)&&delete g.data),c&&c(g,h),b&&this.hasChildren())for(g.children=[],d=0,e=this.children.length;e>d;d++)f=this.children[d],f.isStatusNode()||g.children.push(f.toDict(!0,c));return g},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return"<FancytreeNode(#"+this.key+", '"+this.title+"')>"},visit:function(a,b){var c,d,e=!0,f=this.children;if(b===!0&&(e=a(this),e===!1||"skip"===e))return e;if(f)for(c=0,d=f.length;d>c&&(e=f[c].visit(a,!0),e!==!1);c++);return e},visitAndLoad:function(b,c,d){var e,f,g,h=this;return b&&c===!0&&(f=b(h),f===!1||"skip"===f)?d?f:k():h.children||h.lazy?(e=new a.Deferred,g=[],h.load().done(function(){for(var c=0,d=h.children.length;d>c;c++){if(f=h.children[c].visitAndLoad(b,!0,!0),f===!1){e.reject();break}"skip"!==f&&g.push(f)}a.when.apply(this,g).then(function(){e.resolve()})}),e.promise()):k()},visitParents:function(a,b){if(b&&a(this)===!1)return!1;for(var c=this.parent;c;){if(a(c)===!1)return!1;c=c.parent}return!0},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),f("warn",arguments)}},r.prototype={_makeHookContext:function(b,c,e){var f,g;return b.node!==d?(c&&b.originalEvent!==c&&a.error("invalid args"),f=b):b.tree?(g=b.tree,f={node:b,tree:g,widget:g.widget,options:g.widget.options,originalEvent:c}):b.widget?f={node:null,tree:b,widget:b.widget,options:b.widget.options,originalEvent:c}:a.error("invalid args"),e&&a.extend(f,e),f},_callHook:function(b,c){var d=this._makeHookContext(c),e=this[b],f=Array.prototype.slice.call(arguments,2);return a.isFunction(e)||a.error("_callHook('"+b+"') is not a function"),f.unshift(d),e.apply(this,f)},_requireExtension:function(b,c,d,f){d=!!d;var g=this._local.name,h=this.options.extensions,i=a.inArray(b,h)<a.inArray(g,h),j=c&&null==this.ext[b],k=!j&&null!=d&&d!==i;return e(g&&g!==b,"invalid or same name"),j||k?(f||(j||c?(f="'"+g+"' extension requires '"+b+"'",k&&(f+=" to be registered "+(d?"before":"after")+" itself")):f="If used together, `"+b+"` must be registered "+(d?"before":"after")+" `"+g+"`"),a.error(f),!1):!0},activateKey:function(a){var b=this.getNodeByKey(a);return b?b.setActive():this.activeNode&&this.activeNode.setActive(!1),b},applyPatch:function(b){var c,d,f,g,h,i,j=b.length,k=[];for(d=0;j>d;d++)f=b[d],e(2===f.length,"patchList must be an array of length-2-arrays"),g=f[0],h=f[1],i=null===g?this.rootNode:this.getNodeByKey(g),i?(c=new a.Deferred,k.push(c),i.applyPatch(h).always(m(c,i))):this.warn("could not find node with key '"+g+"'");return a.when.apply(a,k).promise()},count:function(){return this.rootNode.countChildren()},debug:function(){this.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},findAll:function(a){return this.rootNode.findAll(a)},findFirst:function(a){return this.rootNode.findFirst(a)},findNextNode:function(b,c){var d=null,e=c.parent.children,f=null,g=function(a,b,c){var d,e,f=a.children,h=f.length,i=f[b];if(i&&c(i)===!1)return!1;if(i&&i.children&&i.expanded&&g(i,0,c)===!1)return!1;for(d=b+1;h>d;d++)if(g(a,d,c)===!1)return!1;return e=a.parent,e?g(e,e.children.indexOf(a)+1,c):g(a,0,c)};return b="string"==typeof b?p(b):b,c=c||this.getFirstChild(),g(c.parent,e.indexOf(c),function(e){return e===d?!1:(d=d||e,a(e.span).is(":visible")?b(e)&&(f=e,f!==c)?!1:void 0:void e.debug("quicksearch: skipping hidden node"))}),f},generateFormElements:function(b,c,d){d=d||{};var e,f="string"==typeof b?b:"ft_"+this._id+"[]",g="string"==typeof c?c:"ft_"+this._id+"_active",h="fancytree_result_"+this._id,i=a("#"+h),j=3===this.options.selectMode&&d.stopOnParents!==!1;i.length?i.empty():i=a("<div>",{id:h}).hide().insertAfter(this.$container),b!==!1&&(e=this.getSelectedNodes(j),a.each(e,function(b,c){i.append(a("<input>",{type:"checkbox",name:f,value:c.key,checked:!0}))})),c!==!1&&this.activeNode&&i.append(a("<input>",{type:"radio",name:g,value:this.activeNode.key,checked:!0}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getNodeByKey:function(a,b){var d,e;return!b&&(d=c.getElementById(this.options.idPrefix+a))?d.ftnode?d.ftnode:null:(b=b||this.rootNode,e=null,b.visit(function(b){return b.key===a?(e=b,!1):void 0},!0),e)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(a){var b=[];return this.rootNode.visit(function(c){return c.selected&&(b.push(c),a===!0)?"skip":void 0}),b},hasFocus:function(){return!!this._hasFocus},info:function(){this.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),f("info",arguments))},loadKeyPath:function(b,c,e){function f(a,b,d){c.call(r,b,"loading"),b.load().done(function(){r.loadKeyPath.call(r,l[a],c,b).always(m(d,r))}).fail(function(){r.warn("loadKeyPath: error loading: "+a+" (parent: "+o+")"),c.call(r,b,"error"),d.reject()})}var g,h,i,j,k,l,n,o,p,q=this.options.keyPathSeparator,r=this;for(a.isArray(b)||(b=[b]),l={},i=0;i<b.length;i++)for(o=e||this.rootNode,j=b[i],j.charAt(0)===q&&(j=j.substr(1)),p=j.split(q);p.length;){if(k=p.shift(),n=o._findDirectChild(k),!n){this.warn("loadKeyPath: key not found: "+k+" (parent: "+o+")"),c.call(this,k,"error");break}if(0===p.length){c.call(this,n,"ok");break}if(n.lazy&&n.hasChildren()===d){c.call(this,n,"loaded"),l[k]?l[k].push(p.join(q)):l[k]=[p.join(q)];break}c.call(this,n,"loaded"),o=n}g=[];for(k in l)n=o._findDirectChild(k),h=new a.Deferred,g.push(h),f(k,n,h);return a.when.apply(a,g).promise()},reactivate:function(a){var b,c=this.activeNode;return c?(this.activeNode=null,b=c.setActive(),a&&c.setFocus(),b):k()},reload:function(a){return this._callHook("treeClear",this),this._callHook("treeLoad",this,a)},render:function(a,b){return this.rootNode.render(a,b)},setFocus:function(a){return this._callHook("treeSetFocus",this,a)},toDict:function(a,b){var c=this.rootNode.toDict(!0,b);return a?c:c.children},toString:function(){return"<Fancytree(#"+this._id+")>"},_triggerNodeEvent:function(a,b,c,e){var f=this._makeHookContext(b,c,e),g=this.widget._trigger(a,c,f);return g!==!1&&f.result!==d?f.result:g},_triggerTreeEvent:function(a,b,c){var e=this._makeHookContext(this,b,c),f=this.widget._trigger(a,b,e);return f!==!1&&e.result!==d?e.result:f},visit:function(a){return this.rootNode.visit(a,!1)},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),f("warn",arguments)}},a.extend(r.prototype,{nodeClick:function(a){var b,c,d=a.targetType,e=a.node;if("expander"===d){if(e.isLoading())return void e.debug("Got 2nd click while loading: ignored");this._callHook("nodeToggleExpanded",a)}else if("checkbox"===d)this._callHook("nodeToggleSelected",a),a.options.focusOnSelect&&this._callHook("nodeSetFocus",a,!0);else{if(c=!1,b=!0,e.folder)switch(a.options.clickFolderMode){case 2:c=!0,b=!1;break;case 3:b=!0,c=!0}b&&(this.nodeSetFocus(a),this._callHook("nodeSetActive",a,!0)),c&&this._callHook("nodeToggleExpanded",a)}},nodeCollapseSiblings:function(a,b){var c,d,e,f=a.node;if(f.parent)for(c=f.parent.children,d=0,e=c.length;e>d;d++)c[d]!==f&&c[d].expanded&&this._callHook("nodeSetExpanded",c[d],!1,b)},nodeDblclick:function(a){"title"===a.targetType&&4===a.options.clickFolderMode&&this._callHook("nodeToggleExpanded",a),"title"===a.targetType&&a.originalEvent.preventDefault()},nodeKeydown:function(b){var c,d,e,f,g=b.originalEvent,h=b.node,i=b.tree,j=b.options,k=g.which,l=String.fromCharCode(k),m=!(g.altKey||g.ctrlKey||g.metaKey||g.shiftKey),n=a(g.target),o=!0,p=!(g.ctrlKey||!j.autoActivate);if(h||(f=this.getActiveNode()||this.getFirstChild(),f&&(f.setFocus(),h=b.node=this.focusNode,h.debug("Keydown force focus on active node"))),j.quicksearch&&m&&/\w/.test(l)&&!n.is(":input:enabled"))return d=(new Date).getTime(),d-i.lastQuicksearchTime>500&&(i.lastQuicksearchTerm=""),i.lastQuicksearchTime=d,i.lastQuicksearchTerm+=l,c=i.findNextNode(i.lastQuicksearchTerm,i.getActiveNode()),c&&c.setActive(),void g.preventDefault();switch(u.eventToString(g)){case"+":case"=":i.nodeSetExpanded(b,!0);break;case"-":i.nodeSetExpanded(b,!1);break;case"space":j.checkbox?i.nodeToggleSelected(b):i.nodeSetActive(b,!0);break;case"return":i.nodeSetActive(b,!0);break;case"backspace":case"left":case"right":case"up":case"down":e=h.navigate(g.which,p);break;default:o=!1}o&&g.preventDefault()},nodeLoadChildren:function(b,c){var d,f,g,h=b.tree,i=b.node;return a.isFunction(c)&&(c=c()),c.url&&(d=a.extend({},b.options.ajax,c),d.debugDelay?(f=d.debugDelay,a.isArray(f)&&(f=f[0]+Math.random()*(f[1]-f[0])),i.debug("nodeLoadChildren waiting debug delay "+Math.round(f)+"ms"),d.debugDelay=!1,g=a.Deferred(function(b){setTimeout(function(){a.ajax(d).done(function(){b.resolveWith(this,arguments)}).fail(function(){b.rejectWith(this,arguments)})},f)})):g=a.ajax(d),c=new a.Deferred,g.done(function(d){var e,f;if("json"===this.dataType&&"string"==typeof d&&a.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),b.options.postProcess){if(f=h._triggerNodeEvent("postProcess",b,b.originalEvent,{response:d,error:null,dataType:this.dataType}),f.error)return e=a.isPlainObject(f.error)?f.error:{message:f.error},e=h._makeHookContext(i,null,e),void c.rejectWith(this,[e]);d=a.isArray(f)?f:d}else d&&d.hasOwnProperty("d")&&b.options.enableAspx&&(d="string"==typeof d.d?a.parseJSON(d.d):d.d);c.resolveWith(this,[d])}).fail(function(a,b,d){var e=h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:d,details:a.status+": "+d});c.rejectWith(this,[e])})),a.isFunction(c.then)&&a.isFunction(c["catch"])&&(g=c,c=new a.Deferred,g.then(function(a){c.resolve(a)},function(a){c.reject(a)})),a.isFunction(c.promise)&&(e(!i.isLoading(),"recursive load"),h.nodeSetStatus(b,"loading"),c.done(function(){h.nodeSetStatus(b,"ok")}).fail(function(a){var c;c=a.node&&a.error&&a.message?a:h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:a?a.message||a.toString():""}),h._triggerNodeEvent("loadError",c,null)!==!1&&h.nodeSetStatus(b,"error",c.message,c.details)})),a.when(c).done(function(b){var c;a.isPlainObject(b)&&(e(i.isRootNode(),"source may only be an object for root nodes (expecting an array of child objects otherwise)"),e(a.isArray(b.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),c=b,b=b.children,delete c.children,a.extend(h.data,c)),e(a.isArray(b),"expected array of children"),i._setChildren(b),h._triggerNodeEvent("loadChildren",i)})},nodeLoadKeyPath:function(){},nodeRemoveChild:function(b,c){var d,f=b.node,g=b.options,h=a.extend({},b,{node:c}),i=f.children;return 1===i.length?(e(c===i[0],"invalid single child"),this.nodeRemoveChildren(b)):(this.activeNode&&(c===this.activeNode||this.activeNode.isDescendantOf(c))&&this.activeNode.setActive(!1),this.focusNode&&(c===this.focusNode||this.focusNode.isDescendantOf(c))&&(this.focusNode=null),this.nodeRemoveMarkup(h),this.nodeRemoveChildren(h),d=a.inArray(c,i),e(d>=0,"invalid child"),c.visit(function(a){a.parent=null},!0),this._callHook("treeRegisterNode",this,!1,c),g.removeNode&&g.removeNode.call(b.tree,{type:"removeNode"},h),void i.splice(d,1))},nodeRemoveChildMarkup:function(b){var c=b.node;c.ul&&(c.isRootNode()?a(c.ul).empty():(a(c.ul).remove(),c.ul=null),c.visit(function(a){a.li=a.ul=null}))},nodeRemoveChildren:function(b){var c,d=b.tree,e=b.node,f=e.children,g=b.options;f&&(this.activeNode&&this.activeNode.isDescendantOf(e)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(e)&&(this.focusNode=null),this.nodeRemoveChildMarkup(b),c=a.extend({},b),e.visit(function(a){a.parent=null,d._callHook("treeRegisterNode",d,!1,a),g.removeNode&&(c.node=a,g.removeNode.call(b.tree,{type:"removeNode"},c))}),e.children=e.lazy?[]:null,e.isRootNode()||(e.expanded=!1),this.nodeRenderStatus(b))},nodeRemoveMarkup:function(b){var c=b.node;c.li&&(a(c.li).remove(),c.li=null),this.nodeRemoveChildMarkup(b)},nodeRender:function(b,d,f,g,h){var i,j,k,l,m,n,o,p=b.node,q=b.tree,r=b.options,s=r.aria,t=!1,u=p.parent,v=!u,w=p.children,x=null;if(v||u.ul){if(e(v||u.ul,"parent UL must exist"),v||(p.li&&(d||p.li.parentNode!==p.parent.ul)&&(p.li.parentNode===p.parent.ul?x=p.li.nextSibling:this.debug("Unlinking "+p+" (must be child of "+p.parent+")"),this.nodeRemoveMarkup(b)),p.li?this.nodeRenderStatus(b):(t=!0,p.li=c.createElement("li"),p.li.ftnode=p,p.key&&r.generateIds&&(p.li.id=r.idPrefix+p.key),p.span=c.createElement("span"),p.span.className="fancytree-node",s&&a(p.span).attr("aria-labelledby","ftal_"+p.key),p.li.appendChild(p.span),this.nodeRenderTitle(b),r.createNode&&r.createNode.call(q,{type:"createNode"},b)),r.renderNode&&r.renderNode.call(q,{type:"renderNode"},b)),w){if(v||p.expanded||f===!0){for(p.ul||(p.ul=c.createElement("ul"),(g===!0&&!h||!p.expanded)&&(p.ul.style.display="none"),s&&a(p.ul).attr("role","group"),p.li?p.li.appendChild(p.ul):p.tree.$div.append(p.ul)),l=0,m=w.length;m>l;l++)o=a.extend({},b,{node:w[l]}),this.nodeRender(o,d,f,!1,!0);for(i=p.ul.firstChild;i;)k=i.ftnode,k&&k.parent!==p?(p.debug("_fixParent: remove missing "+k,i),n=i.nextSibling,i.parentNode.removeChild(i),i=n):i=i.nextSibling;for(i=p.ul.firstChild,l=0,m=w.length-1;m>l;l++)j=w[l],k=i.ftnode,j!==k?p.ul.insertBefore(j.li,k.li):i=i.nextSibling}}else p.ul&&(this.warn("remove child markup for "+p),this.nodeRemoveChildMarkup(b));v||t&&u.ul.insertBefore(p.li,x)}},nodeRenderTitle:function(a,b){var c,e,f,g,h,i,j=a.node,k=a.tree,l=a.options,m=l.aria,n=j.getLevel(),o=[],p=j.data.icon;b!==d&&(j.title=b),j.span&&(n<l.minExpandLevel?(j.lazy||(j.expanded=!0),n>1&&o.push(m?"<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>":"<span class='fancytree-expander fancytree-expander-fixed''></span>")):o.push(m?"<span role='button' class='fancytree-expander'></span>":"<span class='fancytree-expander'></span>"),l.checkbox&&j.hideCheckbox!==!0&&!j.isStatusNode()&&o.push(m?"<span role='checkbox' class='fancytree-checkbox'></span>":"<span class='fancytree-checkbox'></span>"),g=m?" role='img'":"",(p===!0||p!==!1&&l.icons!==!1)&&(p&&"string"==typeof p?(p="/"===p.charAt(0)?p:(l.imagePath||"")+p,o.push("<img src='"+p+"' class='fancytree-icon' alt='' />")):(e=l.iconClass&&l.iconClass.call(k,{type:"iconClass"},a)||j.data.iconclass||null,o.push(e?"<span "+g+" class='fancytree-custom-icon "+e+"'></span>":"<span "+g+" class='fancytree-icon'></span>"))),f="",l.renderTitle&&(f=l.renderTitle.call(k,{type:"renderTitle"},a)||""),f||(i=j.tooltip?" title='"+u.escapeHtml(j.tooltip)+"'":"",c=m?" id='ftal_"+j.key+"'":"",g=m?" role='treeitem'":"",h=l.titlesTabbable?" tabindex='0'":"",f="<span "+g+" class='fancytree-title'"+c+i+h+">"+j.title+"</span>"),o.push(f),j.span.innerHTML=o.join(""),this.nodeRenderStatus(a))
+},nodeRenderStatus:function(b){var c=b.node,d=b.tree,e=b.options,f=c.hasChildren(),g=c.isLastSibling(),h=e.aria,i=a(c.span).find(".fancytree-title"),j=e._classNames,k=[],l=c[d.statusClassPropName];l&&(k.push(j.node),d.activeNode===c&&k.push(j.active),d.focusNode===c?(k.push(j.focused),h&&i.attr("aria-activedescendant",!0)):h&&i.removeAttr("aria-activedescendant"),c.expanded?(k.push(j.expanded),h&&i.attr("aria-expanded",!0)):h&&i.removeAttr("aria-expanded"),c.folder&&k.push(j.folder),f!==!1&&k.push(j.hasChildren),g&&k.push(j.lastsib),c.lazy&&null==c.children&&k.push(j.lazy),c.partsel&&k.push(j.partsel),c.unselectable&&k.push(j.unselectable),c._isLoading&&k.push(j.loading),c._error&&k.push(j.error),c.selected?(k.push(j.selected),h&&i.attr("aria-selected",!0)):h&&i.attr("aria-selected",!1),c.extraClasses&&k.push(c.extraClasses),k.push(f===!1?j.combinedExpanderPrefix+"n"+(g?"l":""):j.combinedExpanderPrefix+(c.expanded?"e":"c")+(c.lazy&&null==c.children?"d":"")+(g?"l":"")),k.push(j.combinedIconPrefix+(c.expanded?"e":"c")+(c.folder?"f":"")),l.className=k.join(" "),c.li&&(c.li.className=g?j.lastsib:""))},nodeSetActive:function(b,c,d){d=d||{};var f,g=b.node,h=b.tree,i=b.options,j=d.noEvents===!0,m=d.noFocus===!0,n=g===h.activeNode;return c=c!==!1,n===c?k(g):c&&!j&&this._triggerNodeEvent("beforeActivate",g,b.originalEvent)===!1?l(g,["rejected"]):(c?(h.activeNode&&(e(h.activeNode!==g,"node was active (inconsistency)"),f=a.extend({},b,{node:h.activeNode}),h.nodeSetActive(f,!1),e(null===h.activeNode,"deactivate was out of sync?")),i.activeVisible&&g.makeVisible({scrollIntoView:!1}),h.activeNode=g,h.nodeRenderStatus(b),m||h.nodeSetFocus(b),j||h._triggerNodeEvent("activate",g,b.originalEvent)):(e(h.activeNode===g,"node was not active (inconsistency)"),h.activeNode=null,this.nodeRenderStatus(b),j||b.tree._triggerNodeEvent("deactivate",g,b.originalEvent)),k(g))},nodeSetExpanded:function(b,c,e){e=e||{};var f,g,h,i,j,m,n=b.node,o=b.tree,p=b.options,q=e.noAnimation===!0,r=e.noEvents===!0;if(c=c!==!1,n.expanded&&c||!n.expanded&&!c)return k(n);if(c&&!n.lazy&&!n.hasChildren())return k(n);if(!c&&n.getLevel()<p.minExpandLevel)return l(n,["locked"]);if(!r&&this._triggerNodeEvent("beforeExpand",n,b.originalEvent)===!1)return l(n,["rejected"]);if(q||n.isVisible()||(q=e.noAnimation=!0),g=new a.Deferred,c&&!n.expanded&&p.autoCollapse){j=n.getParentList(!1,!0),m=p.autoCollapse;try{for(p.autoCollapse=!1,h=0,i=j.length;i>h;h++)this._callHook("nodeCollapseSiblings",j[h],e)}finally{p.autoCollapse=m}}return g.done(function(){var a=n.getLastChild();c&&p.autoScroll&&!q&&a?a.scrollIntoView(!0,{topNode:n}).always(function(){r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}):r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}),f=function(d){var e,f,g=p.toggleEffect;if(n.expanded=c,o._callHook("nodeRender",b,!1,!1,!0),n.ul)if(e="none"!==n.ul.style.display,f=!!n.expanded,e===f)n.warn("nodeSetExpanded: UL.style.display already set");else{if(g&&!q)return void a(n.ul).toggle(g.effect,g.options,g.duration,function(){d()});n.ul.style.display=n.expanded||!parent?"":"none"}d()},c&&n.lazy&&n.hasChildren()===d?n.load().done(function(){g.notifyWith&&g.notifyWith(n,["loaded"]),f(function(){g.resolveWith(n)})}).fail(function(a){f(function(){g.rejectWith(n,["load failed ("+a+")"])})}):f(function(){g.resolveWith(n)}),g.promise()},nodeSetFocus:function(b,c){var d,e=b.tree,f=b.node;if(c=c!==!1,e.focusNode){if(e.focusNode===f&&c)return;d=a.extend({},b,{node:e.focusNode}),e.focusNode=null,this._triggerNodeEvent("blur",d),this._callHook("nodeRenderStatus",d)}c&&(this.hasFocus()||(f.debug("nodeSetFocus: forcing container focus"),this._callHook("treeSetFocus",b,!0,{calledByNode:!0})),f.makeVisible({scrollIntoView:!1}),e.focusNode=f,this._triggerNodeEvent("focus",b),b.options.autoScroll&&f.scrollIntoView(),this._callHook("nodeRenderStatus",b))},nodeSetSelected:function(a,b){var c=a.node,d=a.tree,e=a.options;if(b=b!==!1,c.debug("nodeSetSelected("+b+")",a),!c.unselectable){if(c.selected&&b||!c.selected&&!b)return!!c.selected;if(this._triggerNodeEvent("beforeSelect",c,a.originalEvent)===!1)return!!c.selected;b&&1===e.selectMode?d.lastSelectedNode&&d.lastSelectedNode.setSelected(!1):3===e.selectMode&&(c.selected=b,c.fixSelection3AfterClick()),c.selected=b,this.nodeRenderStatus(a),d.lastSelectedNode=b?c:null,d._triggerNodeEvent("select",a)}},nodeSetStatus:function(b,c,d,e){function f(){var a=h.children?h.children[0]:null;if(a&&a.isStatusNode()){try{h.ul&&(h.ul.removeChild(a.li),a.li=null)}catch(b){}1===h.children.length?h.children=[]:h.children.shift()}}function g(b,c){var d=h.children?h.children[0]:null;return d&&d.isStatusNode()?(a.extend(d,b),i._callHook("nodeRenderTitle",d)):(b.key="_statusNode",h._setChildren([b]),h.children[0].statusNodeType=c,i.render()),h.children[0]}var h=b.node,i=b.tree;switch(c){case"ok":f(),h._isLoading=!1,h._error=null,h.renderStatus();break;case"loading":h.parent||g({title:i.options.strings.loading+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-wait"},c),h._isLoading=!0,h._error=null,h.renderStatus();break;case"error":g({title:i.options.strings.loadError+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-error"},c),h._isLoading=!1,h._error={message:d,details:e},h.renderStatus();break;default:a.error("invalid node status "+c)}},nodeToggleExpanded:function(a){return this.nodeSetExpanded(a,!a.node.expanded)},nodeToggleSelected:function(a){return this.nodeSetSelected(a,!a.node.selected)},treeClear:function(a){var b=a.tree;b.activeNode=null,b.focusNode=null,b.$div.find(">ul.fancytree-container").empty(),b.rootNode.children=null},treeCreate:function(){},treeDestroy:function(){this.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("ui-helper-hidden")},treeInit:function(a){this.treeLoad(a)},treeLoad:function(b,c){var d,e,f,g=b.tree,h=b.widget.element,i=a.extend({},b,{node:this.rootNode});if(g.rootNode.children&&this.treeClear(b),c=c||this.options.source)"string"==typeof c&&a.error("Not implemented");else switch(d=h.data("type")||"html"){case"html":e=h.find(">ul:first"),e.addClass("ui-fancytree-source ui-helper-hidden"),c=a.ui.fancytree.parseHtml(e),this.data=a.extend(this.data,n(e));break;case"json":c=a.parseJSON(h.text()),c.children&&(c.title&&(g.title=c.title),c=c.children);break;default:a.error("Invalid data-type: "+d)}return f=this.nodeLoadChildren(i,c).done(function(){g.render(),3===b.options.selectMode&&g.rootNode.fixSelection3FromEndNodes(),g.activeNode&&g.options.activeVisible&&g.activeNode.makeVisible(),g._triggerTreeEvent("init",null,{status:!0})}).fail(function(){g.render(),g._triggerTreeEvent("init",null,{status:!1})})},treeRegisterNode:function(){},treeSetFocus:function(a,b){b=b!==!1,b!==this.hasFocus()&&(this._hasFocus=b,!b&&this.focusNode&&this.focusNode.setFocus(!1),this.$container.toggleClass("fancytree-treefocus",b),this._triggerTreeEvent(b?"focusTree":"blurTree"))}}),a.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!1,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,debugLevel:null,disabled:!1,enableAspx:!0,extensions:[],toggleEffect:{effect:"blind",options:{direction:"vertical",scale:"box"},duration:200},generateIds:!1,icons:!0,idPrefix:"ft_",focusOnSelect:!1,keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,quicksearch:!1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading&#8230;",loadError:"Load error!"},tabbable:!0,titlesTabbable:!1,_classNames:{node:"fancytree-node",folder:"fancytree-folder",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",hasChildren:"fancytree-has-children",active:"fancytree-active",selected:"fancytree-selected",expanded:"fancytree-expanded",lazy:"fancytree-lazy",focused:"fancytree-focused",partsel:"fancytree-partsel",unselectable:"fancytree-unselectable",lastsib:"fancytree-lastsib",loading:"fancytree-loading",error:"fancytree-error"},lazyLoad:null,postProcess:null},_create:function(){this.tree=new r(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul:first");var b,c,f,g=this.options.extensions,h=this.tree;for(f=0;f<g.length;f++)c=g[f],b=a.ui.fancytree._extensions[c],b||a.error("Could not apply extension '"+c+"' (it is not registered, did you forget to include it?)"),this.tree.options[c]=a.extend(!0,{},b.options,this.tree.options[c]),e(this.tree.ext[c]===d,"Extension name must not exist as Fancytree.ext attribute: '"+c+"'"),this.tree.ext[c]={},j(this.tree,h,b,c),h=b;this.tree._callHook("treeCreate",this.tree)},_init:function(){this.tree._callHook("treeInit",this.tree),this._bind()},_setOption:function(b,c){var d=!0,e=!1;switch(b){case"aria":case"checkbox":case"icons":case"minExpandLevel":case"tabbable":this.tree._callHook("treeCreate",this.tree),e=!0;break;case"source":d=!1,this.tree._callHook("treeLoad",this.tree,c)}this.tree.debug("set option "+b+"="+c+" <"+typeof c+">"),d&&a.Widget.prototype._setOption.apply(this,arguments),e&&this.tree.render(!0,!1)},destroy:function(){this._unbind(),this.tree._callHook("treeDestroy",this.tree),a.Widget.prototype.destroy.call(this)},_unbind:function(){var b=this.tree._ns;this.element.unbind(b),this.tree.$container.unbind(b),a(c).unbind(b)},_bind:function(){var a=this,b=this.options,c=this.tree,d=c._ns;this._unbind(),c.$container.on("focusin"+d+" focusout"+d,function(a){var b=u.getNode(a),d="focusin"===a.type;b?c._callHook("nodeSetFocus",b,d):c._callHook("treeSetFocus",c,d)}).on("selectstart"+d,"span.fancytree-title",function(a){a.preventDefault()}).on("keydown"+d,function(a){if(b.disabled||b.keyboard===!1)return!0;var d,e=c.focusNode,f=c._makeHookContext(e||c,a),g=c.phase;try{return c.phase="userEvent",d=e?c._triggerNodeEvent("keydown",e,a):c._triggerTreeEvent("keydown",a),"preventNav"===d?d=!0:d!==!1&&(d=c._callHook("nodeKeydown",f)),d}finally{c.phase=g}}).on("click"+d+" dblclick"+d,function(c){if(b.disabled)return!0;var d,e=u.getEventTarget(c),f=e.node,g=a.tree,h=g.phase;if(!f)return!0;d=g._makeHookContext(f,c);try{switch(g.phase="userEvent",c.type){case"click":return d.targetType=e.type,g._triggerNodeEvent("click",d,c)===!1?!1:g._callHook("nodeClick",d);case"dblclick":return d.targetType=e.type,g._triggerNodeEvent("dblclick",d,c)===!1?!1:g._callHook("nodeDblclick",d)}}finally{g.phase=h}})},getActiveNode:function(){return this.tree.activeNode},getNodeByKey:function(a){return this.tree.getNodeByKey(a)},getRootNode:function(){return this.tree.rootNode},getTree:function(){return this.tree}}),u=a.ui.fancytree,a.extend(a.ui.fancytree,{version:"2.13.0",buildType: "production",debugLevel: 1,_nextId:1,_nextNodeKey:1,_extensions:{},_FancytreeClass:r,_FancytreeNodeClass:q,jquerySupports:{positionMyOfs:h(a.ui.version,1,9)},assert:function(a,b){return e(a,b)},debounce:function(a,b,c,d){var e;return 3===arguments.length&&"boolean"!=typeof c&&(d=c,c=!1),function(){var f=arguments;d=d||this,c&&!e&&b.apply(d,f),clearTimeout(e),e=setTimeout(function(){c||b.apply(d,f),e=null},a)}},debug:function(){a.ui.fancytree.debugLevel>=2&&f("log",arguments)},error:function(){f("error",arguments)},escapeHtml:function(a){return(""+a).replace(/[&<>"'\/]/g,function(a){return v[a]})},fixPositionOptions:function(b){if((b.offset||(""+b.my+b.at).indexOf("%")>=0)&&a.error("expected new position syntax (but '%' is not supported)"),!a.ui.fancytree.jquerySupports.positionMyOfs){var c=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(b.my),d=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(b.at),e=(c[2]?+c[2]:0)+(d[2]?+d[2]:0),f=(c[4]?+c[4]:0)+(d[4]?+d[4]:0);b=a.extend({},b,{my:c[1]+" "+c[3],at:d[1]+" "+d[3]}),(e||f)&&(b.offset=""+e+" "+f)}return b},getEventTargetType:function(a){return this.getEventTarget(a).type},getEventTarget:function(b){var c=b&&b.target?b.target.className:"",e={node:this.getNode(b.target),type:d};return/\bfancytree-title\b/.test(c)?e.type="title":/\bfancytree-expander\b/.test(c)?e.type=e.node.hasChildren()===!1?"prefix":"expander":/\bfancytree-checkbox\b/.test(c)||/\bfancytree-radio\b/.test(c)?e.type="checkbox":/\bfancytree-icon\b/.test(c)?e.type="icon":/\bfancytree-node\b/.test(c)?e.type="title":b&&b.target&&a(b.target).closest(".fancytree-title").length&&(e.type="title"),e},getNode:function(a){if(a instanceof q)return a;for(a.selector!==d?a=a[0]:a.originalEvent!==d&&(a=a.target);a;){if(a.ftnode)return a.ftnode;a=a.parentNode}return null},getTree:function(b){var c;return b instanceof r?b:(b===d&&(b=0),"number"==typeof b?b=a(".fancytree-container").eq(b):"string"==typeof b?b=a(b).eq(0):b.selector!==d?b=b.eq(0):b.originalEvent!==d&&(b=a(b.target)),b=b.closest(":ui-fancytree"),c=b.data("ui-fancytree")||b.data("fancytree"),c?c.tree:null)},info:function(){a.ui.fancytree.debugLevel>=1&&f("info",arguments)},eventToString:function(a){var b=a.which,c=a.type,d=[];return a.altKey&&d.push("alt"),a.ctrlKey&&d.push("ctrl"),a.metaKey&&d.push("meta"),a.shiftKey&&d.push("shift"),"click"===c||"dblclick"===c?d.push(y[a.button]+c):w[b]||d.push(x[b]||String.fromCharCode(b).toLowerCase()),d.join("+")},keyEventToString:function(a){return this.warn("keyEventToString() is deprecated: use eventToString()"),this.eventToString(a)},parseHtml:function(b){var c,e,f,g,h,i,j,k,l=b.find(">li"),m=[];return l.each(function(){var l,o,p=a(this),q=p.find(">span:first",this),r=q.length?null:p.find(">a:first"),s={tooltip:null,data:{}};for(q.length?s.title=q.html():r&&r.length?(s.title=r.html(),s.data.href=r.attr("href"),s.data.target=r.attr("target"),s.tooltip=r.attr("title")):(s.title=p.html(),h=s.title.search(/<ul/i),h>=0&&(s.title=s.title.substring(0,h))),s.title=a.trim(s.title),g=0,i=z.length;i>g;g++)s[z[g]]=d;for(c=this.className.split(" "),f=[],g=0,i=c.length;i>g;g++)e=c[g],A[e]?s[e]=!0:f.push(e);if(s.extraClasses=f.join(" "),j=p.attr("title"),j&&(s.tooltip=j),j=p.attr("id"),j&&(s.key=j),l=n(p),l&&!a.isEmptyObject(l)){for(o in D)l.hasOwnProperty(o)&&(l[D[o]]=l[o],delete l[o]);for(g=0,i=B.length;i>g;g++)j=B[g],k=l[j],null!=k&&(delete l[j],s[j]=k);a.extend(s.data,l)}b=p.find(">ul:first"),s.children=b.length?a.ui.fancytree.parseHtml(b):s.lazy?d:null,m.push(s)}),m},registerExtension:function(b){e(null!=b.name,"extensions must have a `name` property."),e(null!=b.version,"extensions must have a `version` property."),a.ui.fancytree._extensions[b.name]=b},unescapeHtml:function(a){var b=c.createElement("div");return b.innerHTML=a,0===b.childNodes.length?"":b.childNodes[0].nodeValue},warn:function(){f("warn",arguments)}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.childcounter.min.js' */
+!function(a){"use strict";a.ui.fancytree._FancytreeClass.prototype.countSelected=function(a){{var b=this;b.options}return b.getSelectedNodes(a).length},a.ui.fancytree._FancytreeNodeClass.prototype.updateCounters=function(){var b=this,c=a("span.fancytree-childcounter",b.span),d=b.tree.options.childcounter,e=b.countChildren(d.deep);b.data.childCounter=e,!e&&d.hideZeros||b.isExpanded()&&d.hideExpanded?c.remove():(c.length||(c=a("<span class='fancytree-childcounter'/>").appendTo(a("span.fancytree-icon",b.span))),c.text(e)),!d.deep||b.isTopLevel()||b.isRoot()||b.parent.updateCounters()},a.ui.fancytree.prototype.widgetMethod1=function(a){this.tree;return a},a.ui.fancytree.registerExtension({name:"childcounter",version:"1.0.0",options:{deep:!0,hideZeros:!0,hideExpanded:!1},foo:42,_appendCounter:function(){},treeInit:function(a){a.options,a.options.childcounter;this._superApply(arguments),this.$container.addClass("fancytree-ext-childcounter")},treeDestroy:function(){this._superApply(arguments)},nodeRenderTitle:function(b){var c=b.node,d=b.options.childcounter,e=null==c.data.childCounter?c.countChildren(d.deep):+c.data.childCounter;this._superApply(arguments),!e&&d.hideZeros||c.isExpanded()&&d.hideExpanded||a("span.fancytree-icon",c.span).append(a("<span class='fancytree-childcounter'/>").text(e))},nodeSetExpanded:function(a){{var b=a.tree;a.node}return this._superApply(arguments).always(function(){b.nodeRenderTitle(a)})}})}(jQuery);
+
+/*! Extension 'jquery.fancytree.clones.min.js' */
+!function(a){"use strict";function b(b,c){b||(c=c?": "+c:"",a.error("Assertion failed"+c))}function c(a,b){var c;for(c=a.length-1;c>=0;c--)if(a[c]===b)return a.splice(c,1),!0;return!1}function d(a,b,c){for(var d,e,f=3&a.length,g=a.length-f,h=c,i=3432918353,j=461845907,k=0;g>k;)e=255&a.charCodeAt(k)|(255&a.charCodeAt(++k))<<8|(255&a.charCodeAt(++k))<<16|(255&a.charCodeAt(++k))<<24,++k,e=(65535&e)*i+(((e>>>16)*i&65535)<<16)&4294967295,e=e<<15|e>>>17,e=(65535&e)*j+(((e>>>16)*j&65535)<<16)&4294967295,h^=e,h=h<<13|h>>>19,d=5*(65535&h)+((5*(h>>>16)&65535)<<16)&4294967295,h=(65535&d)+27492+(((d>>>16)+58964&65535)<<16);switch(e=0,f){case 3:e^=(255&a.charCodeAt(k+2))<<16;case 2:e^=(255&a.charCodeAt(k+1))<<8;case 1:e^=255&a.charCodeAt(k),e=(65535&e)*i+(((e>>>16)*i&65535)<<16)&4294967295,e=e<<15|e>>>17,e=(65535&e)*j+(((e>>>16)*j&65535)<<16)&4294967295,h^=e}return h^=a.length,h^=h>>>16,h=2246822507*(65535&h)+((2246822507*(h>>>16)&65535)<<16)&4294967295,h^=h>>>13,h=3266489909*(65535&h)+((3266489909*(h>>>16)&65535)<<16)&4294967295,h^=h>>>16,b?("0000000"+(h>>>0).toString(16)).substr(-8):h>>>0}function e(b){var c,e=a.map(b.getParentList(!1,!0),function(a){return a.refKey||a.key});return e=e.join("/"),c="id_"+d(e,!0)}a.ui.fancytree._FancytreeNodeClass.prototype.getCloneList=function(b){var c,d=this.tree,e=d.refMap[this.refKey]||null,f=d.keyMap;return e&&(c=this.key,b?e=a.map(e,function(a){return f[a]}):(e=a.map(e,function(a){return a===c?null:f[a]}),e.length<1&&(e=null))),e},a.ui.fancytree._FancytreeNodeClass.prototype.isClone=function(){var a=this.refKey||null,b=a&&this.tree.refMap[a]||null;return!!(b&&b.length>1)},a.ui.fancytree._FancytreeNodeClass.prototype.reRegister=function(b,c){b=null==b?null:""+b,c=null==c?null:""+c;var d=this.tree,e=this.key,f=this.refKey,g=d.keyMap,h=d.refMap,i=h[f]||null,j=!1;return null!=b&&b!==this.key&&(g[b]&&a.error("[ext-clones] reRegister("+b+"): already exists: "+this),delete g[e],g[b]=this,i&&(h[f]=a.map(i,function(a){return a===e?b:a})),this.key=b,j=!0),null!=c&&c!==this.refKey&&(i&&(1===i.length?delete h[f]:h[f]=a.map(i,function(a){return a===e?null:a})),h[c]?h[c].append(b):h[c]=[this.key],this.refKey=c,j=!0),j},a.ui.fancytree._FancytreeClass.prototype.getNodesByRef=function(b,c){var d=this.keyMap,e=this.refMap[b]||null;return e&&(e=c?a.map(e,function(a){var b=d[a];return b.isDescendantOf(c)?b:null}):a.map(e,function(a){return d[a]}),e.length<1&&(e=null)),e},a.ui.fancytree._FancytreeClass.prototype.changeRefKey=function(a,b){var c,d,e=this.keyMap,f=this.refMap[a]||null;if(f){for(c=0;c<f.length;c++)d=e[f[c]],d.refKey=b;delete this.refMap[a],this.refMap[b]=f}},a.ui.fancytree.registerExtension({name:"clones",version:"0.0.3",options:{highlightActiveClones:!0,highlightClones:!1},treeCreate:function(a){this._superApply(arguments),a.tree.refMap={},a.tree.keyMap={}},treeInit:function(a){this.$container.addClass("fancytree-ext-clones"),b(null==a.options.defaultKey),a.options.defaultKey=function(a){return e(a)},this._superApply(arguments)},treeClear:function(a){return a.tree.refMap={},a.tree.keyMap={},this._superApply(arguments)},treeRegisterNode:function(d,e,f){var g,h,i=d.tree,j=i.keyMap,k=i.refMap,l=f.key,m=f&&null!=f.refKey?""+f.refKey:null;return"_statusNode"===l?this._superApply(arguments):(e?(null!=j[f.key]&&a.error("clones.treeRegisterNode: node.key already exists: "+f),j[l]=f,m&&(g=k[m],g?(g.push(l),2===g.length&&d.options.clones.highlightClones&&j[g[0]].renderStatus()):k[m]=[l])):(null==j[l]&&a.error("clones.treeRegisterNode: node.key not registered: "+f.key),delete j[l],m&&(g=k[m],g&&(h=g.length,1>=h?(b(1===h),b(g[0]===l),delete k[m]):(c(g,l),2===h&&d.options.clones.highlightClones&&j[g[0]].renderStatus())))),this._superApply(arguments))},nodeRenderStatus:function(b){var c,d,e=b.node;return d=this._superApply(arguments),b.options.clones.highlightClones&&(c=a(e[b.tree.statusClassPropName]),c.length&&e.isClone()&&c.addClass("fancytree-clone")),d},nodeSetActive:function(b,c){var d,e=b.tree.statusClassPropName,f=b.node;return d=this._superApply(arguments),b.options.clones.highlightActiveClones&&f.isClone()&&a.each(f.getCloneList(!0),function(b,d){a(d[e]).toggleClass("fancytree-active-clone",c!==!1)}),d}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.dnd.min.js' */
+!function(a,b,c,d){"use strict";function e(a){return 0===a?"":a>0?"+"+a:""+a}function f(b){var c=b.options.dnd||null,d=b.options.glyph||null;c&&g(),c&&c.dragStart&&b.widget.element.draggable(a.extend({addClasses:!1,appendTo:b.$container,containment:!1,delay:0,distance:4,revert:!1,scroll:!0,scrollSpeed:7,scrollSensitivity:10,connectToFancytree:!0,helper:function(b){var c,e,f,g=a.ui.fancytree.getNode(b.target);return g?(f=g.tree.options.dnd,e=a(g.span),c=a("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>").css({zIndex:3,position:"relative"}).append(e.find("span.fancytree-title").clone()),c.data("ftSourceNode",g),d&&c.find(".fancytree-drag-helper-img").addClass(d.map.dragHelper),f.initHelper&&f.initHelper.call(g.tree,g,{node:g,tree:g.tree,originalEvent:b,ui:{helper:c}}),c):"<div>ERROR?: helper requested but sourceNode not found</div>"},start:function(a,b){var c=b.helper.data("ftSourceNode");return!!c}},b.options.dnd.draggable)),c&&c.dragDrop&&b.widget.element.droppable(a.extend({addClasses:!1,tolerance:"intersect",greedy:!1},b.options.dnd.droppable))}function g(){h||(a.ui.plugin.add("draggable","connectToFancytree",{start:function(b,c){var d=a(this).data("ui-draggable")||a(this).data("draggable"),e=c.helper.data("ftSourceNode")||null;return e?(d.offset.click.top=-2,d.offset.click.left=16,e.tree.ext.dnd._onDragEvent("start",e,null,b,c,d)):void 0},drag:function(b,c){var d,e,f,g=a(this).data("ui-draggable")||a(this).data("draggable"),h=c.helper.data("ftSourceNode")||null,i=c.helper.data("ftTargetNode")||null,j=a.ui.fancytree.getNode(b.target),k=h&&h.tree.options.dnd;return b.target&&!j&&(e=a(b.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length>0)?(f=h||i||a.ui.fancytree,void f.debug("Drag event over helper: ignored.")):(c.helper.data("ftTargetNode",j),k&&k.updateHelper&&(d=h.tree._makeHookContext(h,b,{otherNode:j,ui:c,draggable:g,dropMarker:a("#fancytree-drop-marker")}),k.updateHelper.call(h.tree,h,d)),i&&i!==j&&i.tree.ext.dnd._onDragEvent("leave",i,h,b,c,g),void(j&&j.tree.options.dnd.dragDrop&&(j===i?j.tree.ext.dnd._onDragEvent("over",j,h,b,c,g):j.tree.ext.dnd._onDragEvent("enter",j,h,b,c,g))))},stop:function(b,c){var d,e=a(this).data("ui-draggable")||a(this).data("draggable"),f=c.helper.data("ftSourceNode")||null,g=c.helper.data("ftTargetNode")||null,h="mouseup"===b.type&&1===b.which;h||(d=f||g||a.ui.fancytree,d.debug("Drag was cancelled")),g&&(h&&g.tree.ext.dnd._onDragEvent("drop",g,f,b,c,e),g.tree.ext.dnd._onDragEvent("leave",g,f,b,c,e)),f&&f.tree.ext.dnd._onDragEvent("stop",f,null,b,c,e)}}),h=!0)}var h=!1,i="fancytree-drop-accept",j="fancytree-drop-after",k="fancytree-drop-before",l="fancytree-drop-over",m="fancytree-drop-reject",n="fancytree-drop-target";a.ui.fancytree.registerExtension({name:"dnd",version:"0.2.0",options:{autoExpandMS:1e3,draggable:null,droppable:null,focusOnClick:!1,preventVoidMoves:!0,preventRecursiveMoves:!0,smartRevert:!0,dragStart:null,dragStop:null,initHelper:null,updateHelper:null,dragEnter:null,dragOver:null,dragDrop:null,dragLeave:null},treeInit:function(b){var c=b.tree;this._superApply(arguments),c.options.dnd.dragStart&&c.$container.on("mousedown",function(c){if(b.options.dnd.focusOnClick){var d=a.ui.fancytree.getNode(c);d&&d.debug("Re-enable focus that was prevented by jQuery UI draggable."),setTimeout(function(){a(c.target).closest(":tabbable").focus()},10)}}),f(c)},_setDndStatus:function(b,c,d,f,g){var h=0,o="center",p=this._local,q=this.options.glyph||null,r=b?a(b.span):null,s=a(c.span);if(p.$dropMarker||(p.$dropMarker=a("<div id='fancytree-drop-marker'></div>").hide().css({"z-index":1e3}).prependTo(a(this.$div).parent()),q&&p.$dropMarker.addClass(q.map.dropMarker)),"after"===f||"before"===f||"over"===f){switch(f){case"before":o="top";break;case"after":o="bottom";break;default:h=8}p.$dropMarker.toggleClass(j,"after"===f).toggleClass(l,"over"===f).toggleClass(k,"before"===f).show().position(a.ui.fancytree.fixPositionOptions({my:"left"+e(h)+" center",at:"left "+o,of:s}))}else p.$dropMarker.hide();r&&r.toggleClass(i,g===!0).toggleClass(m,g===!1),s.toggleClass(n,"after"===f||"before"===f||"over"===f).toggleClass(j,"after"===f).toggleClass(k,"before"===f).toggleClass(i,g===!0).toggleClass(m,g===!1),d.toggleClass(i,g===!0).toggleClass(m,g===!1)},_onDragEvent:function(b,e,f,g,h,i){"over"!==b&&this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o",b,e,f,this);var j,k,l,m,n,o,p,q=this.options,r=q.dnd,s=this._makeHookContext(e,g,{otherNode:f,ui:h,draggable:i}),t=null,u=this,v=a(e.span);switch(r.smartRevert&&(i.options.revert="invalid"),b){case"start":e.isStatusNode()?t=!1:r.dragStart&&(t=r.dragStart(e,s)),t===!1?(this.debug("tree.dragStart() cancelled"),h.helper.trigger("mouseup").hide()):(v.addClass("fancytree-drag-source"),a(c).on("keydown.fancytree-dnd,mousedown.fancytree-dnd",function(b){"keydown"===b.type&&b.which===a.ui.keyCode.ESCAPE?u.ext.dnd._cancelDrag():"mousedown"===b.type&&u.ext.dnd._cancelDrag()}));break;case"enter":p=r.preventRecursiveMoves&&e.isDescendantOf(f)?!1:r.dragEnter?r.dragEnter(e,s):null,t=p?a.isArray(p)?{over:a.inArray("over",p)>=0,before:a.inArray("before",p)>=0,after:a.inArray("after",p)>=0}:{over:p===!0||"over"===p,before:p===!0||"before"===p,after:p===!0||"after"===p}:!1,h.helper.data("enterResponse",t),this.debug("helper.enterResponse: %o",t);break;case"over":n=h.helper.data("enterResponse"),o=null,n===!1||("string"==typeof n?o=n:(k=v.offset(),l={x:g.pageX-k.left,y:g.pageY-k.top},m={x:l.x/v.width(),y:l.y/v.height()},n.after&&m.y>.75?o="after":!n.over&&n.after&&m.y>.5?o="after":n.before&&m.y<=.25?o="before":!n.over&&n.before&&m.y<=.5?o="before":n.over&&(o="over"),r.preventVoidMoves&&(e===f?(this.debug("    drop over source node prevented"),o=null):"before"===o&&f&&e===f.getNextSibling()?(this.debug("    drop after source node prevented"),o=null):"after"===o&&f&&e===f.getPrevSibling()?(this.debug("    drop before source node prevented"),o=null):"over"===o&&f&&f.parent===e&&f.isLastSibling()&&(this.debug("    drop last child over own parent prevented"),o=null)),h.helper.data("hitMode",o))),"over"===o&&r.autoExpandMS&&e.hasChildren()!==!1&&!e.expanded&&e.scheduleAction("expand",r.autoExpandMS),o&&r.dragOver&&(s.hitMode=o,t=r.dragOver(e,s)),j=t!==!1&&null!==o,r.smartRevert&&(i.options.revert=!j),this._local._setDndStatus(f,e,h.helper,o,j);break;case"drop":o=h.helper.data("hitMode"),o&&r.dragDrop&&(s.hitMode=o,r.dragDrop(e,s));break;case"leave":e.scheduleAction("cancel"),h.helper.data("enterResponse",null),h.helper.data("hitMode",null),this._local._setDndStatus(f,e,h.helper,"out",d),r.dragLeave&&r.dragLeave(e,s);break;case"stop":v.removeClass("fancytree-drag-source"),a(c).off(".fancytree-dnd"),r.dragStop&&r.dragStop(e,s);break;default:a.error("Unsupported drag event: "+b)}return t},_cancelDrag:function(){var b=a.ui.ddmanager.current;b&&b.cancel()}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.edit.min.js' */
+!function(a,b,c){"use strict";var d=/Mac/.test(navigator.platform),e=a.ui.fancytree.escapeHtml,f=a.ui.fancytree.unescapeHtml;a.ui.fancytree._FancytreeNodeClass.prototype.editStart=function(){var b,d=this,e=this.tree,g=e.ext.edit,h=e.options.edit,i=a(".fancytree-title",d.span),j={node:d,tree:e,options:e.options,isNew:a(d[e.statusClassPropName]).hasClass("fancytree-edit-new"),orgTitle:d.title,input:null,dirty:!1};return h.beforeEdit.call(d,{type:"beforeEdit"},j)===!1?!1:(a.ui.fancytree.assert(!g.currentNode,"recursive edit"),g.currentNode=this,g.eventData=j,e.widget._unbind(),a(c).on("mousedown.fancytree-edit",function(b){a(b.target).hasClass("fancytree-edit-input")||d.editEnd(!0,b)}),b=a("<input />",{"class":"fancytree-edit-input",type:"text",value:f(j.orgTitle)}),g.eventData.input=b,null!=h.adjustWidthOfs&&b.width(i.width()+h.adjustWidthOfs),null!=h.inputCss&&b.css(h.inputCss),i.html(b),b.focus().change(function(){b.addClass("fancytree-edit-dirty")}).keydown(function(b){switch(b.which){case a.ui.keyCode.ESCAPE:d.editEnd(!1,b);break;case a.ui.keyCode.ENTER:return d.editEnd(!0,b),!1}b.stopPropagation()}).blur(function(a){return d.editEnd(!0,a)}),void h.edit.call(d,{type:"edit"},j))},a.ui.fancytree._FancytreeNodeClass.prototype.editEnd=function(b){var d,f=this,g=this.tree,h=g.ext.edit,i=h.eventData,j=g.options.edit,k=a(".fancytree-title",f.span),l=k.find("input.fancytree-edit-input");return j.trim&&l.val(a.trim(l.val())),d=l.val(),i.dirty=d!==f.title,i.save=b===!1?!1:i.isNew?""!==d:i.dirty&&""!==d,j.beforeClose.call(f,{type:"beforeClose"},i)===!1?!1:i.save&&j.save.call(f,{type:"save"},i)===!1?!1:(l.removeClass("fancytree-edit-dirty").unbind(),a(c).off(".fancytree-edit"),i.save?(f.setTitle(e(d)),f.setFocus()):i.isNew?(f.remove(),f=i.node=null,h.relatedNode.setFocus()):(f.renderTitle(),f.setFocus()),h.eventData=null,h.currentNode=null,h.relatedNode=null,g.widget._bind(),a(g.$container).focus(),i.input=null,j.close.call(f,{type:"close"},i),!0)},a.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode=function(b,c){var d,e=this.tree,f=this;return b=b||"child",null==c?c={title:""}:"string"==typeof c?c={title:c}:a.ui.fancytree.assert(a.isPlainObject(c)),"child"!==b||this.isExpanded()||this.hasChildren()===!1?(d=this.addNode(c,b),void d.makeVisible().done(function(){a(d[e.statusClassPropName]).addClass("fancytree-edit-new"),f.tree.ext.edit.relatedNode=f,d.editStart()})):void this.setExpanded().done(function(){f.editCreateNode(b,c)})},a.ui.fancytree._FancytreeClass.prototype.isEditing=function(){return this.ext.edit.currentNode},a.ui.fancytree._FancytreeNodeClass.prototype.isEditing=function(){return this.tree.ext.edit.currentNode===this},a.ui.fancytree.registerExtension({name:"edit",version:"0.2.0",options:{adjustWidthOfs:4,allowEmpty:!1,inputCss:{minWidth:"3em"},triggerCancel:["esc","tab","click"],triggerStart:["f2","shift+click","mac+enter"],trim:!0,beforeClose:a.noop,beforeEdit:a.noop,close:a.noop,edit:a.noop,save:a.noop},currentNode:null,treeInit:function(){this._superApply(arguments),this.$container.addClass("fancytree-ext-edit")},nodeClick:function(b){return a.inArray("shift+click",b.options.edit.triggerStart)>=0&&b.originalEvent.shiftKey?(b.node.editStart(),!1):this._superApply(arguments)},nodeDblclick:function(b){return a.inArray("dblclick",b.options.edit.triggerStart)>=0?(b.node.editStart(),!1):this._superApply(arguments)},nodeKeydown:function(b){switch(b.originalEvent.which){case 113:if(a.inArray("f2",b.options.edit.triggerStart)>=0)return b.node.editStart(),!1;break;case a.ui.keyCode.ENTER:if(a.inArray("mac+enter",b.options.edit.triggerStart)>=0&&d)return b.node.editStart(),!1}return this._superApply(arguments)}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.filter.min.js' */
+!function(a){"use strict";function b(a){return(a+"").replace(/([.?*+\^\$\[\]\\(){}|-])/g,"\\$1")}a.ui.fancytree._FancytreeClass.prototype._applyFilterImpl=function(a,c,d){var e,f,g,h,i=0,j=this.options.filter,k="hide"===j.mode;return d=d||{},e=!!d.leavesOnly&&!c,"string"==typeof a&&(f=j.fuzzy?a.split("").reduce(function(a,b){return a+"[^"+b+"]*"+b}):b(a),g=new RegExp(".*"+f+".*","i"),h=new RegExp(a,"gi"),a=function(a){var b=!!g.test(a.title);return b&&j.highlight&&(a.titleWithHighlight=a.title.replace(h,function(a){return"<mark>"+a+"</mark>"})),b}),this.enableFilter=!0,this.lastFilterArgs=arguments,this.$div.addClass("fancytree-ext-filter"),this.$div.addClass(k?"fancytree-ext-filter-hide":"fancytree-ext-filter-dimm"),this.visit(function(a){delete a.match,delete a.titleWithHighlight,a.subMatchCount=0}),this.visit(function(b){return e&&null!=b.children||!a(b)||(i++,b.match=!0,b.visitParents(function(a){a.subMatchCount+=1,d.autoExpand&&!a.expanded&&(a.setExpanded(!0,{noAnimation:!0,noEvents:!0,scrollIntoView:!1}),a._filterAutoExpanded=!0)}),!c)?void 0:(b.visit(function(a){a.match=!0}),"skip")}),this.render(),i},a.ui.fancytree._FancytreeClass.prototype.filterNodes=function(a,b){return"boolean"==typeof b&&(b={leavesOnly:b},this.warn("Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19.")),this._applyFilterImpl(a,!1,b)},a.ui.fancytree._FancytreeClass.prototype.applyFilter=function(){return this.warn("Fancytree.applyFilter() is deprecated since 2.1.0 / 2014-05-29. Use .filterNodes() instead."),this.filterNodes.apply(this,arguments)},a.ui.fancytree._FancytreeClass.prototype.filterBranches=function(a,b){return this._applyFilterImpl(a,!0,b)},a.ui.fancytree._FancytreeClass.prototype.clearFilter=function(){this.visit(function(b){b.match&&a(">span.fancytree-title",b.span).html(b.title),delete b.match,delete b.subMatchCount,delete b.titleWithHighlight,b.$subMatchBadge&&(b.$subMatchBadge.remove(),delete b.$subMatchBadge),b._filterAutoExpanded&&b.expanded&&b.setExpanded(!1,{noAnimation:!0,noEvents:!0,scrollIntoView:!1}),delete b._filterAutoExpanded}),this.enableFilter=!1,this.lastFilterArgs=null,this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"),this.render()},a.ui.fancytree._FancytreeClass.prototype.isFilterActive=function(){return!!this.enableFilter},a.ui.fancytree._FancytreeNodeClass.prototype.isMatched=function(){return!(this.tree.enableFilter&&!this.match)},a.ui.fancytree.registerExtension({name:"filter",version:"0.7.0",options:{autoApply:!0,counter:!0,fuzzy:!1,hideExpandedCounter:!0,highlight:!0,mode:"dimm"},nodeLoadChildren:function(a){return this._superApply(arguments).done(function(){a.tree.enableFilter&&a.tree.lastFilterArgs&&a.options.filter.autoApply&&a.tree._applyFilterImpl.apply(a.tree,a.tree.lastFilterArgs)})},nodeSetExpanded:function(a,b){return delete a.node._filterAutoExpanded,!b&&a.options.filter.hideExpandedCounter&&a.node.$subMatchBadge&&a.node.$subMatchBadge.show(),this._superApply(arguments)},nodeRenderStatus:function(b){var c,d=b.node,e=b.tree,f=b.options.filter,g=a(d[e.statusClassPropName]);return c=this._superApply(arguments),g.length&&e.enableFilter?(g.toggleClass("fancytree-match",!!d.match).toggleClass("fancytree-submatch",!!d.subMatchCount).toggleClass("fancytree-hide",!(d.match||d.subMatchCount)),!f.counter||!d.subMatchCount||d.isExpanded()&&f.hideExpandedCounter?d.$subMatchBadge&&d.$subMatchBadge.hide():(d.$subMatchBadge||(d.$subMatchBadge=a("<span class='fancytree-childcounter'/>"),a("span.fancytree-icon",d.span).append(d.$subMatchBadge)),d.$subMatchBadge.show().text(d.subMatchCount)),a("span.fancytree-title",d.span).html(d.titleWithHighlight?d.titleWithHighlight:d.title),c):c}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.glyph.min.js' */
+!function(a){"use strict";function b(a,b){return a.map[b]}a.ui.fancytree.registerExtension({name:"glyph",version:"0.3.0",options:{map:{checkbox:"icon-check-empty",checkboxSelected:"icon-check",checkboxUnknown:"icon-check icon-muted",error:"icon-exclamation-sign",expanderClosed:"icon-caret-right",expanderLazy:"icon-angle-right",expanderOpen:"icon-caret-down",noExpander:"",dragHelper:"icon-caret-right",dropMarker:"icon-caret-right",doc:"icon-file-alt",docOpen:"icon-file-alt",loading:"icon-refresh icon-spin",folder:"icon-folder-close-alt",folderOpen:"icon-folder-open-alt"}},treeInit:function(a){var b=a.tree;this._superApply(arguments),b.$container.addClass("fancytree-ext-glyph")},nodeRenderStatus:function(c){var d,e,f=c.node,g=a(f.span),h=c.options.glyph,i=h.map;this._superApply(arguments),f.isRoot()||(e=g.children("span.fancytree-expander").get(0),e&&(d=f.isLoading()?"loading":f.expanded?"expanderOpen":f.isUndefined()?"expanderLazy":f.hasChildren()?"expanderClosed":"noExpander",e.className="fancytree-expander "+i[d]),e=f.tr?a("td",f.tr).find("span.fancytree-checkbox").get(0):g.children("span.fancytree-checkbox").get(0),e&&(d=f.selected?"checkboxSelected":f.partsel?"checkboxUnknown":"checkbox",e.className="fancytree-checkbox "+i[d]),e=g.children("span.fancytree-icon").get(0),e&&(d=f.folder?f.expanded?b(h,"folderOpen"):b(h,"folder"):f.expanded?b(h,"docOpen"):b(h,"doc"),e.className="fancytree-icon "+d))},nodeSetStatus:function(c,d){var e,f=c.options.glyph,g=c.node;this._superApply(arguments),e=g.parent?a("span.fancytree-expander",g.span).get(0):a(".fancytree-statusnode-wait, .fancytree-statusnode-error",g[this.nodeContainerAttrName]).find("span.fancytree-expander").get(0),"loading"===d?e.className="fancytree-expander "+b(f,"loading"):"error"===d&&(e.className="fancytree-expander "+b(f,"error"))}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.gridnav.min.js' */
+!function(a){"use strict";function b(b,c){var d,e=c.get(0),f=0;return b.children().each(function(){return this===e?!1:(d=a(this).prop("colspan"),void(f+=d?d:1))}),f}function c(b,c){var d,e=null,f=0;return b.children().each(function(){return f>=c?(e=a(this),!1):(d=a(this).prop("colspan"),void(f+=d?d:1))}),e}function d(a,d){var f,g,h=a.closest("td"),i=null;switch(d){case e.LEFT:i=h.prev();break;case e.RIGHT:i=h.next();break;case e.UP:case e.DOWN:for(f=h.parent(),g=b(f,h);;){if(f=d===e.UP?f.prev():f.next(),!f.length)break;if(!f.is(":hidden")&&(i=c(f,g),i&&i.find(":input").length))break}}return i}var e=a.ui.keyCode,f={text:[e.UP,e.DOWN],checkbox:[e.UP,e.DOWN,e.LEFT,e.RIGHT],radiobutton:[e.UP,e.DOWN,e.LEFT,e.RIGHT],"select-one":[e.LEFT,e.RIGHT],"select-multiple":[e.LEFT,e.RIGHT]};a.ui.fancytree.registerExtension({name:"gridnav",version:"0.0.1",options:{autofocusInput:!1,handleCursorKeys:!0},treeInit:function(b){this._requireExtension("table",!0,!0),this._superApply(arguments),this.$container.addClass("fancytree-ext-gridnav"),this.$container.on("focusin",function(c){var d,e=a.ui.fancytree.getNode(c.target);e&&!e.isActive()&&(d=b.tree._makeHookContext(e,c),b.tree._callHook("nodeSetActive",d,!0))})},nodeSetActive:function(b,c){var d,e=b.options.gridnav,f=b.node,g=b.originalEvent||{},h=a(g.target).is(":input");c=c!==!1,this._superApply(arguments),c&&(b.options.titlesTabbable?(h||(a(f.span).find("span.fancytree-title").focus(),f.setFocus()),b.tree.$container.attr("tabindex","-1")):e.autofocusInput&&!h&&(d=a(f.tr||f.span),d.find(":input:enabled:first").focus()))},nodeKeydown:function(b){var c,e,g,h=b.options.gridnav,i=b.originalEvent,j=a(i.target);return c=j.is(":input:enabled")?j.prop("type"):null,c&&h.handleCursorKeys?(e=f[c],e&&a.inArray(i.which,e)>=0&&(g=d(j,i.which),g&&g.length)?(g.find(":input:enabled").focus(),!1):!0):this._superApply(arguments)}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.persist.min.js' */
+!function(a,b,c,d){"use strict";function e(b,c,d,f,g){var h,i,j,l,m=!1,n=[],o=[];for(d=d||[],g=g||a.Deferred(),h=0,j=d.length;j>h;h++)i=d[h],l=b.getNodeByKey(i),l?f&&l.isUndefined()?(m=!0,b.debug("_loadLazyNodes: "+l+" is lazy: loading..."),n.push("expand"===f?l.setExpanded():l.load())):(b.debug("_loadLazyNodes: "+l+" already loaded."),l.setExpanded()):(o.push(i),b.debug("_loadLazyNodes: "+l+" was not yet found."));return a.when.apply(a,n).always(function(){if(m&&o.length>0)e(b,c,o,f,g);else{if(o.length)for(b.warn("_loadLazyNodes: could not load those keys: ",o),h=0,j=o.length;j>h;h++)i=d[h],c._appendKey(k,d[h],!1);g.resolve()}}),g}var f,g,h,i=a.ui.fancytree.assert,j="active",k="expanded",l="focus",m="selected";"function"==typeof Cookies?(h=Cookies.set,f=Cookies.get,g=Cookies.remove):(h=f=a.cookie,g=a.removeCookie),a.ui.fancytree._FancytreeClass.prototype.clearCookies=function(a){var b=this.ext.persist,c=b.cookiePrefix;a=a||"active expanded focus selected",a.indexOf(j)>=0&&b._data(c+j,null),a.indexOf(k)>=0&&b._data(c+k,null),a.indexOf(l)>=0&&b._data(c+l,null),a.indexOf(m)>=0&&b._data(c+m,null)},a.ui.fancytree._FancytreeClass.prototype.getPersistData=function(){var a=this.ext.persist,b=a.cookiePrefix,c=a.cookieDelimiter,d={};return d[j]=a._data(b+j),d[k]=(a._data(b+k)||"").split(c),d[m]=(a._data(b+m)||"").split(c),d[l]=a._data(b+l),d},a.ui.fancytree.registerExtension({name:"persist",version:"0.3.0",options:{cookieDelimiter:"~",cookiePrefix:d,cookie:{raw:!1,expires:"",path:"",domain:"",secure:!1},expandLazy:!1,fireActivate:!0,overrideSource:!0,store:"auto",types:"active expanded focus selected"},_data:function(a,b){var c=this._local.localStorage;return b===d?c?c.getItem(a):f(a):void(null===b?c?c.removeItem(a):g(a):c?c.setItem(a,b):h(a,b,this.options.persist.cookie))},_appendKey:function(b,c,d){c=""+c;var e=this._local,f=this.options.persist,g=f.cookieDelimiter,h=e.cookiePrefix+b,i=e._data(h),j=i?i.split(g):[],k=a.inArray(c,j);k>=0&&j.splice(k,1),d&&j.push(c),e._data(h,j.join(g))},treeInit:function(c){var g=c.tree,h=c.options,n=this._local,o=this.options.persist;return i("auto"!==o.store&&"cookie"!==o.store||f,"Missing required plugin for 'persist' extension: js.cookie.js or jquery.cookie.js"),n.cookiePrefix=o.cookiePrefix||"fancytree-"+g._id+"-",n.storeActive=o.types.indexOf(j)>=0,n.storeExpanded=o.types.indexOf(k)>=0,n.storeSelected=o.types.indexOf(m)>=0,n.storeFocus=o.types.indexOf(l)>=0,n.localStorage="cookie"!==o.store&&b.localStorage?"local"===o.store?b.localStorage:b.sessionStorage:null,g.$div.bind("fancytreeinit",function(){var b,c,f,i,p,q=n._data(n.cookiePrefix+l),r=o.fireActivate===!1;b=n._data(n.cookiePrefix+k),i=b&&b.split(o.cookieDelimiter),c=n.storeExpanded?e(g,n,i,o.expandLazy?"expand":!1,null):(new a.Deferred).resolve(),c.done(function(){if(n.storeSelected){if(b=n._data(n.cookiePrefix+m))for(i=b.split(o.cookieDelimiter),f=0;f<i.length;f++)p=g.getNodeByKey(i[f]),p?(p.selected===d||o.overrideSource&&p.selected===!1)&&(p.selected=!0,p.renderStatus()):n._appendKey(m,i[f],!1);3===g.options.selectMode&&g.visit(function(a){return a.selected?(a.fixSelection3AfterClick(),"skip"):void 0})}n.storeActive&&(b=n._data(n.cookiePrefix+j),!b||!h.persist.overrideSource&&g.activeNode||(p=g.getNodeByKey(b),p&&(p.debug("persist: set active",b),p.setActive(!0,{noFocus:!0,noEvents:r})))),n.storeFocus&&q&&(p=g.getNodeByKey(q),p&&(g.options.titlesTabbable?a(p.span).find(".fancytree-title").focus():a(g.$container).focus())),g._triggerTreeEvent("restore",null,{})})}),this._superApply(arguments)},nodeSetActive:function(a,b){var c,d=this._local;return b=b!==!1,c=this._superApply(arguments),d.storeActive&&d._data(d.cookiePrefix+j,this.activeNode?this.activeNode.key:null),c},nodeSetExpanded:function(a,b){var c,d=a.node,e=this._local;return b=b!==!1,c=this._superApply(arguments),e.storeExpanded&&e._appendKey(k,d.key,b),c},nodeSetFocus:function(a,b){var c,d=this._local;return b=b!==!1,c=this._superApply(arguments),d.storeFocus&&d._data(d.cookiePrefix+l,this.focusNode?this.focusNode.key:null),c},nodeSetSelected:function(b,c){var d,e,f=b.tree,g=b.node,h=this._local;return c=c!==!1,d=this._superApply(arguments),h.storeSelected&&(3===f.options.selectMode?(e=a.map(f.getSelectedNodes(!0),function(a){return a.key}),e=e.join(b.options.persist.cookieDelimiter),h._data(h.cookiePrefix+m,e)):h._appendKey(m,g.key,g.selected)),d}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.table.min.js' */
+!function(a,b,c){"use strict";function d(b,c){c=c||"",b||a.error("Assertion failed "+c)}function e(a,b){a.parentNode.insertBefore(b,a.nextSibling)}function f(a,b){a.visit(function(a){var c=a.tr;return c&&(c.style.display=a.hide||!b?"none":""),a.expanded?void 0:"skip"})}function g(b){var c,e,f,g=b.parent,h=g?g.children:null;if(h&&h.length>1&&h[0]!==b)for(c=a.inArray(b,h),f=h[c-1],d(f.tr);f.children&&(e=f.children[f.children.length-1],e.tr);)f=e;else f=g;return f}a.ui.fancytree.registerExtension({name:"table",version:"0.2.1",options:{checkboxColumnIdx:null,customStatus:!1,indentation:16,nodeColumnIdx:0},treeInit:function(b){var d,e,f,g=b.tree,h=g.widget.element;for(h.addClass("fancytree-container fancytree-ext-table"),g.tbody=h.find("> tbody")[0],g.columnCount=a("thead >tr >th",h).length,a(g.tbody).empty(),g.rowFragment=c.createDocumentFragment(),e=a("<tr />"),f="",b.options.aria&&(e.attr("role","row"),f=" role='gridcell'"),d=0;d<g.columnCount;d++)e.append(b.options.table.nodeColumnIdx===d?"<td"+f+"><span class='fancytree-node' /></td>":"<td"+f+" />");g.rowFragment.appendChild(e.get(0)),g.statusClassPropName="tr",g.ariaPropName="tr",this.nodeContainerAttrName="tr",g.$container=h,this._superApply(arguments),a(g.rootNode.ul).remove(),g.rootNode.ul=null,this.$container.attr("tabindex",this.options.tabbable?"0":"-1"),this.options.aria&&g.$container.attr("role","treegrid").attr("aria-readonly",!0)},nodeRemoveChildMarkup:function(b){var c=b.node;c.visit(function(b){b.tr&&(a(b.tr).remove(),b.tr=null)})},nodeRemoveMarkup:function(b){var c=b.node;c.tr&&(a(c.tr).remove(),c.tr=null),this.nodeRemoveChildMarkup(b)},nodeRender:function(b,c,h,i,j){var k,l,m,n,o,p,q,r,s=b.tree,t=b.node,u=b.options,v=!t.parent;if(j||(b.hasCollapsedParents=t.parent&&!t.parent.expanded),!v)if(t.tr)c?this.nodeRenderTitle(b):this.nodeRenderStatus(b);else{if(b.hasCollapsedParents&&!h)return void t.debug("nodeRender ignored due to unrendered parent");o=s.rowFragment.firstChild.cloneNode(!0),p=g(t),d(p),i===!0&&j?o.style.display="none":h&&b.hasCollapsedParents&&(o.style.display="none"),p.tr?e(p.tr,o):(d(!p.parent,"prev. row must have a tr, or is system root"),s.tbody.appendChild(o)),t.tr=o,t.key&&u.generateIds&&(t.tr.id=u.idPrefix+t.key),t.tr.ftnode=t,u.aria&&a(t.tr).attr("aria-labelledby","ftal_"+t.key),t.span=a("span.fancytree-node",t.tr).get(0),this.nodeRenderTitle(b),u.createNode&&u.createNode.call(s,{type:"createNode"},b)}if(u.renderNode&&u.renderNode.call(s,{type:"renderNode"},b),k=t.children,k&&(v||h||t.expanded))for(m=0,n=k.length;n>m;m++)r=a.extend({},b,{node:k[m]}),r.hasCollapsedParents=r.hasCollapsedParents||!t.expanded,this.nodeRender(r,c,h,i,!0);k&&!j&&(q=t.tr||null,l=s.tbody.firstChild,t.visit(function(a){if(a.tr){if(a.parent.expanded||"none"===a.tr.style.display||(a.tr.style.display="none",f(a,!1)),a.tr.previousSibling!==q){t.debug("_fixOrder: mismatch at node: "+a);var b=q?q.nextSibling:l;s.tbody.insertBefore(a.tr,b)}q=a.tr}}))},nodeRenderTitle:function(b){var c,d=b.node,e=b.options;this._superApply(arguments),e.checkbox&&null!=e.table.checkboxColumnIdx&&(c=a("span.fancytree-checkbox",d.span).detach(),a(d.tr).find("td").eq(+e.table.checkboxColumnIdx).html(c)),d.isRoot()||this.nodeRenderStatus(b),!e.table.customStatus&&d.isStatusNode()||e.renderColumns&&e.renderColumns.call(b.tree,{type:"renderColumns"},b)},nodeRenderStatus:function(b){var c,d=b.node,e=b.options;this._superApply(arguments),a(d.tr).removeClass("fancytree-node"),c=(d.getLevel()-1)*e.table.indentation,a(d.span).css({paddingLeft:c+"px"})},nodeSetExpanded:function(b,c,d){function e(a){c=c!==!1,f(b.node,c),a?c&&b.options.autoScroll&&!d.noAnimation&&b.node.hasChildren()?b.node.getLastChild().scrollIntoView(!0,{topNode:b.node}).always(function(){d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.resolveWith(b.node)}):(d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.resolveWith(b.node)):(d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.rejectWith(b.node))}var g=new a.Deferred,h=a.extend({},d,{noEvents:!0,noAnimation:!0});return d=d||{},this._super(b,c,h).done(function(){e(!0)}).fail(function(){e(!1)}),g.promise()},nodeSetStatus:function(b,c){if("ok"===c){var d=b.node,e=d.children?d.children[0]:null;e&&e.isStatusNode()&&a(e.tr).remove()}return this._superApply(arguments)},treeClear:function(){return this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode)),this._superApply(arguments)},treeDestroy:function(){this.$container.find("tbody").empty(),this.$source&&this.$source.removeClass("ui-helper-hidden")}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.themeroller.min.js' */
+!function(a){"use strict";a.ui.fancytree.registerExtension({name:"themeroller",version:"0.0.1",options:{activeClass:"ui-state-active",foccusClass:"ui-state-focus",hoverClass:"ui-state-hover",selectedClass:"ui-state-highlight"},treeInit:function(b){this._superApply(arguments);var c=b.widget.element;"TABLE"===c[0].nodeName?(c.addClass("ui-widget ui-corner-all"),c.find(">thead tr").addClass("ui-widget-header"),c.find(">tbody").addClass("ui-widget-conent")):c.addClass("ui-widget ui-widget-content ui-corner-all"),c.delegate(".fancytree-node","mouseenter mouseleave",function(b){var c=a.ui.fancytree.getNode(b.target),d="mouseenter"===b.type;c.debug("hover: "+d),a(c.tr?c.tr:c.span).toggleClass("ui-state-hover ui-corner-all",d)})},treeDestroy:function(a){this._superApply(arguments),a.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all")},nodeRenderStatus:function(b){var c=b.node,d=a(c.tr?c.tr:c.span);this._superApply(arguments),d.toggleClass("ui-state-active",c.isActive()),d.toggleClass("ui-state-focus",c.hasFocus()),d.toggleClass("ui-state-highlight",c.isSelected())}})}(jQuery,window,document);
+
+/*! Extension 'jquery.fancytree.wide.min.js' */
+!function(a){"use strict";function b(b,c){b="fancytree-style-"+b;var d=a("#"+b);if(!c)return d.remove(),null;d.length||(d=a("<style />").attr("id",b).addClass("fancytree-style").prop("type","text/css").appendTo("head"));try{d.html(c)}catch(e){d[0].styleSheet.cssText=c}return d}function c(a,b,c,d,e){var f,g="#"+a+" span.fancytree-level-",h=[];for(f=0;b>f;f++)h.push(g+(f+1)+" span.fancytree-title { padding-left: "+(f*c+d)+e+"; }");return h.push("#"+a+" div.ui-effects-wrapper ul li span.fancytree-title { padding-left: 3px; position: static; width: auto; }"),h.join("\n")}var d=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;a.ui.fancytree.registerExtension({name:"wide",version:"0.0.3",options:{iconWidth:null,iconSpacing:null,levelOfs:null},treeCreate:function(e){this._superApply(arguments),this.$container.addClass("fancytree-ext-wide");var f,g,h,i,j,k=e.options.wide,l=a("<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />").appendTo(e.tree.$container),m=l.find(".fancytree-icon"),n=l.find("ul"),o=k.iconSpacing||m.css("margin-left"),p=k.iconWidth||m.css("width"),q=k.levelOfs||n.css("padding-left");l.remove(),h=o.match(d)[2],o=parseFloat(o,10),i=p.match(d)[2],p=parseFloat(p,10),j=q.match(d)[2],(h!==i||j!==i)&&a.error("iconWidth, iconSpacing, and levelOfs must have the same css measure unit"),this._local.measureUnit=i,this._local.levelOfs=parseFloat(q),this._local.lineOfs=(1+(e.options.checkbox?1:0)+(e.options.icons?1:0))*(p+o)+o,this._local.maxDepth=10,f=this.$container.uniqueId().attr("id"),g=c(f,this._local.maxDepth,this._local.levelOfs,this._local.lineOfs,this._local.measureUnit),b(f,g)},treeDestroy:function(){return b(this.$container.attr("id"),null),this._superApply(arguments)},nodeRenderStatus:function(d){var e,f,g,h=d.node,i=h.getLevel();return g=this._superApply(arguments),i>this._local.maxDepth&&(e=this.$container.attr("id"),this._local.maxDepth*=2,h.debug("Define global ext-wide css up to level "+this._local.maxDepth),f=c(e,this._local.maxDepth,this._local.levelOfs,this._local.lineOfs,this._local.measureUnit),b(e,f)),a(h.span).addClass("fancytree-level-"+i),g}})}(jQuery,window,document);
+}));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.js
new file mode 100644
index 00000000000..95de0d3735c
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.js
@@ -0,0 +1,4515 @@
+/*!
+ * jquery.fancytree.js
+ * Tree view control with support for lazy loading and much more.
+ * https://github.com/mar10/fancytree/
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+/** Core Fancytree module.
+ */
+
+
+// Start of local namespace
+;(function($, window, document, undefined) {
+"use strict";
+
+// prevent duplicate loading
+if ( $.ui && $.ui.fancytree ) {
+	$.ui.fancytree.warn("Fancytree: ignored duplicate include");
+	return;
+}
+
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+
+function _assert(cond, msg){
+	// TODO: see qunit.js extractStacktrace()
+	if(!cond){
+		msg = msg ? ": " + msg : "";
+		// consoleApply("assert", [!!cond, msg]);
+		$.error("Fancytree assertion failed" + msg);
+	}
+}
+
+_assert($.ui, "Fancytree requires jQuery UI (http://jqueryui.com)");
+
+function consoleApply(method, args){
+	var i, s,
+		fn = window.console ? window.console[method] : null;
+
+	if(fn){
+		try{
+			fn.apply(window.console, args);
+		} catch(e) {
+			// IE 8?
+			s = "";
+			for( i=0; i<args.length; i++){
+				s += args[i];
+			}
+			fn(s);
+		}
+	}
+}
+
+/*Return true if x is a FancytreeNode.*/
+function _isNode(x){
+	return !!(x.tree && x.statusNodeType !== undefined);
+}
+
+/** Return true if dotted version string is equal or higher than requested version.
+ *
+ * See http://jsfiddle.net/mar10/FjSAN/
+ */
+function isVersionAtLeast(dottedVersion, major, minor, patch){
+	var i, v, t,
+		verParts = $.map($.trim(dottedVersion).split("."), function(e){ return parseInt(e, 10); }),
+		testParts = $.map(Array.prototype.slice.call(arguments, 1), function(e){ return parseInt(e, 10); });
+
+	for( i = 0; i < testParts.length; i++ ){
+		v = verParts[i] || 0;
+		t = testParts[i] || 0;
+		if( v !== t ){
+			return ( v > t );
+		}
+	}
+	return true;
+}
+
+/** Return a wrapper that calls sub.methodName() and exposes
+ *  this        : tree
+ *  this._local : tree.ext.EXTNAME
+ *  this._super : base.methodName()
+ */
+function _makeVirtualFunction(methodName, tree, base, extension, extName){
+	// $.ui.fancytree.debug("_makeVirtualFunction", methodName, tree, base, extension, extName);
+	// if(rexTestSuper && !rexTestSuper.test(func)){
+	//     // extension.methodName() doesn't call _super(), so no wrapper required
+	//     return func;
+	// }
+	// Use an immediate function as closure
+	var proxy = (function(){
+		var prevFunc = tree[methodName],      // org. tree method or prev. proxy
+			baseFunc = extension[methodName], //
+			_local = tree.ext[extName],
+			_super = function(){
+				return prevFunc.apply(tree, arguments);
+			},
+			_superApply = function(args){
+				return prevFunc.apply(tree, args);
+			};
+
+		// Return the wrapper function
+		return function(){
+			var prevLocal = tree._local,
+				prevSuper = tree._super,
+				prevSuperApply = tree._superApply;
+
+			try{
+				tree._local = _local;
+				tree._super = _super;
+				tree._superApply = _superApply;
+				return  baseFunc.apply(tree, arguments);
+			}finally{
+				tree._local = prevLocal;
+				tree._super = prevSuper;
+				tree._superApply = prevSuperApply;
+			}
+		};
+	})(); // end of Immediate Function
+	return proxy;
+}
+
+/**
+ * Subclass `base` by creating proxy functions
+ */
+function _subclassObject(tree, base, extension, extName){
+	// $.ui.fancytree.debug("_subclassObject", tree, base, extension, extName);
+	for(var attrName in extension){
+		if(typeof extension[attrName] === "function"){
+			if(typeof tree[attrName] === "function"){
+				// override existing method
+				tree[attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);
+			}else if(attrName.charAt(0) === "_"){
+				// Create private methods in tree.ext.EXTENSION namespace
+				tree.ext[extName][attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);
+			}else{
+				$.error("Could not override tree." + attrName + ". Use prefix '_' to create tree." + extName + "._" + attrName);
+			}
+		}else{
+			// Create member variables in tree.ext.EXTENSION namespace
+			if(attrName !== "options"){
+				tree.ext[extName][attrName] = extension[attrName];
+			}
+		}
+	}
+}
+
+
+function _getResolvedPromise(context, argArray){
+	if(context === undefined){
+		return $.Deferred(function(){this.resolve();}).promise();
+	}else{
+		return $.Deferred(function(){this.resolveWith(context, argArray);}).promise();
+	}
+}
+
+
+function _getRejectedPromise(context, argArray){
+	if(context === undefined){
+		return $.Deferred(function(){this.reject();}).promise();
+	}else{
+		return $.Deferred(function(){this.rejectWith(context, argArray);}).promise();
+	}
+}
+
+
+function _makeResolveFunc(deferred, context){
+	return function(){
+		deferred.resolveWith(context);
+	};
+}
+
+
+function _getElementDataAsDict($el){
+	// Evaluate 'data-NAME' attributes with special treatment for 'data-json'.
+	var d = $.extend({}, $el.data()),
+		json = d.json;
+
+	delete d.fancytree; // added to container by widget factory (old jQuery UI)
+	delete d.uiFancytree; // added to container by widget factory
+
+	if( json ) {
+		delete d.json;
+		// <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)
+		d = $.extend(d, json);
+	}
+	return d;
+}
+
+
+// TODO: use currying
+function _makeNodeTitleMatcher(s){
+	s = s.toLowerCase();
+	return function(node){
+		return node.title.toLowerCase().indexOf(s) >= 0;
+	};
+}
+
+
+function _makeNodeTitleStartMatcher(s){
+	var reMatch = new RegExp("^" + s, "i");
+	return function(node){
+		return reMatch.test(node.title);
+	};
+}
+
+var i, attr,
+	FT = null, // initialized below
+	ENTITY_MAP = {"&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;", "/": "&#x2F;"},
+	IGNORE_KEYCODES = { 16: true, 17: true, 18: true },
+	SPECIAL_KEYCODES = {
+		8: "backspace", 9: "tab", 10: "return", 13: "return",
+		// 16: null, 17: null, 18: null, // ignore shift, ctrl, alt
+		19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup",
+		34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up",
+		39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=",
+		96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6",
+		103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".",
+		111: "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5",
+		117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11",
+		123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=",
+		188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
+		221: "]", 222: "'"},
+	MOUSE_BUTTONS = { 0: "", 1: "left", 2: "middle", 3: "right" },
+	//boolean attributes that can be set with equivalent class names in the LI tags
+	CLASS_ATTRS = "active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),
+	CLASS_ATTR_MAP = {},
+	//	Top-level Fancytree node attributes, that can be set by dict
+	NODE_ATTRS = "expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "),
+	NODE_ATTR_MAP = {},
+	// Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)
+	NODE_ATTR_LOWERCASE_MAP = {},
+	// Attribute names that should NOT be added to node.data
+	NONE_NODE_DATA_MAP = {"active": true, "children": true, "data": true, "focus": true};
+
+for(i=0; i<CLASS_ATTRS.length; i++){ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true; }
+for(i=0; i<NODE_ATTRS.length; i++) {
+	attr = NODE_ATTRS[i];
+	NODE_ATTR_MAP[attr] = true;
+	if( attr !== attr.toLowerCase() ) {
+		NODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;
+	}
+}
+
+
+/* *****************************************************************************
+ * FancytreeNode
+ */
+
+
+/**
+ * Creates a new FancytreeNode
+ *
+ * @class FancytreeNode
+ * @classdesc A FancytreeNode represents the hierarchical data model and operations.
+ *
+ * @param {FancytreeNode} parent
+ * @param {NodeData} obj
+ *
+ * @property {Fancytree} tree The tree instance
+ * @property {FancytreeNode} parent The parent node
+ * @property {string} key Node id (must be unique inside the tree)
+ * @property {string} title Display name (may contain HTML)
+ * @property {object} data Contains all extra data that was passed on node creation
+ * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>
+ *     For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array
+ *     to define a node that has no children.
+ * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.
+ * @property {string} extraClasses Addtional CSS classes, added to the node's `&lt;span>`
+ * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>
+ *     Note: Also non-folders may have children.
+ * @property {string} statusNodeType null or type of temporarily generated system node like 'loading', or 'error'.
+ * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.
+ * @property {boolean} selected Use isSelected(), setSelected() to access this property.
+ * @property {string} tooltip Alternative description used as hover banner
+ */
+function FancytreeNode(parent, obj){
+	var i, l, name, cl;
+
+	this.parent = parent;
+	this.tree = parent.tree;
+	this.ul = null;
+	this.li = null;  // <li id='key' ftnode=this> tag
+	this.statusNodeType = null; // if this is a temp. node to display the status of its parent
+	this._isLoading = false;    // if this node itself is loading
+	this._error = null;         // {message: '...'} if a load error occurred
+	this.data = {};
+
+	// TODO: merge this code with node.toDict()
+	// copy attributes from obj object
+	for(i=0, l=NODE_ATTRS.length; i<l; i++){
+		name = NODE_ATTRS[i];
+		this[name] = obj[name];
+	}
+	// node.data += obj.data
+	if(obj.data){
+		$.extend(this.data, obj.data);
+	}
+	// copy all other attributes to this.data.NAME
+	for(name in obj){
+		if(!NODE_ATTR_MAP[name] && !$.isFunction(obj[name]) && !NONE_NODE_DATA_MAP[name]){
+			// node.data.NAME = obj.NAME
+			this.data[name] = obj[name];
+		}
+	}
+
+	// Fix missing key
+	if( this.key == null ){ // test for null OR undefined
+		if( this.tree.options.defaultKey ) {
+			this.key = this.tree.options.defaultKey(this);
+			_assert(this.key, "defaultKey() must return a unique key");
+		} else {
+			this.key = "_" + (FT._nextNodeKey++);
+		}
+	} else {
+		this.key = "" + this.key; // Convert to string (#217)
+	}
+
+	// Fix tree.activeNode
+	// TODO: not elegant: we use obj.active as marker to set tree.activeNode
+	// when loading from a dictionary.
+	if(obj.active){
+		_assert(this.tree.activeNode === null, "only one active node allowed");
+		this.tree.activeNode = this;
+	}
+	if( obj.selected ){ // #186
+		this.tree.lastSelectedNode = this;
+	}
+	// TODO: handle obj.focus = true
+	// Create child nodes
+	cl = obj.children;
+	if( cl ){
+		if( cl.length ){
+			this._setChildren(cl);
+		} else {
+			// if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'
+			this.children = this.lazy ? [] : null;
+		}
+	} else {
+		this.children = null;
+	}
+	// Add to key/ref map (except for root node)
+//	if( parent ) {
+	this.tree._callHook("treeRegisterNode", this.tree, true, this);
+//	}
+}
+
+
+FancytreeNode.prototype = /** @lends FancytreeNode# */{
+	/* Return the direct child FancytreeNode with a given key, index. */
+	_findDirectChild: function(ptr){
+		var i, l,
+			cl = this.children;
+
+		if(cl){
+			if(typeof ptr === "string"){
+				for(i=0, l=cl.length; i<l; i++){
+					if(cl[i].key === ptr){
+						return cl[i];
+					}
+				}
+			}else if(typeof ptr === "number"){
+				return this.children[ptr];
+			}else if(ptr.parent === this){
+				return ptr;
+			}
+		}
+		return null;
+	},
+	// TODO: activate()
+	// TODO: activateSilently()
+	/* Internal helper called in recursive addChildren sequence.*/
+	_setChildren: function(children){
+		_assert(children && (!this.children || this.children.length === 0), "only init supported");
+		this.children = [];
+		for(var i=0, l=children.length; i<l; i++){
+			this.children.push(new FancytreeNode(this, children[i]));
+		}
+	},
+	/**
+	 * Append (or insert) a list of child nodes.
+	 *
+	 * @param {NodeData[]} children array of child node definitions (also single child accepted)
+	 * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).
+	 *     If omitted, the new children are appended.
+	 * @returns {FancytreeNode} first child added
+	 *
+	 * @see FancytreeNode#applyPatch
+	 */
+	addChildren: function(children, insertBefore){
+		var i, l, pos,
+			firstNode = null,
+			nodeList = [];
+
+		if($.isPlainObject(children) ){
+			children = [children];
+		}
+		if(!this.children){
+			this.children = [];
+		}
+		for(i=0, l=children.length; i<l; i++){
+			nodeList.push(new FancytreeNode(this, children[i]));
+		}
+		firstNode = nodeList[0];
+		if(insertBefore == null){
+			this.children = this.children.concat(nodeList);
+		}else{
+			insertBefore = this._findDirectChild(insertBefore);
+			pos = $.inArray(insertBefore, this.children);
+			_assert(pos >= 0, "insertBefore must be an existing child");
+			// insert nodeList after children[pos]
+			this.children.splice.apply(this.children, [pos, 0].concat(nodeList));
+		}
+		if( !this.parent || this.parent.ul || this.tr ){
+			// render if the parent was rendered (or this is a root node)
+			this.render();
+		}
+		if( this.tree.options.selectMode === 3 ){
+			this.fixSelection3FromEndNodes();
+		}
+		return firstNode;
+	},
+	/**
+	 * Append or prepend a node, or append a child node.
+	 *
+	 * This a convenience function that calls addChildren()
+	 *
+	 * @param {NodeData} node node definition
+	 * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
+	 * @returns {FancytreeNode} new node
+	 */
+	addNode: function(node, mode){
+		if(mode === undefined || mode === "over"){
+			mode = "child";
+		}
+		switch(mode){
+		case "after":
+			return this.getParent().addChildren(node, this.getNextSibling());
+		case "before":
+			return this.getParent().addChildren(node, this);
+		case "firstChild":
+			// Insert before the first child if any
+			var insertBefore = (this.children ? this.children[0] : null);
+			return this.addChildren(node, insertBefore);
+		case "child":
+		case "over":
+			return this.addChildren(node);
+		}
+		_assert(false, "Invalid mode: " + mode);
+	},
+	/**
+	 * Append new node after this.
+	 *
+	 * This a convenience function that calls addNode(node, 'after')
+	 *
+	 * @param {NodeData} node node definition
+	 * @returns {FancytreeNode} new node
+	 */
+	appendSibling: function(node){
+		return this.addNode(node, "after");
+	},
+	/**
+	 * Modify existing child nodes.
+	 *
+	 * @param {NodePatch} patch
+	 * @returns {$.Promise}
+	 * @see FancytreeNode#addChildren
+	 */
+	applyPatch: function(patch) {
+		// patch [key, null] means 'remove'
+		if(patch === null){
+			this.remove();
+			return _getResolvedPromise(this);
+		}
+		// TODO: make sure that root node is not collapsed or modified
+		// copy (most) attributes to node.ATTR or node.data.ATTR
+		var name, promise, v,
+			IGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global
+
+		for(name in patch){
+			v = patch[name];
+			if( !IGNORE_MAP[name] && !$.isFunction(v)){
+				if(NODE_ATTR_MAP[name]){
+					this[name] = v;
+				}else{
+					this.data[name] = v;
+				}
+			}
+		}
+		// Remove and/or create children
+		if(patch.hasOwnProperty("children")){
+			this.removeChildren();
+			if(patch.children){ // only if not null and not empty list
+				// TODO: addChildren instead?
+				this._setChildren(patch.children);
+			}
+			// TODO: how can we APPEND or INSERT child nodes?
+		}
+		if(this.isVisible()){
+			this.renderTitle();
+			this.renderStatus();
+		}
+		// Expand collapse (final step, since this may be async)
+		if(patch.hasOwnProperty("expanded")){
+			promise = this.setExpanded(patch.expanded);
+		}else{
+			promise = _getResolvedPromise(this);
+		}
+		return promise;
+	},
+	/** Collapse all sibling nodes.
+	 * @returns {$.Promise}
+	 */
+	collapseSiblings: function() {
+		return this.tree._callHook("nodeCollapseSiblings", this);
+	},
+	/** Copy this node as sibling or child of `node`.
+	 *
+	 * @param {FancytreeNode} node source node
+	 * @param {string} [mode=child] 'before' | 'after' | 'child'
+	 * @param {Function} [map] callback function(NodeData) that could modify the new node
+	 * @returns {FancytreeNode} new
+	 */
+	copyTo: function(node, mode, map) {
+		return node.addNode(this.toDict(true, map), mode);
+	},
+	/** Count direct and indirect children.
+	 *
+	 * @param {boolean} [deep=true] pass 'false' to only count direct children
+	 * @returns {int} number of child nodes
+	 */
+	countChildren: function(deep) {
+		var cl = this.children, i, l, n;
+		if( !cl ){
+			return 0;
+		}
+		n = cl.length;
+		if(deep !== false){
+			for(i=0, l=n; i<l; i++){
+				n += cl[i].countChildren();
+			}
+		}
+		return n;
+	},
+	// TODO: deactivate()
+	/** Write to browser console if debugLevel >= 2 (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	debug: function(msg){
+		if( this.tree.options.debugLevel >= 2 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("log", arguments);
+		}
+	},
+	/** Deprecated.
+	 * @deprecated since 2014-02-16. Use resetLazy() instead.
+	 */
+	discard: function(){
+		this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead.");
+		return this.resetLazy();
+	},
+
+	// TODO: expand(flag)
+
+	/**Find all nodes that match condition (excluding self).
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode[]} array of nodes (may be empty)
+	 */
+	findAll: function(match) {
+		match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);
+		var res = [];
+		this.visit(function(n){
+			if(match(n)){
+				res.push(n);
+			}
+		});
+		return res;
+	},
+	/**Find first node that matches condition (excluding self).
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode} matching node or null
+	 * @see FancytreeNode#findAll
+	 */
+	findFirst: function(match) {
+		match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);
+		var res = null;
+		this.visit(function(n){
+			if(match(n)){
+				res = n;
+				return false;
+			}
+		});
+		return res;
+	},
+	/* Apply selection state (internal use only) */
+	_changeSelectStatusAttrs: function (state) {
+		var changed = false;
+
+		switch(state){
+		case false:
+			changed = ( this.selected || this.partsel );
+			this.selected = false;
+			this.partsel = false;
+			break;
+		case true:
+			changed = ( !this.selected || !this.partsel );
+			this.selected = true;
+			this.partsel = true;
+			break;
+		case undefined:
+			changed = ( this.selected || !this.partsel );
+			this.selected = false;
+			this.partsel = true;
+			break;
+		default:
+			_assert(false, "invalid state: " + state);
+		}
+		// this.debug("fixSelection3AfterLoad() _changeSelectStatusAttrs()", state, changed);
+		if( changed ){
+			this.renderStatus();
+		}
+		return changed;
+	},
+	/**
+	 * Fix selection status, after this node was (de)selected in multi-hier mode.
+	 * This includes (de)selecting all children.
+	 */
+	fixSelection3AfterClick: function() {
+		var flag = this.isSelected();
+
+//		this.debug("fixSelection3AfterClick()");
+
+		this.visit(function(node){
+			node._changeSelectStatusAttrs(flag);
+		});
+		this.fixSelection3FromEndNodes();
+	},
+	/**
+	 * Fix selection status for multi-hier mode.
+	 * Only end-nodes are considered to update the descendants branch and parents.
+	 * Should be called after this node has loaded new children or after
+	 * children have been modified using the API.
+	 */
+	fixSelection3FromEndNodes: function() {
+//		this.debug("fixSelection3FromEndNodes()");
+		_assert(this.tree.options.selectMode === 3, "expected selectMode 3");
+
+		// Visit all end nodes and adjust their parent's `selected` and `partsel`
+		// attributes. Return selection state true, false, or undefined.
+		function _walk(node){
+			var i, l, child, s, state, allSelected,someSelected,
+				children = node.children;
+
+			if( children && children.length ){
+				// check all children recursively
+				allSelected = true;
+				someSelected = false;
+
+				for( i=0, l=children.length; i<l; i++ ){
+					child = children[i];
+					// the selection state of a node is not relevant; we need the end-nodes
+					s = _walk(child);
+					if( s !== false ) {
+						someSelected = true;
+					}
+					if( s !== true ) {
+						allSelected = false;
+					}
+				}
+				state = allSelected ? true : (someSelected ? undefined : false);
+			}else{
+				// This is an end-node: simply report the status
+//				state = ( node.unselectable ) ? undefined : !!node.selected;
+				state = !!node.selected;
+			}
+			node._changeSelectStatusAttrs(state);
+			return state;
+		}
+		_walk(this);
+
+		// Update parent's state
+		this.visitParents(function(node){
+			var i, l, child, state,
+				children = node.children,
+				allSelected = true,
+				someSelected = false;
+
+			for( i=0, l=children.length; i<l; i++ ){
+				child = children[i];
+				// When fixing the parents, we trust the sibling status (i.e.
+				// we don't recurse)
+				if( child.selected || child.partsel ) {
+					someSelected = true;
+				}
+				if( !child.unselectable && !child.selected ) {
+					allSelected = false;
+				}
+			}
+			state = allSelected ? true : (someSelected ? undefined : false);
+			node._changeSelectStatusAttrs(state);
+		});
+	},
+	// TODO: focus()
+	/**
+	 * Update node data. If dict contains 'children', then also replace
+	 * the hole sub tree.
+	 * @param {NodeData} dict
+	 *
+	 * @see FancytreeNode#addChildren
+	 * @see FancytreeNode#applyPatch
+	 */
+	fromDict: function(dict) {
+		// copy all other attributes to this.data.xxx
+		for(var name in dict){
+			if(NODE_ATTR_MAP[name]){
+				// node.NAME = dict.NAME
+				this[name] = dict[name];
+			}else if(name === "data"){
+				// node.data += dict.data
+				$.extend(this.data, dict.data);
+			}else if(!$.isFunction(dict[name]) && !NONE_NODE_DATA_MAP[name]){
+				// node.data.NAME = dict.NAME
+				this.data[name] = dict[name];
+			}
+		}
+		if(dict.children){
+			// recursively set children and render
+			this.removeChildren();
+			this.addChildren(dict.children);
+		}
+		this.renderTitle();
+/*
+		var children = dict.children;
+		if(children === undefined){
+			this.data = $.extend(this.data, dict);
+			this.render();
+			return;
+		}
+		dict = $.extend({}, dict);
+		dict.children = undefined;
+		this.data = $.extend(this.data, dict);
+		this.removeChildren();
+		this.addChild(children);
+*/
+	},
+	/** Return the list of child nodes (undefined for unexpanded lazy nodes).
+	 * @returns {FancytreeNode[] | undefined}
+	 */
+	getChildren: function() {
+		if(this.hasChildren() === undefined){ // TODO: only required for lazy nodes?
+			return undefined; // Lazy node: unloaded, currently loading, or load error
+		}
+		return this.children;
+	},
+	/** Return the first child node or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getFirstChild: function() {
+		return this.children ? this.children[0] : null;
+	},
+	/** Return the 0-based child index.
+	 * @returns {int}
+	 */
+	getIndex: function() {
+//		return this.parent.children.indexOf(this);
+		return $.inArray(this, this.parent.children); // indexOf doesn't work in IE7
+	},
+	/** Return the hierarchical child index (1-based, e.g. '3.2.4').
+	 * @returns {string}
+	 */
+	getIndexHier: function(separator) {
+		separator = separator || ".";
+		var res = [];
+		$.each(this.getParentList(false, true), function(i, o){
+			res.push(o.getIndex() + 1);
+		});
+		return res.join(separator);
+	},
+	/** Return the parent keys separated by options.keyPathSeparator, e.g. "id_1/id_17/id_32".
+	 * @param {boolean} [excludeSelf=false]
+	 * @returns {string}
+	 */
+	getKeyPath: function(excludeSelf) {
+		var path = [],
+			sep = this.tree.options.keyPathSeparator;
+		this.visitParents(function(n){
+			if(n.parent){
+				path.unshift(n.key);
+			}
+		}, !excludeSelf);
+		return sep + path.join(sep);
+	},
+	/** Return the last child of this node or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getLastChild: function() {
+		return this.children ? this.children[this.children.length - 1] : null;
+	},
+	/** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .
+	 * @returns {int}
+	 */
+	getLevel: function() {
+		var level = 0,
+			dtn = this.parent;
+		while( dtn ) {
+			level++;
+			dtn = dtn.parent;
+		}
+		return level;
+	},
+	/** Return the successor node (under the same parent) or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getNextSibling: function() {
+		// TODO: use indexOf, if available: (not in IE6)
+		if( this.parent ){
+			var i, l,
+				ac = this.parent.children;
+
+			for(i=0, l=ac.length-1; i<l; i++){ // up to length-2, so next(last) = null
+				if( ac[i] === this ){
+					return ac[i+1];
+				}
+			}
+		}
+		return null;
+	},
+	/** Return the parent node (null for the system root node).
+	 * @returns {FancytreeNode | null}
+	 */
+	getParent: function() {
+		// TODO: return null for top-level nodes?
+		return this.parent;
+	},
+	/** Return an array of all parent nodes (top-down).
+	 * @param {boolean} [includeRoot=false] Include the invisible system root node.
+	 * @param {boolean} [includeSelf=false] Include the node itself.
+	 * @returns {FancytreeNode[]}
+	 */
+	getParentList: function(includeRoot, includeSelf) {
+		var l = [],
+			dtn = includeSelf ? this : this.parent;
+		while( dtn ) {
+			if( includeRoot || dtn.parent ){
+				l.unshift(dtn);
+			}
+			dtn = dtn.parent;
+		}
+		return l;
+	},
+	/** Return the predecessor node (under the same parent) or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getPrevSibling: function() {
+		if( this.parent ){
+			var i, l,
+				ac = this.parent.children;
+
+			for(i=1, l=ac.length; i<l; i++){ // start with 1, so prev(first) = null
+				if( ac[i] === this ){
+					return ac[i-1];
+				}
+			}
+		}
+		return null;
+	},
+	/** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).
+	 * @returns {boolean | undefined}
+	 */
+	hasChildren: function() {
+		if(this.lazy){
+			if(this.children == null ){
+				// null or undefined: Not yet loaded
+				return undefined;
+			}else if(this.children.length === 0){
+				// Loaded, but response was empty
+				return false;
+			}else if(this.children.length === 1 && this.children[0].isStatusNode() ){
+				// Currently loading or load error
+				return undefined;
+			}
+			return true;
+		}
+		return !!( this.children && this.children.length );
+	},
+	/** Return true if node has keyboard focus.
+	 * @returns {boolean}
+	 */
+	hasFocus: function() {
+		return (this.tree.hasFocus() && this.tree.focusNode === this);
+	},
+	/** Write to browser console if debugLevel >= 1 (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	info: function(msg){
+		if( this.tree.options.debugLevel >= 1 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("info", arguments);
+		}
+	},
+	/** Return true if node is active (see also FancytreeNode#isSelected).
+	 * @returns {boolean}
+	 */
+	isActive: function() {
+		return (this.tree.activeNode === this);
+	},
+	/** Return true if node is a direct child of otherNode.
+	 * @param {FancytreeNode} otherNode
+	 * @returns {boolean}
+	 */
+	isChildOf: function(otherNode) {
+		return (this.parent && this.parent === otherNode);
+	},
+	/** Return true, if node is a direct or indirect sub node of otherNode.
+	 * @param {FancytreeNode} otherNode
+	 * @returns {boolean}
+	 */
+	isDescendantOf: function(otherNode) {
+		if(!otherNode || otherNode.tree !== this.tree){
+			return false;
+		}
+		var p = this.parent;
+		while( p ) {
+			if( p === otherNode ){
+				return true;
+			}
+			p = p.parent;
+		}
+		return false;
+	},
+	/** Return true if node is expanded.
+	 * @returns {boolean}
+	 */
+	isExpanded: function() {
+		return !!this.expanded;
+	},
+	/** Return true if node is the first node of its parent's children.
+	 * @returns {boolean}
+	 */
+	isFirstSibling: function() {
+		var p = this.parent;
+		return !p || p.children[0] === this;
+	},
+	/** Return true if node is a folder, i.e. has the node.folder attribute set.
+	 * @returns {boolean}
+	 */
+	isFolder: function() {
+		return !!this.folder;
+	},
+	/** Return true if node is the last node of its parent's children.
+	 * @returns {boolean}
+	 */
+	isLastSibling: function() {
+		var p = this.parent;
+		return !p || p.children[p.children.length-1] === this;
+	},
+	/** Return true if node is lazy (even if data was already loaded)
+	 * @returns {boolean}
+	 */
+	isLazy: function() {
+		return !!this.lazy;
+	},
+	/** Return true if node is lazy and loaded. For non-lazy nodes always return true.
+	 * @returns {boolean}
+	 */
+	isLoaded: function() {
+		return !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node
+	},
+	/** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.
+	 * @returns {boolean}
+	 */
+	isLoading: function() {
+		return !!this._isLoading;
+	},
+	/*
+	 * @deprecated since v2.4.0:  Use isRootNode() instead
+	 */
+	isRoot: function() {
+		return this.isRootNode();
+	},
+	/** Return true if this is the (invisible) system root node.
+	 * @returns {boolean}
+	 * @since 2.4
+	 */
+	isRootNode: function() {
+		return (this.tree.rootNode === this);
+	},
+	/** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).
+	 * @returns {boolean}
+	 */
+	isSelected: function() {
+		return !!this.selected;
+	},
+	/** Return true if this node is a temporarily generated system node like
+	 * 'loading', or 'error' (node.statusNodeType contains the type).
+	 * @returns {boolean}
+	 */
+	isStatusNode: function() {
+		return !!this.statusNodeType;
+	},
+	/** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.
+	 * @returns {boolean}
+	 * @since 2.4
+	 */
+	isTopLevel: function() {
+		return (this.tree.rootNode === this.parent);
+	},
+	/** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.
+	 * @returns {boolean}
+	 */
+	isUndefined: function() {
+		return this.hasChildren() === undefined; // also checks if the only child is a status node
+	},
+	/** Return true if all parent nodes are expanded. Note: this does not check
+	 * whether the node is scrolled into the visible part of the screen.
+	 * @returns {boolean}
+	 */
+	isVisible: function() {
+		var i, l,
+			parents = this.getParentList(false, false);
+
+		for(i=0, l=parents.length; i<l; i++){
+			if( ! parents[i].expanded ){ return false; }
+		}
+		return true;
+	},
+	/** Deprecated.
+	 * @deprecated since 2014-02-16: use load() instead.
+	 */
+	lazyLoad: function(discard) {
+		this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.");
+		return this.load(discard);
+	},
+	/**
+	 * Load all children of a lazy node if neccessary. The *expanded* state is maintained.
+	 * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before.
+	 * @returns {$.Promise}
+	 */
+	load: function(forceReload) {
+		var res, source,
+			that = this;
+
+		_assert( this.isLazy(), "load() requires a lazy node" );
+		// _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" );
+		if( !forceReload && !this.isUndefined() ) {
+			return _getResolvedPromise(this);
+		}
+		if( this.isLoaded() ){
+			this.resetLazy(); // also collapses
+		}
+		// This method is also called by setExpanded() and loadKeyPath(), so we
+		// have to avoid recursion.
+		source = this.tree._triggerNodeEvent("lazyLoad", this);
+		if( source === false ) { // #69
+			return _getResolvedPromise(this);
+		}
+		_assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+		res = this.tree._callHook("nodeLoadChildren", this, source);
+		if( this.expanded ) {
+			res.always(function(){
+				that.render();
+			});
+		}
+		return res;
+	},
+	/** Expand all parents and optionally scroll into visible area as neccessary.
+	 * Promise is resolved, when lazy loading and animations are done.
+	 * @param {object} [opts] passed to `setExpanded()`.
+	 *     Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
+	 * @returns {$.Promise}
+	 */
+	makeVisible: function(opts) {
+		var i,
+			that = this,
+			deferreds = [],
+			dfd = new $.Deferred(),
+			parents = this.getParentList(false, false),
+			len = parents.length,
+			effects = !(opts && opts.noAnimation === true),
+			scroll = !(opts && opts.scrollIntoView === false);
+
+		// Expand bottom-up, so only the top node is animated
+		for(i = len - 1; i >= 0; i--){
+			// that.debug("pushexpand" + parents[i]);
+			deferreds.push(parents[i].setExpanded(true, opts));
+		}
+		$.when.apply($, deferreds).done(function(){
+			// All expands have finished
+			// that.debug("expand DONE", scroll);
+			if( scroll ){
+				that.scrollIntoView(effects).done(function(){
+					// that.debug("scroll DONE");
+					dfd.resolve();
+				});
+			} else {
+				dfd.resolve();
+			}
+		});
+		return dfd.promise();
+	},
+	/** Move this node to targetNode.
+	 *  @param {FancytreeNode} targetNode
+	 *  @param {string} mode <pre>
+	 *      'child': append this node as last child of targetNode.
+	 *               This is the default. To be compatble with the D'n'd
+	 *               hitMode, we also accept 'over'.
+	 *      'before': add this node as sibling before targetNode.
+	 *      'after': add this node as sibling after targetNode.</pre>
+	 *  @param {function} [map] optional callback(FancytreeNode) to allow modifcations
+	 */
+	moveTo: function(targetNode, mode, map) {
+		if(mode === undefined || mode === "over"){
+			mode = "child";
+		}
+		var pos,
+			prevParent = this.parent,
+			targetParent = (mode === "child") ? targetNode : targetNode.parent;
+
+		if(this === targetNode){
+			return;
+		}else if( !this.parent  ){
+			throw "Cannot move system root";
+		}else if( targetParent.isDescendantOf(this) ){
+			throw "Cannot move a node to its own descendant";
+		}
+		// Unlink this node from current parent
+		if( this.parent.children.length === 1 ) {
+			if( this.parent === targetParent ){
+				return; // #258
+			}
+			this.parent.children = this.parent.lazy ? [] : null;
+			this.parent.expanded = false;
+		} else {
+			pos = $.inArray(this, this.parent.children);
+			_assert(pos >= 0, "invalid source parent");
+			this.parent.children.splice(pos, 1);
+		}
+		// Remove from source DOM parent
+//		if(this.parent.ul){
+//			this.parent.ul.removeChild(this.li);
+//		}
+
+		// Insert this node to target parent's child list
+		this.parent = targetParent;
+		if( targetParent.hasChildren() ) {
+			switch(mode) {
+			case "child":
+				// Append to existing target children
+				targetParent.children.push(this);
+				break;
+			case "before":
+				// Insert this node before target node
+				pos = $.inArray(targetNode, targetParent.children);
+				_assert(pos >= 0, "invalid target parent");
+				targetParent.children.splice(pos, 0, this);
+				break;
+			case "after":
+				// Insert this node after target node
+				pos = $.inArray(targetNode, targetParent.children);
+				_assert(pos >= 0, "invalid target parent");
+				targetParent.children.splice(pos+1, 0, this);
+				break;
+			default:
+				throw "Invalid mode " + mode;
+			}
+		} else {
+			targetParent.children = [ this ];
+		}
+		// Parent has no <ul> tag yet:
+//		if( !targetParent.ul ) {
+//			// This is the parent's first child: create UL tag
+//			// (Hidden, because it will be
+//			targetParent.ul = document.createElement("ul");
+//			targetParent.ul.style.display = "none";
+//			targetParent.li.appendChild(targetParent.ul);
+//		}
+//		// Issue 319: Add to target DOM parent (only if node was already rendered(expanded))
+//		if(this.li){
+//			targetParent.ul.appendChild(this.li);
+//		}^
+
+		// Let caller modify the nodes
+		if( map ){
+			targetNode.visit(map, true);
+		}
+		// Handle cross-tree moves
+		if( this.tree !== targetNode.tree ) {
+			// Fix node.tree for all source nodes
+//			_assert(false, "Cross-tree move is not yet implemented.");
+			this.warn("Cross-tree moveTo is experimantal!");
+			this.visit(function(n){
+				// TODO: fix selection state and activation, ...
+				n.tree = targetNode.tree;
+			}, true);
+		}
+
+		// A collaposed node won't re-render children, so we have to remove it manually
+		// if( !targetParent.expanded ){
+		//   prevParent.ul.removeChild(this.li);
+		// }
+
+		// Update HTML markup
+		if( !prevParent.isDescendantOf(targetParent)) {
+			prevParent.render();
+		}
+		if( !targetParent.isDescendantOf(prevParent) && targetParent !== prevParent) {
+			targetParent.render();
+		}
+		// TODO: fix selection state
+		// TODO: fix active state
+
+/*
+		var tree = this.tree;
+		var opts = tree.options;
+		var pers = tree.persistence;
+
+
+		// Always expand, if it's below minExpandLevel
+//		tree.logDebug ("%s._addChildNode(%o), l=%o", this, ftnode, ftnode.getLevel());
+		if ( opts.minExpandLevel >= ftnode.getLevel() ) {
+//			tree.logDebug ("Force expand for %o", ftnode);
+			this.bExpanded = true;
+		}
+
+		// In multi-hier mode, update the parents selection state
+		// DT issue #82: only if not initializing, because the children may not exist yet
+//		if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )
+//			ftnode._fixSelectionState();
+
+		// In multi-hier mode, update the parents selection state
+		if( ftnode.bSelected && opts.selectMode==3 ) {
+			var p = this;
+			while( p ) {
+				if( !p.hasSubSel )
+					p._setSubSel(true);
+				p = p.parent;
+			}
+		}
+		// render this node and the new child
+		if ( tree.bEnableUpdate )
+			this.render();
+
+		return ftnode;
+
+*/
+	},
+	/** Set focus relative to this node and optionally activate.
+	 *
+	 * @param {number} where The keyCode that would normally trigger this move,
+	 *		e.g. `$.ui.keyCode.LEFT` would collapse the node if it
+	 *      is expanded or move to the parent oterwise.
+	 * @param {boolean} [activate=true]
+	 * @returns {$.Promise}
+	 */
+	// navigate: function(where, activate) {
+	// 	console.time("navigate")
+	// 	this._navigate(where, activate)
+	// 	console.timeEnd("navigate")
+	// },
+	navigate: function(where, activate) {
+		var i, parents,
+			handled = true,
+			KC = $.ui.keyCode,
+			sib = null;
+
+		// Navigate to node
+		function _goto(n){
+			if( n ){
+				try { n.makeVisible(); } catch(e) {} // #272
+				// Node may still be hidden by a filter
+				if( ! $(n.span).is(":visible") ) {
+					n.debug("Navigate: skipping hidden node");
+					n.navigate(where, activate);
+					return;
+				}
+				return activate === false ? n.setFocus() : n.setActive();
+			}
+		}
+
+		switch( where ) {
+			case KC.BACKSPACE:
+				if( this.parent && this.parent.parent ) {
+					_goto(this.parent);
+				}
+				break;
+			case KC.LEFT:
+				if( this.expanded ) {
+					this.setExpanded(false);
+					_goto(this);
+				} else if( this.parent && this.parent.parent ) {
+					_goto(this.parent);
+				}
+				break;
+			case KC.RIGHT:
+				if( !this.expanded && (this.children || this.lazy) ) {
+					this.setExpanded();
+					_goto(this);
+				} else if( this.children && this.children.length ) {
+					_goto(this.children[0]);
+				}
+				break;
+			case KC.UP:
+				sib = this.getPrevSibling();
+				// #359: skip hidden sibling nodes, preventing a _goto() recursion
+				while( sib && !$(sib.span).is(":visible") ) {
+					sib = sib.getPrevSibling();
+				}
+				while( sib && sib.expanded && sib.children && sib.children.length ) {
+					sib = sib.children[sib.children.length - 1];
+				}
+				if( !sib && this.parent && this.parent.parent ){
+					sib = this.parent;
+				}
+				_goto(sib);
+				break;
+			case KC.DOWN:
+				if( this.expanded && this.children && this.children.length ) {
+					sib = this.children[0];
+				} else {
+					parents = this.getParentList(false, true);
+					for(i=parents.length-1; i>=0; i--) {
+						sib = parents[i].getNextSibling();
+						// #359: skip hidden sibling nodes, preventing a _goto() recursion
+						while( sib && !$(sib.span).is(":visible") ) {
+							sib = sib.getNextSibling();
+						}
+						if( sib ){ break; }
+					}
+				}
+				_goto(sib);
+				break;
+			default:
+				handled = false;
+		}
+	},
+	/**
+	 * Remove this node (not allowed for system root).
+	 */
+	remove: function() {
+		return this.parent.removeChild(this);
+	},
+	/**
+	 * Remove childNode from list of direct children.
+	 * @param {FancytreeNode} childNode
+	 */
+	removeChild: function(childNode) {
+		return this.tree._callHook("nodeRemoveChild", this, childNode);
+	},
+	/**
+	 * Remove all child nodes and descendents. This converts the node into a leaf.<br>
+	 * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()
+	 * in order to trigger lazyLoad on next expand.
+	 */
+	removeChildren: function() {
+		return this.tree._callHook("nodeRemoveChildren", this);
+	},
+	/**
+	 * This method renders and updates all HTML markup that is required
+	 * to display this node in its current state.<br>
+	 * Note:
+	 * <ul>
+	 * <li>It should only be neccessary to call this method after the node object
+	 *     was modified by direct access to its properties, because the common
+	 *     API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)
+	 *     already handle this.
+	 * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}
+	 *     are implied. If changes are more local, calling only renderTitle() or
+	 *     renderStatus() may be sufficient and faster.
+	 * <li>If a node was created/removed, node.render() must be called <i>on the parent</i>.
+	 * </ul>
+	 *
+	 * @param {boolean} [force=false] re-render, even if html markup was already created
+	 * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+	 */
+	render: function(force, deep) {
+		return this.tree._callHook("nodeRender", this, force, deep);
+	},
+	/** Create HTML markup for the node's outer &lt;span> (expander, checkbox, icon, and title).
+	 * Implies {@link FancytreeNode#renderStatus}.
+	 * @see Fancytree_Hooks#nodeRenderTitle
+	 */
+	renderTitle: function() {
+		return this.tree._callHook("nodeRenderTitle", this);
+	},
+	/** Update element's CSS classes according to node state.
+	 * @see Fancytree_Hooks#nodeRenderStatus
+	 */
+	renderStatus: function() {
+		return this.tree._callHook("nodeRenderStatus", this);
+	},
+	/**
+	 * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
+	 * event is triggered on next expand.
+	 */
+	resetLazy: function() {
+		this.removeChildren();
+		this.expanded = false;
+		this.lazy = true;
+		this.children = undefined;
+		this.renderStatus();
+	},
+	/** Schedule activity for delayed execution (cancel any pending request).
+	 *  scheduleAction('cancel') will only cancel a pending request (if any).
+	 * @param {string} mode
+	 * @param {number} ms
+	 */
+	scheduleAction: function(mode, ms) {
+		if( this.tree.timer ) {
+			clearTimeout(this.tree.timer);
+//            this.tree.debug("clearTimeout(%o)", this.tree.timer);
+		}
+		this.tree.timer = null;
+		var self = this; // required for closures
+		switch (mode) {
+		case "cancel":
+			// Simply made sure that timer was cleared
+			break;
+		case "expand":
+			this.tree.timer = setTimeout(function(){
+				self.tree.debug("setTimeout: trigger expand");
+				self.setExpanded(true);
+			}, ms);
+			break;
+		case "activate":
+			this.tree.timer = setTimeout(function(){
+				self.tree.debug("setTimeout: trigger activate");
+				self.setActive(true);
+			}, ms);
+			break;
+		default:
+			throw "Invalid mode " + mode;
+		}
+//        this.tree.debug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer);
+	},
+	/**
+	 *
+	 * @param {boolean | PlainObject} [effects=false] animation options.
+	 * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in
+	 *     any case, even if `this` is outside the scroll pane.
+	 * @returns {$.Promise}
+	 */
+	scrollIntoView: function(effects, options) {
+		if( options !== undefined && _isNode(options) ) {
+			this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.");
+			options = {topNode: options};
+		}
+		// this.$scrollParent = (this.options.scrollParent === "auto") ? $ul.scrollParent() : $(this.options.scrollParent);
+		// this.$scrollParent = this.$scrollParent.length ? this.$scrollParent || this.$container;
+
+		var topNodeY, nodeY, horzScrollbarHeight, containerOffsetTop,
+			opts = $.extend({
+				effects: (effects === true) ? {duration: 200, queue: false} : effects,
+				scrollOfs: this.tree.options.scrollOfs,
+				scrollParent: this.tree.options.scrollParent || this.tree.$container,
+				topNode: null
+			}, options),
+			dfd = new $.Deferred(),
+			that = this,
+			nodeHeight = $(this.span).height(),
+			$container = $(opts.scrollParent),
+			topOfs = opts.scrollOfs.top || 0,
+			bottomOfs = opts.scrollOfs.bottom || 0,
+			containerHeight = $container.height(),// - topOfs - bottomOfs,
+			scrollTop = $container.scrollTop(),
+			$animateTarget = $container,
+			isParentWindow = $container[0] === window,
+			topNode = opts.topNode || null,
+			newScrollTop = null;
+
+		// this.debug("scrollIntoView(), scrollTop=", scrollTop, opts.scrollOfs);
+//		_assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets
+		if( !$(this.span).is(":visible") ) {
+			// We cannot calc offsets for hidden elements
+			this.warn("scrollIntoView(): node is invisible.");
+			return _getResolvedPromise();
+		}
+		if( isParentWindow ) {
+			nodeY = $(this.span).offset().top;
+			topNodeY = (topNode && topNode.span) ? $(topNode.span).offset().top : 0;
+			$animateTarget = $("html,body");
+
+		} else {
+			_assert($container[0] !== document && $container[0] !== document.body, "scrollParent should be an simple element or `window`, not document or body.");
+
+			containerOffsetTop = $container.offset().top,
+			nodeY = $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent
+			topNodeY = topNode ? $(topNode.span).offset().top - containerOffsetTop  + scrollTop : 0;
+			horzScrollbarHeight = Math.max(0, ($container.innerHeight() - $container[0].clientHeight));
+			containerHeight -= horzScrollbarHeight;
+		}
+
+		// this.debug("    scrollIntoView(), nodeY=", nodeY, "containerHeight=", containerHeight);
+		if( nodeY < (scrollTop + topOfs) ){
+			// Node is above visible container area
+			newScrollTop = nodeY - topOfs;
+			// this.debug("    scrollIntoView(), UPPER newScrollTop=", newScrollTop);
+
+		}else if((nodeY + nodeHeight) > (scrollTop + containerHeight - bottomOfs)){
+			newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;
+			// this.debug("    scrollIntoView(), LOWER newScrollTop=", newScrollTop);
+			// If a topNode was passed, make sure that it is never scrolled
+			// outside the upper border
+			if(topNode){
+				_assert(topNode.isRootNode() || $(topNode.span).is(":visible"), "topNode must be visible");
+				if( topNodeY < newScrollTop ){
+					newScrollTop = topNodeY - topOfs;
+					// this.debug("    scrollIntoView(), TOP newScrollTop=", newScrollTop);
+				}
+			}
+		}
+
+		if(newScrollTop !== null){
+			// this.debug("    scrollIntoView(), SET newScrollTop=", newScrollTop);
+			if(opts.effects){
+				opts.effects.complete = function(){
+					dfd.resolveWith(that);
+				};
+				$animateTarget.stop(true).animate({
+					scrollTop: newScrollTop
+				}, opts.effects);
+			}else{
+				$animateTarget[0].scrollTop = newScrollTop;
+				dfd.resolveWith(this);
+			}
+		}else{
+			dfd.resolveWith(this);
+		}
+		return dfd.promise();
+	},
+
+	/**Activate this node.
+	 * @param {boolean} [flag=true] pass false to deactivate
+	 * @param {object} [opts] additional options. Defaults to {noEvents: false}
+	 * @returns {$.Promise}
+	 */
+	setActive: function(flag, opts){
+		return this.tree._callHook("nodeSetActive", this, flag, opts);
+	},
+	/**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.
+	 * @param {boolean} [flag=true] pass false to collapse
+	 * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+	 * @returns {$.Promise}
+	 */
+	setExpanded: function(flag, opts){
+		return this.tree._callHook("nodeSetExpanded", this, flag, opts);
+	},
+	/**Set keyboard focus to this node.
+	 * @param {boolean} [flag=true] pass false to blur
+	 * @see Fancytree#setFocus
+	 */
+	setFocus: function(flag){
+		return this.tree._callHook("nodeSetFocus", this, flag);
+	},
+	/**Select this node, i.e. check the checkbox.
+	 * @param {boolean} [flag=true] pass false to deselect
+	 */
+	setSelected: function(flag){
+		return this.tree._callHook("nodeSetSelected", this, flag);
+	},
+	/**Mark a lazy node as 'error', 'loading', or 'ok'.
+	 * @param {string} status 'error', 'ok'
+	 * @param {string} [message]
+	 * @param {string} [details]
+	 */
+	setStatus: function(status, message, details){
+		return this.tree._callHook("nodeSetStatus", this, status, message, details);
+	},
+	/**Rename this node.
+	 * @param {string} title
+	 */
+	setTitle: function(title){
+		this.title = title;
+		this.renderTitle();
+	},
+	/**Sort child list by title.
+	 * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).
+	 * @param {boolean} [deep=false] pass true to sort all descendant nodes
+	 */
+	sortChildren: function(cmp, deep) {
+		var i,l,
+			cl = this.children;
+
+		if( !cl ){
+			return;
+		}
+		cmp = cmp || function(a, b) {
+			var x = a.title.toLowerCase(),
+				y = b.title.toLowerCase();
+			return x === y ? 0 : x > y ? 1 : -1;
+			};
+		cl.sort(cmp);
+		if( deep ){
+			for(i=0, l=cl.length; i<l; i++){
+				if( cl[i].children ){
+					cl[i].sortChildren(cmp, "$norender$");
+				}
+			}
+		}
+		if( deep !== "$norender$" ){
+			this.render();
+		}
+	},
+	/** Convert node (or whole branch) into a plain object.
+	 *
+	 * The result is compatible with node.addChildren().
+	 *
+	 * @param {boolean} [recursive=false] include child nodes
+	 * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications
+	 * @returns {NodeData}
+	 */
+	toDict: function(recursive, callback) {
+		var i, l, node,
+			dict = {},
+			self = this;
+
+		$.each(NODE_ATTRS, function(i, a){
+			if(self[a] || self[a] === false){
+				dict[a] = self[a];
+			}
+		});
+		if(!$.isEmptyObject(this.data)){
+			dict.data = $.extend({}, this.data);
+			if($.isEmptyObject(dict.data)){
+				delete dict.data;
+			}
+		}
+		if( callback ){
+			callback(dict, self);
+		}
+		if( recursive ) {
+			if(this.hasChildren()){
+				dict.children = [];
+				for(i=0, l=this.children.length; i<l; i++ ){
+					node = this.children[i];
+					if( !node.isStatusNode() ){
+						dict.children.push(node.toDict(true, callback));
+					}
+				}
+			}else{
+//                dict.children = null;
+			}
+		}
+		return dict;
+	},
+	/** Flip expanded status.  */
+	toggleExpanded: function(){
+		return this.tree._callHook("nodeToggleExpanded", this);
+	},
+	/** Flip selection status.  */
+	toggleSelected: function(){
+		return this.tree._callHook("nodeToggleSelected", this);
+	},
+	toString: function() {
+		return "<FancytreeNode(#" + this.key + ", '" + this.title + "')>";
+	},
+	/** Call fn(node) for all child nodes.<br>
+	 * Stop iteration, if fn() returns false. Skip current branch, if fn() returns "skip".<br>
+	 * Return false if iteration was stopped.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and
+	 *     its children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {boolean}
+	 */
+	visit: function(fn, includeSelf) {
+		var i, l,
+			res = true,
+			children = this.children;
+
+		if( includeSelf === true ) {
+			res = fn(this);
+			if( res === false || res === "skip" ){
+				return res;
+			}
+		}
+		if(children){
+			for(i=0, l=children.length; i<l; i++){
+				res = children[i].visit(fn, true);
+				if( res === false ){
+					break;
+				}
+			}
+		}
+		return res;
+	},
+	/** Call fn(node) for all child nodes and recursively load lazy children.<br>
+	 * <b>Note:</b> If you need this method, you probably should consider to review
+	 * your architecture! Recursivley loading nodes is a perfect way for lazy
+	 * programmers to flood the server with requests ;-)
+	 *
+	 * @param {function} [fn] optional callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and
+	 *     its children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {$.Promise}
+	 * @since 2.4
+	 */
+	visitAndLoad: function(fn, includeSelf, _recursion) {
+		var dfd, res, loaders,
+			node = this;
+
+		// node.debug("visitAndLoad");
+		if( fn && includeSelf === true ) {
+			res = fn(node);
+			if( res === false || res === "skip" ) {
+				return _recursion ? res : _getResolvedPromise();
+			}
+		}
+		if( !node.children && !node.lazy ) {
+			return _getResolvedPromise();
+		}
+		dfd = new $.Deferred();
+		loaders = [];
+		// node.debug("load()...");
+		node.load().done(function(){
+			// node.debug("load()... done.");
+			for(var i=0, l=node.children.length; i<l; i++){
+				res = node.children[i].visitAndLoad(fn, true, true);
+				if( res === false ) {
+					dfd.reject();
+					break;
+				} else if ( res !== "skip" ) {
+					loaders.push(res); // Add promise to the list
+				}
+			}
+			$.when.apply(this, loaders).then(function(){
+				dfd.resolve();
+			});
+		});
+		return dfd.promise();
+	},
+	/** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
+	 * Stop iteration, if fn() returns false.<br>
+	 * Return false if iteration was stopped.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {boolean}
+	 */
+	visitParents: function(fn, includeSelf) {
+		// Visit parent nodes (bottom up)
+		if(includeSelf && fn(this) === false){
+			return false;
+		}
+		var p = this.parent;
+		while( p ) {
+			if(fn(p) === false){
+				return false;
+			}
+			p = p.parent;
+		}
+		return true;
+	},
+	/** Write warning to browser console (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	warn: function(msg){
+		Array.prototype.unshift.call(arguments, this.toString());
+		consoleApply("warn", arguments);
+	}
+};
+
+
+/* *****************************************************************************
+ * Fancytree
+ */
+/**
+ * Construct a new tree object.
+ *
+ * @class Fancytree
+ * @classdesc The controller behind a fancytree.
+ * This class also contains 'hook methods': see {@link Fancytree_Hooks}.
+ *
+ * @param {Widget} widget
+ *
+ * @property {string} _id Automatically generated unique tree instance ID, e.g. "1".
+ * @property {string} _ns Automatically generated unique tree namespace, e.g. ".fancytree-1".
+ * @property {FancytreeNode} activeNode Currently active node or null.
+ * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.
+ *     Typically "li", but "tr" for table extension.
+ * @property {jQueryObject} $container Outer &lt;ul> element (or &lt;table> element for ext-table).
+ * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)
+ * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.
+ * @property {object} ext Hash of all active plugin instances.
+ * @property {FancytreeNode} focusNode Currently focused node or null.
+ * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)
+ * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.
+ *     Typically "li", but "tr" for table extension.
+ * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.
+ * @property {FancytreeNode} rootNode Invisible system root node.
+ * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.
+ *     Typically "span", but "tr" for table extension.
+ * @property {object} widget Base widget instance.
+ */
+function Fancytree(widget) {
+	this.widget = widget;
+	this.$div = widget.element;
+	this.options = widget.options;
+	if( this.options ) {
+		if(  $.isFunction(this.options.lazyload ) && !$.isFunction(this.options.lazyLoad) ) {
+			this.options.lazyLoad = function() {
+				FT.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead.");
+				return widget.options.lazyload.apply(this, arguments);
+			};
+		}
+		if( $.isFunction(this.options.loaderror) ) {
+			$.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead.");
+		}
+		if( this.options.fx !== undefined ) {
+			FT.warn("The 'fx' options was replaced by 'toggleEffect' since 2014-11-30.");
+		}
+	}
+	this.ext = {}; // Active extension instances
+	// allow to init tree.data.foo from <div data-foo=''>
+	this.data = _getElementDataAsDict(this.$div);
+	// TODO: use widget.uuid instead?
+	this._id = $.ui.fancytree._nextId++;
+	// TODO: use widget.eventNamespace instead?
+	this._ns = ".fancytree-" + this._id; // append for namespaced events
+	this.activeNode = null;
+	this.focusNode = null;
+	this._hasFocus = null;
+	this.lastSelectedNode = null;
+	this.systemFocusElement = null;
+	this.lastQuicksearchTerm = "";
+	this.lastQuicksearchTime = 0;
+
+	this.statusClassPropName = "span";
+	this.ariaPropName = "li";
+	this.nodeContainerAttrName = "li";
+
+	// Remove previous markup if any
+	this.$div.find(">ul.fancytree-container").remove();
+
+	// Create a node without parent.
+	var fakeParent = { tree: this },
+		$ul;
+	this.rootNode = new FancytreeNode(fakeParent, {
+		title: "root",
+		key: "root_" + this._id,
+		children: null,
+		expanded: true
+	});
+	this.rootNode.parent = null;
+
+	// Create root markup
+	$ul = $("<ul>", {
+		"class": "ui-fancytree fancytree-container fancytree-plain"
+	}).appendTo(this.$div);
+	this.$container = $ul;
+	this.rootNode.ul = $ul[0];
+
+	if(this.options.debugLevel == null){
+		this.options.debugLevel = FT.debugLevel;
+	}
+	// Add container to the TAB chain
+	// See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+	this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1");
+	if(this.options.aria){
+		this.$container
+			.attr("role", "tree")
+			.attr("aria-multiselectable", true);
+	}
+}
+
+
+Fancytree.prototype = /** @lends Fancytree# */{
+	/* Return a context object that can be re-used for _callHook().
+	 * @param {Fancytree | FancytreeNode | EventData} obj
+	 * @param {Event} originalEvent
+	 * @param {Object} extra
+	 * @returns {EventData}
+	 */
+	_makeHookContext: function(obj, originalEvent, extra) {
+		var ctx, tree;
+		if(obj.node !== undefined){
+			// obj is already a context object
+			if(originalEvent && obj.originalEvent !== originalEvent){
+				$.error("invalid args");
+			}
+			ctx = obj;
+		}else if(obj.tree){
+			// obj is a FancytreeNode
+			tree = obj.tree;
+			ctx = { node: obj, tree: tree, widget: tree.widget, options: tree.widget.options, originalEvent: originalEvent };
+		}else if(obj.widget){
+			// obj is a Fancytree
+			ctx = { node: null, tree: obj, widget: obj.widget, options: obj.widget.options, originalEvent: originalEvent };
+		}else{
+			$.error("invalid args");
+		}
+		if(extra){
+			$.extend(ctx, extra);
+		}
+		return ctx;
+	},
+	/* Trigger a hook function: funcName(ctx, [...]).
+	 *
+	 * @param {string} funcName
+	 * @param {Fancytree|FancytreeNode|EventData} contextObject
+	 * @param {any}  [_extraArgs] optional additional arguments
+	 * @returns {any}
+	 */
+	_callHook: function(funcName, contextObject, _extraArgs) {
+		var ctx = this._makeHookContext(contextObject),
+			fn = this[funcName],
+			args = Array.prototype.slice.call(arguments, 2);
+		if(!$.isFunction(fn)){
+			$.error("_callHook('" + funcName + "') is not a function");
+		}
+		args.unshift(ctx);
+//		this.debug("_hook", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);
+		return fn.apply(this, args);
+	},
+	/* Check if current extensions dependencies are met and throw an error if not.
+	 *
+	 * This method may be called inside the `treeInit` hook for custom extensions.
+	 *
+	 * @param {string} extension name of the required extension
+	 * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present
+	 * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)
+	 * @param {string} [message] optional error message (defaults to a descriptve error message)
+	 */
+	_requireExtension: function(name, required, before, message) {
+		before = !!before;
+		var thisName = this._local.name,
+			extList = this.options.extensions,
+			isBefore = $.inArray(name, extList) < $.inArray(thisName, extList),
+			isMissing = required && this.ext[name] == null,
+			badOrder = !isMissing && before != null && (before !== isBefore);
+
+		_assert(thisName && thisName !== name, "invalid or same name");
+
+		if( isMissing || badOrder ){
+			if( !message ){
+				if( isMissing || required ){
+					message = "'" + thisName + "' extension requires '" + name + "'";
+					if( badOrder ){
+						message += " to be registered " + (before ? "before" : "after") + " itself";
+					}
+				}else{
+					message = "If used together, `" + name + "` must be registered " + (before ? "before" : "after") + " `" + thisName + "`";
+				}
+			}
+			$.error(message);
+			return false;
+		}
+		return true;
+	},
+	/** Activate node with a given key and fire focus and activate events.
+	 *
+	 * A prevously activated node will be deactivated.
+	 * If activeVisible option is set, all parents will be expanded as necessary.
+	 * Pass key = false, to deactivate the current node only.
+	 * @param {string} key
+	 * @returns {FancytreeNode} activated node (null, if not found)
+	 */
+	activateKey: function(key) {
+		var node = this.getNodeByKey(key);
+		if(node){
+			node.setActive();
+		}else if(this.activeNode){
+			this.activeNode.setActive(false);
+		}
+		return node;
+	},
+	/** (experimental)
+	 *
+	 * @param {Array} patchList array of [key, NodePatch] arrays
+	 * @returns {$.Promise} resolved, when all patches have been applied
+	 * @see TreePatch
+	 */
+	applyPatch: function(patchList) {
+		var dfd, i, p2, key, patch, node,
+			patchCount = patchList.length,
+			deferredList = [];
+
+		for(i=0; i<patchCount; i++){
+			p2 = patchList[i];
+			_assert(p2.length === 2, "patchList must be an array of length-2-arrays");
+			key = p2[0];
+			patch = p2[1];
+			node = (key === null) ? this.rootNode : this.getNodeByKey(key);
+			if(node){
+				dfd = new $.Deferred();
+				deferredList.push(dfd);
+				node.applyPatch(patch).always(_makeResolveFunc(dfd, node));
+			}else{
+				this.warn("could not find node with key '" + key + "'");
+			}
+		}
+		// Return a promise that is resolved, when ALL patches were applied
+		return $.when.apply($, deferredList).promise();
+	},
+	/* TODO: implement in dnd extension
+	cancelDrag: function() {
+		var dd = $.ui.ddmanager.current;
+		if(dd){
+			dd.cancel();
+		}
+	},
+   */
+   /** Return the number of nodes.
+	* @returns {integer}
+	*/
+	count: function() {
+		return this.rootNode.countChildren();
+	},
+	/** Write to browser console if debugLevel >= 2 (prepending tree name)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	debug: function(msg){
+		if( this.options.debugLevel >= 2 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("log", arguments);
+		}
+	},
+	// TODO: disable()
+	// TODO: enable()
+	// TODO: enableUpdate()
+
+	/**Find all nodes that matches condition.
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode[]} array of nodes (may be empty)
+	 * @see FancytreeNode#findAll
+	 * @since 2.12
+	 */
+	findAll: function(match) {
+		return this.rootNode.findAll(match);
+	},
+	/**Find first node that matches condition.
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode} matching node or null
+	 * @see FancytreeNode#findFirst
+	 * @since 2.12
+	 */
+	findFirst: function(match) {
+		return this.rootNode.findFirst(match);
+	},
+	/** Find the next visible node that starts with `match`, starting at `startNode`
+	 * and wrap-around at the end.
+	 *
+	 * @param {string|function} match
+	 * @param {FancytreeNode} [startNode] defaults to first node
+	 * @returns {FancytreeNode} matching node or null
+	 */
+	findNextNode: function(match, startNode, visibleOnly) {
+		var stopNode = null,
+			parentChildren = startNode.parent.children,
+			matchingNode = null,
+			walkVisible = function(parent, idx, fn) {
+				var i, grandParent,
+					parentChildren = parent.children,
+					siblingCount = parentChildren.length,
+					node = parentChildren[idx];
+				// visit node itself
+				if( node && fn(node) === false ) {
+					return false;
+				}
+				// visit descendants
+				if( node && node.children && node.expanded ) {
+					if( walkVisible(node, 0, fn) === false ) {
+						return false;
+					}
+				}
+				// visit subsequent siblings
+				for( i = idx + 1; i < siblingCount; i++ ) {
+					if( walkVisible(parent, i, fn) === false ) {
+						return false;
+					}
+				}
+				// visit parent's subsequent siblings
+				grandParent = parent.parent;
+				if( grandParent ) {
+					return walkVisible(grandParent, grandParent.children.indexOf(parent) + 1, fn);
+				} else {
+					// wrap-around: restart with first node
+					return walkVisible(parent, 0, fn);
+				}
+			};
+
+		match = (typeof match === "string") ? _makeNodeTitleStartMatcher(match) : match;
+		startNode = startNode || this.getFirstChild();
+
+		walkVisible(startNode.parent, parentChildren.indexOf(startNode), function(node){
+			// Stop iteration if we see the start node a second time
+			if( node === stopNode ) {
+				return false;
+			}
+			stopNode = stopNode || node;
+			// Ignore nodes hidden by a filter
+			if( ! $(node.span).is(":visible") ) {
+				node.debug("quicksearch: skipping hidden node");
+				return;
+			}
+			// Test if we found a match, but search for a second match if this
+			// was the currently active node
+			if( match(node) ) {
+				// node.debug("quicksearch match " + node.title, startNode);
+				matchingNode = node;
+				if( matchingNode !== startNode ) {
+					return false;
+				}
+			}
+		});
+		return matchingNode;
+	},
+	// TODO: fromDict
+	/**
+	 * Generate INPUT elements that can be submitted with html forms.
+	 *
+	 * In selectMode 3 only the topmost selected nodes are considered, unless
+	 * `opts.stopOnParents: false` is passed.
+	 *
+	 * @param {boolean | string} [selected=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID[]')
+	 * @param {boolean | string} [active=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID_active')
+	 * @param {object} [opts] default { stopOnParents: true }
+	 */
+	generateFormElements: function(selected, active, opts) {
+		// TODO: test case
+		opts = opts || {};
+
+		var nodeList,
+			selectedName = (typeof selected === "string") ? selected : "ft_" + this._id + "[]",
+			activeName = (typeof active === "string") ? active : "ft_" + this._id + "_active",
+			id = "fancytree_result_" + this._id,
+			$result = $("#" + id),
+			stopOnParents = this.options.selectMode === 3 && opts.stopOnParents !== false;
+
+		if($result.length){
+			$result.empty();
+		}else{
+			$result = $("<div>", {
+				id: id
+			}).hide().insertAfter(this.$container);
+		}
+		if(selected !== false){
+			nodeList = this.getSelectedNodes(stopOnParents);
+			$.each(nodeList, function(idx, node){
+				$result.append($("<input>", {
+					type: "checkbox",
+					name: selectedName,
+					value: node.key,
+					checked: true
+				}));
+			});
+		}
+		if(active !== false && this.activeNode){
+			$result.append($("<input>", {
+				type: "radio",
+				name: activeName,
+				value: this.activeNode.key,
+				checked: true
+			}));
+		}
+	},
+	/**
+	 * Return the currently active node or null.
+	 * @returns {FancytreeNode}
+	 */
+	getActiveNode: function() {
+		return this.activeNode;
+	},
+	/** Return the first top level node if any (not the invisible root node).
+	 * @returns {FancytreeNode | null}
+	 */
+	getFirstChild: function() {
+		return this.rootNode.getFirstChild();
+	},
+	/**
+	 * Return node that has keyboard focus or null.
+	 * @returns {FancytreeNode}
+	 */
+	getFocusNode: function() {
+		return this.focusNode;
+	},
+	/**
+	 * Return node with a given key or null if not found.
+	 * @param {string} key
+	 * @param {FancytreeNode} [searchRoot] only search below this node
+	 * @returns {FancytreeNode | null}
+	 */
+	getNodeByKey: function(key, searchRoot) {
+		// Search the DOM by element ID (assuming this is faster than traversing all nodes).
+		// $("#...") has problems, if the key contains '.', so we use getElementById()
+		var el, match;
+		if(!searchRoot){
+			el = document.getElementById(this.options.idPrefix + key);
+			if( el ){
+				return el.ftnode ? el.ftnode : null;
+			}
+		}
+		// Not found in the DOM, but still may be in an unrendered part of tree
+		// TODO: optimize with specialized loop
+		// TODO: consider keyMap?
+		searchRoot = searchRoot || this.rootNode;
+		match = null;
+		searchRoot.visit(function(node){
+//            window.console.log("getNodeByKey(" + key + "): ", node.key);
+			if(node.key === key) {
+				match = node;
+				return false;
+			}
+		}, true);
+		return match;
+	},
+	/** Return the invisible system root node.
+	 * @returns {FancytreeNode}
+	 */
+	getRootNode: function() {
+		return this.rootNode;
+	},
+	/**
+	 * Return an array of selected nodes.
+	 * @param {boolean} [stopOnParents=false] only return the topmost selected
+	 *     node (useful with selectMode 3)
+	 * @returns {FancytreeNode[]}
+	 */
+	getSelectedNodes: function(stopOnParents) {
+		var nodeList = [];
+		this.rootNode.visit(function(node){
+			if( node.selected ) {
+				nodeList.push(node);
+				if( stopOnParents === true ){
+					return "skip"; // stop processing this branch
+				}
+			}
+		});
+		return nodeList;
+	},
+	/** Return true if the tree control has keyboard focus
+	 * @returns {boolean}
+	 */
+	hasFocus: function(){
+		return !!this._hasFocus;
+	},
+	/** Write to browser console if debugLevel >= 1 (prepending tree name)
+	 * @param {*} msg string or object or array of such
+	 */
+	info: function(msg){
+		if( this.options.debugLevel >= 1 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("info", arguments);
+		}
+	},
+/*
+	TODO: isInitializing: function() {
+		return ( this.phase=="init" || this.phase=="postInit" );
+	},
+	TODO: isReloading: function() {
+		return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
+	},
+	TODO: isUserEvent: function() {
+		return ( this.phase=="userEvent" );
+	},
+*/
+
+	/**
+	 * Make sure that a node with a given ID is loaded, by traversing - and
+	 * loading - its parents. This method is ment for lazy hierarchies.
+	 * A callback is executed for every node as we go.
+	 * @example
+	 * tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){
+	 *   if(status === "loaded") {
+	 *     console.log("loaded intermiediate node " + node);
+	 *   }else if(status === "ok") {
+	 *     node.activate();
+	 *   }
+	 * });
+	 *
+	 * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')
+	 * @param {function} callback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error')
+	 * @returns {$.Promise}
+	 */
+	loadKeyPath: function(keyPathList, callback, _rootNode) {
+		var deferredList, dfd, i, path, key, loadMap, node, root, segList,
+			sep = this.options.keyPathSeparator,
+			self = this;
+
+		if(!$.isArray(keyPathList)){
+			keyPathList = [keyPathList];
+		}
+		// Pass 1: handle all path segments for nodes that are already loaded
+		// Collect distinct top-most lazy nodes in a map
+		loadMap = {};
+
+		for(i=0; i<keyPathList.length; i++){
+			root = _rootNode || this.rootNode;
+			path = keyPathList[i];
+			// strip leading slash
+			if(path.charAt(0) === sep){
+				path = path.substr(1);
+			}
+			// traverse and strip keys, until we hit a lazy, unloaded node
+			segList = path.split(sep);
+			while(segList.length){
+				key = segList.shift();
+//                node = _findDirectChild(root, key);
+				node = root._findDirectChild(key);
+				if(!node){
+					this.warn("loadKeyPath: key not found: " + key + " (parent: " + root + ")");
+					callback.call(this, key, "error");
+					break;
+				}else if(segList.length === 0){
+					callback.call(this, node, "ok");
+					break;
+				}else if(!node.lazy || (node.hasChildren() !== undefined )){
+					callback.call(this, node, "loaded");
+					root = node;
+				}else{
+					callback.call(this, node, "loaded");
+//                    segList.unshift(key);
+					if(loadMap[key]){
+						loadMap[key].push(segList.join(sep));
+					}else{
+						loadMap[key] = [segList.join(sep)];
+					}
+					break;
+				}
+			}
+		}
+//        alert("loadKeyPath: loadMap=" + JSON.stringify(loadMap));
+		// Now load all lazy nodes and continue itearation for remaining paths
+		deferredList = [];
+		// Avoid jshint warning 'Don't make functions within a loop.':
+		function __lazyload(key, node, dfd){
+			callback.call(self, node, "loading");
+			node.load().done(function(){
+				self.loadKeyPath.call(self, loadMap[key], callback, node).always(_makeResolveFunc(dfd, self));
+			}).fail(function(errMsg){
+				self.warn("loadKeyPath: error loading: " + key + " (parent: " + root + ")");
+				callback.call(self, node, "error");
+				dfd.reject();
+			});
+		}
+		for(key in loadMap){
+			node = root._findDirectChild(key);
+//            alert("loadKeyPath: lazy node(" + key + ") = " + node);
+			dfd = new $.Deferred();
+			deferredList.push(dfd);
+			__lazyload(key, node, dfd);
+		}
+		// Return a promise that is resolved, when ALL paths were loaded
+		return $.when.apply($, deferredList).promise();
+	},
+	/** Re-fire beforeActivate and activate events. */
+	reactivate: function(setFocus) {
+		var res,
+			node = this.activeNode;
+
+		if( !node ) {
+			return _getResolvedPromise();
+		}
+		this.activeNode = null; // Force re-activating
+		res = node.setActive();
+		if( setFocus ){
+			node.setFocus();
+		}
+		return res;
+	},
+	/** Reload tree from source and return a promise.
+	 * @param [source] optional new source (defaults to initial source data)
+	 * @returns {$.Promise}
+	 */
+	reload: function(source) {
+		this._callHook("treeClear", this);
+		return this._callHook("treeLoad", this, source);
+	},
+	/**Render tree (i.e. create DOM elements for all top-level nodes).
+	 * @param {boolean} [force=false] create DOM elemnts, even is parent is collapsed
+	 * @param {boolean} [deep=false]
+	 */
+	render: function(force, deep) {
+		return this.rootNode.render(force, deep);
+	},
+	// TODO: selectKey: function(key, select)
+	// TODO: serializeArray: function(stopOnParents)
+	/**
+	 * @param {boolean} [flag=true]
+	 */
+	setFocus: function(flag) {
+		return this._callHook("treeSetFocus", this, flag);
+	},
+	/**
+	 * Return all nodes as nested list of {@link NodeData}.
+	 *
+	 * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)
+	 * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications
+	 * @returns {Array | object}
+	 * @see FancytreeNode#toDict
+	 */
+	toDict: function(includeRoot, callback){
+		var res = this.rootNode.toDict(true, callback);
+		return includeRoot ? res : res.children;
+	},
+	/* Implicitly called for string conversions.
+	 * @returns {string}
+	 */
+	toString: function(){
+		return "<Fancytree(#" + this._id + ")>";
+	},
+	/* _trigger a widget event with additional node ctx.
+	 * @see EventData
+	 */
+	_triggerNodeEvent: function(type, node, originalEvent, extra) {
+//		this.debug("_trigger(" + type + "): '" + ctx.node.title + "'", ctx);
+		var ctx = this._makeHookContext(node, originalEvent, extra),
+			res = this.widget._trigger(type, originalEvent, ctx);
+		if(res !== false && ctx.result !== undefined){
+			return ctx.result;
+		}
+		return res;
+	},
+	/* _trigger a widget event with additional tree data. */
+	_triggerTreeEvent: function(type, originalEvent, extra) {
+//		this.debug("_trigger(" + type + ")", ctx);
+		var ctx = this._makeHookContext(this, originalEvent, extra),
+			res = this.widget._trigger(type, originalEvent, ctx);
+
+		if(res !== false && ctx.result !== undefined){
+			return ctx.result;
+		}
+		return res;
+	},
+	/** Call fn(node) for all nodes.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and children only.
+	 * @returns {boolean} false, if the iterator was stopped.
+	 */
+	visit: function(fn) {
+		return this.rootNode.visit(fn, false);
+	},
+	/** Write warning to browser console (prepending tree info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	warn: function(msg){
+		Array.prototype.unshift.call(arguments, this.toString());
+		consoleApply("warn", arguments);
+	}
+};
+
+/**
+ * These additional methods of the {@link Fancytree} class are 'hook functions'
+ * that can be used and overloaded by extensions.
+ * (See <a href="https://github.com/mar10/fancytree/wiki/TutorialExtensions">writing extensions</a>.)
+ * @mixin Fancytree_Hooks
+ */
+$.extend(Fancytree.prototype,
+	/** @lends Fancytree_Hooks# */
+	{
+	/** Default handling for mouse click events.
+	 *
+	 * @param {EventData} ctx
+	 */
+	nodeClick: function(ctx) {
+		var activate, expand,
+			// event = ctx.originalEvent,
+			targetType = ctx.targetType,
+			node = ctx.node;
+
+//	    this.debug("ftnode.onClick(" + event.type + "): ftnode:" + this + ", button:" + event.button + ", which: " + event.which, ctx);
+		// TODO: use switch
+		// TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)
+		if( targetType === "expander" ) {
+			if( node.isLoading() ) {
+				// #495: we probably got a click event while a lazy load is pending.
+				// The 'expanded' state is not yet set, so 'toggle' would expand
+				// and trigger lazyLoad again.
+				// It would be better to allow to collapse/expand the status node
+				// while loading (instead of ignoring), but that would require some
+				// more work.
+				node.debug("Got 2nd click while loading: ignored");
+				return;
+			}
+			// Clicking the expander icon always expands/collapses
+			this._callHook("nodeToggleExpanded", ctx);
+
+		} else if( targetType === "checkbox" ) {
+			// Clicking the checkbox always (de)selects
+			this._callHook("nodeToggleSelected", ctx);
+			if( ctx.options.focusOnSelect ) { // #358
+				this._callHook("nodeSetFocus", ctx, true);
+			}
+
+		} else {
+			// Honor `clickFolderMode` for
+			expand = false;
+			activate = true;
+			if( node.folder ) {
+				switch( ctx.options.clickFolderMode ) {
+				case 2: // expand only
+					expand = true;
+					activate = false;
+					break;
+				case 3: // expand and activate
+					activate = true;
+					expand = true; //!node.isExpanded();
+					break;
+				// else 1 or 4: just activate
+				}
+			}
+			if( activate ) {
+				this.nodeSetFocus(ctx);
+				this._callHook("nodeSetActive", ctx, true);
+			}
+			if( expand ) {
+				if(!activate){
+//                    this._callHook("nodeSetFocus", ctx);
+				}
+//				this._callHook("nodeSetExpanded", ctx, true);
+				this._callHook("nodeToggleExpanded", ctx);
+			}
+		}
+		// Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+		// if(event.target.localName === "a" && event.target.className === "fancytree-title"){
+		// 	event.preventDefault();
+		// }
+		// TODO: return promise?
+	},
+	/** Collapse all other  children of same parent.
+	 *
+	 * @param {EventData} ctx
+	 * @param {object} callOpts
+	 */
+	nodeCollapseSiblings: function(ctx, callOpts) {
+		// TODO: return promise?
+		var ac, i, l,
+			node = ctx.node;
+
+		if( node.parent ){
+			ac = node.parent.children;
+			for (i=0, l=ac.length; i<l; i++) {
+				if ( ac[i] !== node && ac[i].expanded ){
+					this._callHook("nodeSetExpanded", ac[i], false, callOpts);
+				}
+			}
+		}
+	},
+	/** Default handling for mouse douleclick events.
+	 * @param {EventData} ctx
+	 */
+	nodeDblclick: function(ctx) {
+		// TODO: return promise?
+		if( ctx.targetType === "title" && ctx.options.clickFolderMode === 4) {
+//			this.nodeSetFocus(ctx);
+//			this._callHook("nodeSetActive", ctx, true);
+			this._callHook("nodeToggleExpanded", ctx);
+		}
+		// TODO: prevent text selection on dblclicks
+		if( ctx.targetType === "title" ) {
+			ctx.originalEvent.preventDefault();
+		}
+	},
+	/** Default handling for mouse keydown events.
+	 *
+	 * NOTE: this may be called with node == null if tree (but no node) has focus.
+	 * @param {EventData} ctx
+	 */
+	nodeKeydown: function(ctx) {
+		// TODO: return promise?
+		var matchNode, stamp, res, focusNode,
+			event = ctx.originalEvent,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			which = event.which,
+			whichChar = String.fromCharCode(which),
+			clean = !(event.altKey || event.ctrlKey || event.metaKey || event.shiftKey),
+			$target = $(event.target),
+			handled = true,
+			activate = !(event.ctrlKey || !opts.autoActivate );
+
+//		(node || FT).debug("ftnode.nodeKeydown(" + event.type + "): ftnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+//		FT.debug("eventToString", which, '"' + String.fromCharCode(which) + '"', '"' + FT.eventToString(event) + '"');
+
+		// Set focus to active (or first node) if no other node has the focus yet
+		if( !node ){
+			focusNode = (this.getActiveNode() || this.getFirstChild());
+			if (focusNode){
+				focusNode.setFocus();
+				node = ctx.node = this.focusNode;
+				node.debug("Keydown force focus on active node");
+			}
+		}
+
+		if( opts.quicksearch && clean && /\w/.test(whichChar) && !$target.is(":input:enabled") ) {
+			// Allow to search for longer streaks if typed in quickly
+			stamp = new Date().getTime();
+			if( stamp - tree.lastQuicksearchTime > 500 ) {
+				tree.lastQuicksearchTerm = "";
+			}
+			tree.lastQuicksearchTime = stamp;
+			tree.lastQuicksearchTerm += whichChar;
+			// tree.debug("quicksearch find", tree.lastQuicksearchTerm);
+			matchNode = tree.findNextNode(tree.lastQuicksearchTerm, tree.getActiveNode());
+			if( matchNode ) {
+				matchNode.setActive();
+			}
+			event.preventDefault();
+			return;
+		}
+		switch( FT.eventToString(event) ) {
+			case "+":
+			case "=": // 187: '+' @ Chrome, Safari
+				tree.nodeSetExpanded(ctx, true);
+				break;
+			case "-":
+				tree.nodeSetExpanded(ctx, false);
+				break;
+			case "space":
+				if(opts.checkbox){
+					tree.nodeToggleSelected(ctx);
+				}else{
+					tree.nodeSetActive(ctx, true);
+				}
+				break;
+			case "return":
+				tree.nodeSetActive(ctx, true);
+				break;
+			case "backspace":
+			case "left":
+			case "right":
+			case "up":
+			case "down":
+				res = node.navigate(event.which, activate);
+				break;
+			default:
+				handled = false;
+		}
+		if(handled){
+			event.preventDefault();
+		}
+	},
+
+
+	// /** Default handling for mouse keypress events. */
+	// nodeKeypress: function(ctx) {
+	//     var event = ctx.originalEvent;
+	// },
+
+	// /** Trigger lazyLoad event (async). */
+	// nodeLazyLoad: function(ctx) {
+	//     var node = ctx.node;
+	//     if(this._triggerNodeEvent())
+	// },
+	/** Load child nodes (async).
+	 *
+	 * @param {EventData} ctx
+	 * @param {object[]|object|string|$.Promise|function} source
+	 * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)
+	 *     data was rendered.
+	 */
+	nodeLoadChildren: function(ctx, source) {
+		var ajax, delay, dfd,
+			tree = ctx.tree,
+			node = ctx.node;
+
+		if($.isFunction(source)){
+			source = source();
+		}
+		// TOTHINK: move to 'ajax' extension?
+		if(source.url){
+			// `source` is an Ajax options object
+			ajax = $.extend({}, ctx.options.ajax, source);
+			if(ajax.debugDelay){
+				// simulate a slow server
+				delay = ajax.debugDelay;
+				if($.isArray(delay)){ // random delay range [min..max]
+					delay = delay[0] + Math.random() * (delay[1] - delay[0]);
+				}
+
+				node.debug("nodeLoadChildren waiting debug delay " + Math.round(delay) + "ms");
+				ajax.debugDelay = false;
+				dfd = $.Deferred(function (dfd) {
+					setTimeout(function () {
+						$.ajax(ajax)
+							.done(function () {	dfd.resolveWith(this, arguments); })
+							.fail(function () {	dfd.rejectWith(this, arguments); });
+					}, delay);
+				});
+			}else{
+				dfd = $.ajax(ajax);
+			}
+
+			// Defer the deferred: we want to be able to reject, even if ajax
+			// resolved ok.
+			source = new $.Deferred();
+			dfd.done(function (data, textStatus, jqXHR) {
+				var errorObj, res;
+				if(this.dataType === "json" && typeof data === "string"){
+					$.error("Ajax request returned a string (did you get the JSON dataType wrong?).");
+				}
+				// postProcess is similar to the standard ajax dataFilter hook,
+				// but it is also called for JSONP
+				if( ctx.options.postProcess ){
+					res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, error: null, dataType: this.dataType});
+					if( res.error ) {
+						errorObj = $.isPlainObject(res.error) ? res.error : {message: res.error};
+						errorObj = tree._makeHookContext(node, null, errorObj);
+						source.rejectWith(this, [errorObj]);
+						return;
+					}
+					data = $.isArray(res) ? res : data;
+
+				} else if (data && data.hasOwnProperty("d") && ctx.options.enableAspx ) {
+					// Process ASPX WebMethod JSON object inside "d" property
+					data = (typeof data.d === "string") ? $.parseJSON(data.d) : data.d;
+				}
+				source.resolveWith(this, [data]);
+			}).fail(function (jqXHR, textStatus, errorThrown) {
+				var errorObj = tree._makeHookContext(node, null, {
+					error: jqXHR,
+					args: Array.prototype.slice.call(arguments),
+					message: errorThrown,
+					details: jqXHR.status + ": " + errorThrown
+				});
+				source.rejectWith(this, [errorObj]);
+			});
+		}
+		// #383: accept and convert ECMAScript 6 Promise
+		if( $.isFunction(source.then) && $.isFunction(source["catch"]) ) {
+			dfd = source;
+			source = new $.Deferred();
+			dfd.then(function(value){
+				source.resolve(value);
+			}, function(reason){
+				source.reject(reason);
+			});
+		}
+		if($.isFunction(source.promise)){
+			// `source` is a deferred, i.e. ajax request
+			_assert(!node.isLoading(), "recursive load");
+			// node._isLoading = true;
+			tree.nodeSetStatus(ctx, "loading");
+
+			source.done(function (children) {
+				tree.nodeSetStatus(ctx, "ok");
+			}).fail(function(error){
+				var ctxErr;
+				if (error.node && error.error && error.message) {
+					// error is already a context object
+					ctxErr = error;
+				} else {
+					ctxErr = tree._makeHookContext(node, null, {
+						error: error, // it can be jqXHR or any custom error
+						args: Array.prototype.slice.call(arguments),
+						message: error ? (error.message || error.toString()) : ""
+					});
+				}
+				if( tree._triggerNodeEvent("loadError", ctxErr, null) !== false ) {
+					tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details);
+				}
+			});
+		}
+		// $.when(source) resolves also for non-deferreds
+		return $.when(source).done(function(children){
+			var metaData;
+
+			if( $.isPlainObject(children) ){
+				// We got {foo: 'abc', children: [...]}
+				// Copy extra properties to tree.data.foo
+				_assert(node.isRootNode(), "source may only be an object for root nodes (expecting an array of child objects otherwise)");
+				_assert($.isArray(children.children), "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')");
+				metaData = children;
+				children = children.children;
+				delete metaData.children;
+				$.extend(tree.data, metaData);
+			}
+			_assert($.isArray(children), "expected array of children");
+			node._setChildren(children);
+			// trigger fancytreeloadchildren
+			tree._triggerNodeEvent("loadChildren", node);
+		// }).always(function(){
+		// 	node._isLoading = false;
+		});
+	},
+	/** [Not Implemented]  */
+	nodeLoadKeyPath: function(ctx, keyPathList) {
+		// TODO: implement and improve
+		// http://code.google.com/p/dynatree/issues/detail?id=222
+	},
+	/**
+	 * Remove a single direct child of ctx.node.
+	 * @param {EventData} ctx
+	 * @param {FancytreeNode} childNode dircect child of ctx.node
+	 */
+	nodeRemoveChild: function(ctx, childNode) {
+		var idx,
+			node = ctx.node,
+			opts = ctx.options,
+			subCtx = $.extend({}, ctx, {node: childNode}),
+			children = node.children;
+
+		// FT.debug("nodeRemoveChild()", node.toString(), childNode.toString());
+
+		if( children.length === 1 ) {
+			_assert(childNode === children[0], "invalid single child");
+			return this.nodeRemoveChildren(ctx);
+		}
+		if( this.activeNode && (childNode === this.activeNode || this.activeNode.isDescendantOf(childNode))){
+			this.activeNode.setActive(false); // TODO: don't fire events
+		}
+		if( this.focusNode && (childNode === this.focusNode || this.focusNode.isDescendantOf(childNode))){
+			this.focusNode = null;
+		}
+		// TODO: persist must take care to clear select and expand cookies
+		this.nodeRemoveMarkup(subCtx);
+		this.nodeRemoveChildren(subCtx);
+		idx = $.inArray(childNode, children);
+		_assert(idx >= 0, "invalid child");
+		// Unlink to support GC
+		childNode.visit(function(n){
+			n.parent = null;
+		}, true);
+		this._callHook("treeRegisterNode", this, false, childNode);
+		if ( opts.removeNode ){
+			opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx);
+		}
+		// remove from child list
+		children.splice(idx, 1);
+	},
+	/**Remove HTML markup for all descendents of ctx.node.
+	 * @param {EventData} ctx
+	 */
+	nodeRemoveChildMarkup: function(ctx) {
+		var node = ctx.node;
+
+		// FT.debug("nodeRemoveChildMarkup()", node.toString());
+		// TODO: Unlink attr.ftnode to support GC
+		if(node.ul){
+			if( node.isRootNode() ) {
+				$(node.ul).empty();
+			} else {
+				$(node.ul).remove();
+				node.ul = null;
+			}
+			node.visit(function(n){
+				n.li = n.ul = null;
+			});
+		}
+	},
+	/**Remove all descendants of ctx.node.
+	* @param {EventData} ctx
+	*/
+	nodeRemoveChildren: function(ctx) {
+		var subCtx,
+			tree = ctx.tree,
+			node = ctx.node,
+			children = node.children,
+			opts = ctx.options;
+
+		// FT.debug("nodeRemoveChildren()", node.toString());
+		if(!children){
+			return;
+		}
+		if( this.activeNode && this.activeNode.isDescendantOf(node)){
+			this.activeNode.setActive(false); // TODO: don't fire events
+		}
+		if( this.focusNode && this.focusNode.isDescendantOf(node)){
+			this.focusNode = null;
+		}
+		// TODO: persist must take care to clear select and expand cookies
+		this.nodeRemoveChildMarkup(ctx);
+		// Unlink children to support GC
+		// TODO: also delete this.children (not possible using visit())
+		subCtx = $.extend({}, ctx);
+		node.visit(function(n){
+			n.parent = null;
+			tree._callHook("treeRegisterNode", tree, false, n);
+			if ( opts.removeNode ){
+				subCtx.node = n;
+				opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx);
+			}
+		});
+		if( node.lazy ){
+			// 'undefined' would be interpreted as 'not yet loaded' for lazy nodes
+			node.children = [];
+		} else{
+			node.children = null;
+		}
+		if( !node.isRootNode() ) {
+			node.expanded = false;  // #449, #459
+		}
+		this.nodeRenderStatus(ctx);
+	},
+	/**Remove HTML markup for ctx.node and all its descendents.
+	 * @param {EventData} ctx
+	 */
+	nodeRemoveMarkup: function(ctx) {
+		var node = ctx.node;
+		// FT.debug("nodeRemoveMarkup()", node.toString());
+		// TODO: Unlink attr.ftnode to support GC
+		if(node.li){
+			$(node.li).remove();
+			node.li = null;
+		}
+		this.nodeRemoveChildMarkup(ctx);
+	},
+	/**
+	 * Create `&lt;li>&lt;span>..&lt;/span> .. &lt;/li>` tags for this node.
+	 *
+	 * This method takes care that all HTML markup is created that is required
+	 * to display this node in it's current state.
+	 *
+	 * Call this method to create new nodes, or after the strucuture
+	 * was changed (e.g. after moving this node or adding/removing children)
+	 * nodeRenderTitle() and nodeRenderStatus() are implied.
+	 *
+	 * Note: if a node was created/removed, nodeRender() must be called for the
+	 *       parent.
+	 * &lt;code>
+	 * &lt;li id='KEY' ftnode=NODE>
+	 *     &lt;span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>
+	 *         &lt;span class="fancytree-expander">&lt;/span>
+	 *         &lt;span class="fancytree-checkbox">&lt;/span> // only present in checkbox mode
+	 *         &lt;span class="fancytree-icon">&lt;/span>
+	 *         &lt;a href="#" class="fancytree-title"> Node 1 &lt;/a>
+	 *     &lt;/span>
+	 *     &lt;ul> // only present if node has children
+	 *         &lt;li id='KEY' ftnode=NODE> child1 ... &lt;/li>
+	 *         &lt;li id='KEY' ftnode=NODE> child2 ... &lt;/li>
+	 *     &lt;/ul>
+	 * &lt;/li>
+	 * &lt;/code>
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [force=false] re-render, even if html markup was already created
+	 * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+	 * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later
+	 */
+	nodeRender: function(ctx, force, deep, collapsed, _recursive) {
+		/* This method must take care of all cases where the current data mode
+		 * (i.e. node hierarchy) does not match the current markup.
+		 *
+		 * - node was not yet rendered:
+		 *   create markup
+		 * - node was rendered: exit fast
+		 * - children have been added
+		 * - children have been removed
+		 */
+		var childLI, childNode1, childNode2, i, l, next, subCtx,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			aria = opts.aria,
+			firstTime = false,
+			parent = node.parent,
+			isRootNode = !parent,
+			children = node.children,
+			successorLi = null;
+		// FT.debug("nodeRender(" + !!force + ", " + !!deep + ")", node.toString());
+
+		if( ! isRootNode && ! parent.ul ) {
+			// Calling node.collapse on a deep, unrendered node
+			return;
+		}
+		_assert(isRootNode || parent.ul, "parent UL must exist");
+
+		// Render the node
+		if( !isRootNode ){
+			// Discard markup on force-mode, or if it is not linked to parent <ul>
+			if(node.li && (force || (node.li.parentNode !== node.parent.ul) ) ){
+				if( node.li.parentNode === node.parent.ul ){
+					// #486: store following node, so we can insert the new markup there later
+					successorLi = node.li.nextSibling;
+				}else{
+					// May happen, when a top-level node was dropped over another
+					this.debug("Unlinking " + node + " (must be child of " + node.parent + ")");
+				}
+//	            this.debug("nodeRemoveMarkup...");
+				this.nodeRemoveMarkup(ctx);
+			}
+			// Create <li><span /> </li>
+//			node.debug("render...");
+			if( !node.li ) {
+//	            node.debug("render... really");
+				firstTime = true;
+				node.li = document.createElement("li");
+				node.li.ftnode = node;
+				if(aria){
+					// TODO: why doesn't this work:
+//					node.li.role = "treeitem";
+//                    $(node.li).attr("role", "treeitem")
+//                    .attr("aria-labelledby", "ftal_" + node.key);
+				}
+				if( node.key && opts.generateIds ){
+					node.li.id = opts.idPrefix + node.key;
+				}
+				node.span = document.createElement("span");
+				node.span.className = "fancytree-node";
+				if(aria){
+					$(node.span).attr("aria-labelledby", "ftal_" + node.key);
+				}
+				node.li.appendChild(node.span);
+
+				// Create inner HTML for the <span> (expander, checkbox, icon, and title)
+				this.nodeRenderTitle(ctx);
+
+				// Allow tweaking and binding, after node was created for the first time
+				if ( opts.createNode ){
+					opts.createNode.call(tree, {type: "createNode"}, ctx);
+				}
+			}else{
+//				this.nodeRenderTitle(ctx);
+				this.nodeRenderStatus(ctx);
+			}
+			// Allow tweaking after node state was rendered
+			if ( opts.renderNode ){
+				opts.renderNode.call(tree, {type: "renderNode"}, ctx);
+			}
+		}
+
+		// Visit child nodes
+		if( children ){
+			if( isRootNode || node.expanded || deep === true ) {
+				// Create a UL to hold the children
+				if( !node.ul ){
+					node.ul = document.createElement("ul");
+					if((collapsed === true && !_recursive) || !node.expanded){
+						// hide top UL, so we can use an animation to show it later
+						node.ul.style.display = "none";
+					}
+					if(aria){
+						$(node.ul).attr("role", "group");
+					}
+					if ( node.li ) { // issue #67
+						node.li.appendChild(node.ul);
+					} else {
+						node.tree.$div.append(node.ul);
+					}
+				}
+				// Add child markup
+				for(i=0, l=children.length; i<l; i++) {
+					subCtx = $.extend({}, ctx, {node: children[i]});
+					this.nodeRender(subCtx, force, deep, false, true);
+				}
+				// Remove <li> if nodes have moved to another parent
+				childLI = node.ul.firstChild;
+				while( childLI ){
+					childNode2 = childLI.ftnode;
+					if( childNode2 && childNode2.parent !== node ) {
+						node.debug("_fixParent: remove missing " + childNode2, childLI);
+						next = childLI.nextSibling;
+						childLI.parentNode.removeChild(childLI);
+						childLI = next;
+					}else{
+						childLI = childLI.nextSibling;
+					}
+				}
+				// Make sure, that <li> order matches node.children order.
+				childLI = node.ul.firstChild;
+				for(i=0, l=children.length-1; i<l; i++) {
+					childNode1 = children[i];
+					childNode2 = childLI.ftnode;
+					if( childNode1 !== childNode2 ) {
+						// node.debug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
+						node.ul.insertBefore(childNode1.li, childNode2.li);
+					} else {
+						childLI = childLI.nextSibling;
+					}
+				}
+			}
+		}else{
+			// No children: remove markup if any
+			if( node.ul ){
+//				alert("remove child markup for " + node);
+				this.warn("remove child markup for " + node);
+				this.nodeRemoveChildMarkup(ctx);
+			}
+		}
+		if( !isRootNode ){
+			// Update element classes according to node state
+			// this.nodeRenderStatus(ctx);
+			// Finally add the whole structure to the DOM, so the browser can render
+			if( firstTime ){
+				// #486: successorLi is set, if we re-rendered (i.e. discarded)
+				// existing markup, which  we want to insert at the same position.
+				// (null is equivalent to append)
+//				parent.ul.appendChild(node.li);
+				parent.ul.insertBefore(node.li, successorLi);
+			}
+		}
+	},
+	/** Create HTML inside the node's outer &lt;span> (i.e. expander, checkbox,
+	 * icon, and title).
+	 *
+	 * nodeRenderStatus() is implied.
+	 * @param {EventData} ctx
+	 * @param {string} [title] optinal new title
+	 */
+	nodeRenderTitle: function(ctx, title) {
+		// set node connector images, links and text
+		var id, iconSpanClass, nodeTitle, role, tabindex, tooltip,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			aria = opts.aria,
+			level = node.getLevel(),
+			ares = [],
+			iconSrc = node.data.icon;
+
+		if(title !== undefined){
+			node.title = title;
+		}
+		if(!node.span){
+			// Silently bail out if node was not rendered yet, assuming
+			// node.render() will be called as the node becomes visible
+			return;
+		}
+		// connector (expanded, expandable or simple)
+		// TODO: optimize this if clause
+		if( level < opts.minExpandLevel ) {
+			if( !node.lazy ) {
+				node.expanded = true;
+			}
+			if(level > 1){
+				if(aria){
+					ares.push("<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>");
+				}else{
+					ares.push("<span class='fancytree-expander fancytree-expander-fixed''></span>");
+				}
+			}
+			// .. else (i.e. for root level) skip expander/connector alltogether
+		} else {
+			if(aria){
+				ares.push("<span role='button' class='fancytree-expander'></span>");
+			}else{
+				ares.push("<span class='fancytree-expander'></span>");
+			}
+		}
+		// Checkbox mode
+		if( opts.checkbox && node.hideCheckbox !== true && !node.isStatusNode() ) {
+			if(aria){
+				ares.push("<span role='checkbox' class='fancytree-checkbox'></span>");
+			}else{
+				ares.push("<span class='fancytree-checkbox'></span>");
+			}
+		}
+		// folder or doctype icon
+		role = aria ? " role='img'" : "";
+		if( iconSrc === true || (iconSrc !== false && opts.icons !== false) ) {
+			// opts.icons defines the default behavior, node.icon == true/false can override this
+			if ( iconSrc && typeof iconSrc === "string" ) {
+				// node.icon is an image url
+				iconSrc = (iconSrc.charAt(0) === "/") ? iconSrc : ((opts.imagePath || "") + iconSrc);
+				ares.push("<img src='" + iconSrc + "' class='fancytree-icon' alt='' />");
+			} else {
+				// See if node.iconclass or opts.iconClass() define a class name
+				iconSpanClass = (opts.iconClass && opts.iconClass.call(tree, {type: "iconClass"}, ctx)) || node.data.iconclass || null;
+				if( iconSpanClass ) {
+					ares.push("<span " + role + " class='fancytree-custom-icon " + iconSpanClass +  "'></span>");
+				} else {
+					ares.push("<span " + role + " class='fancytree-icon'></span>");
+				}
+			}
+		}
+
+		// node title
+		nodeTitle = "";
+		if ( opts.renderTitle ){
+			nodeTitle = opts.renderTitle.call(tree, {type: "renderTitle"}, ctx) || "";
+		}
+		if(!nodeTitle){
+			tooltip = node.tooltip ? " title='" + FT.escapeHtml(node.tooltip) + "'" : "";
+			id = aria ? " id='ftal_" + node.key + "'" : "";
+			role = aria ? " role='treeitem'" : "";
+			tabindex = opts.titlesTabbable ? " tabindex='0'" : "";
+
+			nodeTitle = "<span " + role + " class='fancytree-title'" + id + tooltip + tabindex + ">" + node.title + "</span>";
+		}
+		ares.push(nodeTitle);
+		// Note: this will trigger focusout, if node had the focus
+		//$(node.span).html(ares.join("")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly
+		node.span.innerHTML = ares.join("");
+		// Update CSS classes
+		this.nodeRenderStatus(ctx);
+	},
+	/** Update element classes according to node state.
+	 * @param {EventData} ctx
+	 */
+	nodeRenderStatus: function(ctx) {
+		// Set classes for current status
+		var node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+//			nodeContainer = node[tree.nodeContainerAttrName],
+			hasChildren = node.hasChildren(),
+			isLastSib = node.isLastSibling(),
+			aria = opts.aria,
+//            $ariaElem = aria ? $(node[tree.ariaPropName]) : null,
+			$ariaElem = $(node.span).find(".fancytree-title"),
+			cn = opts._classNames,
+			cnList = [],
+			statusElem = node[tree.statusClassPropName];
+
+		if( !statusElem ){
+			// if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)
+			return;
+		}
+		// Build a list of class names that we will add to the node <span>
+		cnList.push(cn.node);
+		if( tree.activeNode === node ){
+			cnList.push(cn.active);
+//			$(">span.fancytree-title", statusElem).attr("tabindex", "0");
+//			tree.$container.removeAttr("tabindex");
+		// }else{
+//			$(">span.fancytree-title", statusElem).removeAttr("tabindex");
+//			tree.$container.attr("tabindex", "0");
+		}
+		if( tree.focusNode === node ){
+			cnList.push(cn.focused);
+			if(aria){
+//              $(">span.fancytree-title", statusElem).attr("tabindex", "0");
+//                $(">span.fancytree-title", statusElem).attr("tabindex", "-1");
+				// TODO: is this the right element for this attribute?
+				$ariaElem
+					.attr("aria-activedescendant", true);
+//					.attr("tabindex", "-1");
+			}
+		}else if(aria){
+//			$(">span.fancytree-title", statusElem).attr("tabindex", "-1");
+			$ariaElem
+				.removeAttr("aria-activedescendant");
+//				.removeAttr("tabindex");
+		}
+		if( node.expanded ){
+			cnList.push(cn.expanded);
+			if(aria){
+				$ariaElem.attr("aria-expanded", true);
+			}
+		}else if(aria){
+			$ariaElem.removeAttr("aria-expanded");
+		}
+		if( node.folder ){
+			cnList.push(cn.folder);
+		}
+		if( hasChildren !== false ){
+			cnList.push(cn.hasChildren);
+		}
+		// TODO: required?
+		if( isLastSib ){
+			cnList.push(cn.lastsib);
+		}
+		if( node.lazy && node.children == null ){
+			cnList.push(cn.lazy);
+		}
+		if( node.partsel ){
+			cnList.push(cn.partsel);
+		}
+		if( node.unselectable ){
+			cnList.push(cn.unselectable);
+		}
+		if( node._isLoading ){
+			cnList.push(cn.loading);
+		}
+		if( node._error ){
+			cnList.push(cn.error);
+		}
+		if( node.selected ){
+			cnList.push(cn.selected);
+			if(aria){
+				$ariaElem.attr("aria-selected", true);
+			}
+		}else if(aria){
+			$ariaElem.attr("aria-selected", false);
+		}
+		if( node.extraClasses ){
+			cnList.push(node.extraClasses);
+		}
+		// IE6 doesn't correctly evaluate multiple class names,
+		// so we create combined class names that can be used in the CSS
+		if( hasChildren === false ){
+			cnList.push(cn.combinedExpanderPrefix + "n" +
+					(isLastSib ? "l" : "")
+					);
+		}else{
+			cnList.push(cn.combinedExpanderPrefix +
+					(node.expanded ? "e" : "c") +
+					(node.lazy && node.children == null ? "d" : "") +
+					(isLastSib ? "l" : "")
+					);
+		}
+		cnList.push(cn.combinedIconPrefix +
+				(node.expanded ? "e" : "c") +
+				(node.folder ? "f" : "")
+				);
+//        node.span.className = cnList.join(" ");
+		statusElem.className = cnList.join(" ");
+
+		// TODO: we should not set this in the <span> tag also, if we set it here:
+		// Maybe most (all) of the classes should be set in LI instead of SPAN?
+		if(node.li){
+			node.li.className = isLastSib ? cn.lastsib : "";
+		}
+	},
+	/** Activate node.
+	 * flag defaults to true.
+	 * If flag is true, the node is activated (must be a synchronous operation)
+	 * If flag is false, the node is deactivated (must be a synchronous operation)
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+	 * @returns {$.Promise}
+	 */
+	nodeSetActive: function(ctx, flag, callOpts) {
+		// Handle user click / [space] / [enter], according to clickFolderMode.
+		callOpts = callOpts || {};
+		var subCtx,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			noEvents = (callOpts.noEvents === true),
+			noFocus = (callOpts.noFocus === true),
+			isActive = (node === tree.activeNode);
+
+		// flag defaults to true
+		flag = (flag !== false);
+		// node.debug("nodeSetActive", flag);
+
+		if(isActive === flag){
+			// Nothing to do
+			return _getResolvedPromise(node);
+		}else if(flag && !noEvents && this._triggerNodeEvent("beforeActivate", node, ctx.originalEvent) === false ){
+			// Callback returned false
+			return _getRejectedPromise(node, ["rejected"]);
+		}
+		if(flag){
+			if(tree.activeNode){
+				_assert(tree.activeNode !== node, "node was active (inconsistency)");
+				subCtx = $.extend({}, ctx, {node: tree.activeNode});
+				tree.nodeSetActive(subCtx, false);
+				_assert(tree.activeNode === null, "deactivate was out of sync?");
+			}
+			if(opts.activeVisible){
+				// tree.nodeMakeVisible(ctx);
+				node.makeVisible({scrollIntoView: false}); // nodeSetFocus will scroll
+			}
+			tree.activeNode = node;
+			tree.nodeRenderStatus(ctx);
+			if( !noFocus ) {
+				tree.nodeSetFocus(ctx);
+			}
+			if( !noEvents ) {
+				tree._triggerNodeEvent("activate", node, ctx.originalEvent);
+			}
+		}else{
+			_assert(tree.activeNode === node, "node was not active (inconsistency)");
+			tree.activeNode = null;
+			this.nodeRenderStatus(ctx);
+			if( !noEvents ) {
+				ctx.tree._triggerNodeEvent("deactivate", node, ctx.originalEvent);
+			}
+		}
+		return _getResolvedPromise(node);
+	},
+	/** Expand or collapse node, return Deferred.promise.
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+	 * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)
+	 *     data was retrieved, rendered, and the expand animation finshed.
+	 */
+	nodeSetExpanded: function(ctx, flag, callOpts) {
+		callOpts = callOpts || {};
+		var _afterLoad, dfd, i, l, parents, prevAC,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			noAnimation = (callOpts.noAnimation === true),
+			noEvents = (callOpts.noEvents === true);
+
+		// flag defaults to true
+		flag = (flag !== false);
+
+		// node.debug("nodeSetExpanded(" + flag + ")");
+
+		if((node.expanded && flag) || (!node.expanded && !flag)){
+			// Nothing to do
+			// node.debug("nodeSetExpanded(" + flag + "): nothing to do");
+			return _getResolvedPromise(node);
+		}else if(flag && !node.lazy && !node.hasChildren() ){
+			// Prevent expanding of empty nodes
+			// return _getRejectedPromise(node, ["empty"]);
+			return _getResolvedPromise(node);
+		}else if( !flag && node.getLevel() < opts.minExpandLevel ) {
+			// Prevent collapsing locked levels
+			return _getRejectedPromise(node, ["locked"]);
+		}else if ( !noEvents && this._triggerNodeEvent("beforeExpand", node, ctx.originalEvent) === false ){
+			// Callback returned false
+			return _getRejectedPromise(node, ["rejected"]);
+		}
+		// If this node inside a collpased node, no animation and scrolling is needed
+		if( !noAnimation && !node.isVisible() ) {
+			noAnimation = callOpts.noAnimation = true;
+		}
+
+		dfd = new $.Deferred();
+
+		// Auto-collapse mode: collapse all siblings
+		if( flag && !node.expanded && opts.autoCollapse ) {
+			parents = node.getParentList(false, true);
+			prevAC = opts.autoCollapse;
+			try{
+				opts.autoCollapse = false;
+				for(i=0, l=parents.length; i<l; i++){
+					// TODO: should return promise?
+					this._callHook("nodeCollapseSiblings", parents[i], callOpts);
+				}
+			}finally{
+				opts.autoCollapse = prevAC;
+			}
+		}
+		// Trigger expand/collapse after expanding
+		dfd.done(function(){
+			var	lastChild = node.getLastChild();
+			if( flag && opts.autoScroll && !noAnimation && lastChild ) {
+				// Scroll down to last child, but keep current node visible
+				lastChild.scrollIntoView(true, {topNode: node}).always(function(){
+					if( !noEvents ) {
+						ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+					}
+				});
+			} else {
+				if( !noEvents ) {
+					ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+				}
+			}
+		});
+		// vvv Code below is executed after loading finished:
+		_afterLoad = function(callback){
+			var isVisible, isExpanded,
+				effect = opts.toggleEffect;
+
+			node.expanded = flag;
+			// Create required markup, but make sure the top UL is hidden, so we
+			// can animate later
+			tree._callHook("nodeRender", ctx, false, false, true);
+
+			// If the currently active node is now hidden, deactivate it
+			// if( opts.activeVisible && this.activeNode && ! this.activeNode.isVisible() ) {
+			//     this.activeNode.deactivate();
+			// }
+
+			// Expanding a lazy node: set 'loading...' and call callback
+			// if( bExpand && this.data.isLazy && this.childList === null && !this._isLoading ) {
+			//     this._loadContent();
+			//     return;
+			// }
+			// Hide children, if node is collapsed
+			if( node.ul ) {
+				isVisible = (node.ul.style.display !== "none");
+				isExpanded = !!node.expanded;
+				if ( isVisible === isExpanded ) {
+					node.warn("nodeSetExpanded: UL.style.display already set");
+
+				} else if ( !effect || noAnimation ) {
+					node.ul.style.display = ( node.expanded || !parent ) ? "" : "none";
+
+				} else {
+					// The UI toggle() effect works with the ext-wide extension,
+					// while jQuery.animate() has problems when the title span
+					// has positon: absolute
+
+					// duration = opts.fx.duration || 200;
+					// easing = opts.fx.easing;
+					// $(node.ul).animate(opts.fx, duration, easing, function(){
+
+					// node.debug("nodeSetExpanded: animate start...");
+					$(node.ul).toggle(effect.effect, effect.options, effect.duration, function(){
+						// node.debug("nodeSetExpanded: animate done");
+						callback();
+					});
+					return;
+				}
+			}
+			callback();
+		};
+		// ^^^ Code above is executed after loading finshed.
+
+		// Load lazy nodes, if any. Then continue with _afterLoad()
+		if(flag && node.lazy && node.hasChildren() === undefined){
+			// node.debug("nodeSetExpanded: load start...");
+			node.load().done(function(){
+				// node.debug("nodeSetExpanded: load done");
+				if(dfd.notifyWith){ // requires jQuery 1.6+
+					dfd.notifyWith(node, ["loaded"]);
+				}
+				_afterLoad(function () { dfd.resolveWith(node); });
+			}).fail(function(errMsg){
+				_afterLoad(function () { dfd.rejectWith(node, ["load failed (" + errMsg + ")"]); });
+			});
+/*
+			var source = tree._triggerNodeEvent("lazyLoad", node, ctx.originalEvent);
+			_assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+			node.debug("nodeSetExpanded: load start...");
+			this._callHook("nodeLoadChildren", ctx, source).done(function(){
+				node.debug("nodeSetExpanded: load done");
+				if(dfd.notifyWith){ // requires jQuery 1.6+
+					dfd.notifyWith(node, ["loaded"]);
+				}
+				_afterLoad.call(tree);
+			}).fail(function(errMsg){
+				dfd.rejectWith(node, ["load failed (" + errMsg + ")"]);
+			});
+*/
+		}else{
+			_afterLoad(function () { dfd.resolveWith(node); });
+		}
+		// node.debug("nodeSetExpanded: returns");
+		return dfd.promise();
+	},
+	/** Focus or blur this node.
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	nodeSetFocus: function(ctx, flag) {
+		// ctx.node.debug("nodeSetFocus(" + flag + ")");
+		var ctx2,
+			tree = ctx.tree,
+			node = ctx.node;
+
+		flag = (flag !== false);
+
+		// Blur previous node if any
+		if(tree.focusNode){
+			if(tree.focusNode === node && flag){
+				// node.debug("nodeSetFocus(" + flag + "): nothing to do");
+				return;
+			}
+			ctx2 = $.extend({}, ctx, {node: tree.focusNode});
+			tree.focusNode = null;
+			this._triggerNodeEvent("blur", ctx2);
+			this._callHook("nodeRenderStatus", ctx2);
+		}
+		// Set focus to container and node
+		if(flag){
+			if( !this.hasFocus() ){
+				node.debug("nodeSetFocus: forcing container focus");
+				this._callHook("treeSetFocus", ctx, true, {calledByNode: true});
+			}
+			node.makeVisible({scrollIntoView: false});
+			tree.focusNode = node;
+//			node.debug("FOCUS...");
+//			$(node.span).find(".fancytree-title").focus();
+			this._triggerNodeEvent("focus", ctx);
+//          if(ctx.options.autoActivate){
+//              tree.nodeSetActive(ctx, true);
+//          }
+			if(ctx.options.autoScroll){
+				node.scrollIntoView();
+			}
+			this._callHook("nodeRenderStatus", ctx);
+		}
+	},
+	/** (De)Select node, return new status (sync).
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	nodeSetSelected: function(ctx, flag) {
+		var node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options;
+		// flag defaults to true
+		flag = (flag !== false);
+
+		node.debug("nodeSetSelected(" + flag + ")", ctx);
+		if( node.unselectable){
+			return;
+		}
+		// TODO: !!node.expanded is nicer, but doesn't pass jshint
+		// https://github.com/jshint/jshint/issues/455
+//        if( !!node.expanded === !!flag){
+		if((node.selected && flag) || (!node.selected && !flag)){
+			return !!node.selected;
+		}else if ( this._triggerNodeEvent("beforeSelect", node, ctx.originalEvent) === false ){
+			return !!node.selected;
+		}
+		if(flag && opts.selectMode === 1){
+			// single selection mode
+			if(tree.lastSelectedNode){
+				tree.lastSelectedNode.setSelected(false);
+			}
+		}else if(opts.selectMode === 3){
+			// multi.hier selection mode
+			node.selected = flag;
+//			this._fixSelectionState(node);
+			node.fixSelection3AfterClick();
+		}
+		node.selected = flag;
+		this.nodeRenderStatus(ctx);
+		tree.lastSelectedNode = flag ? node : null;
+		tree._triggerNodeEvent("select", ctx);
+	},
+	/** Show node status (ok, loading, error) using styles and a dummy child node.
+	 *
+	 * @param {EventData} ctx
+	 * @param status
+	 * @param message
+	 * @param details
+	 * @since 2.3
+	 */
+	nodeSetStatus: function(ctx, status, message, details) {
+		var node = ctx.node,
+			tree = ctx.tree;
+			// cn = ctx.options._classNames;
+
+		function _clearStatusNode() {
+			// Remove dedicated dummy node, if any
+			var firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				try{
+					// I've seen exceptions here with loadKeyPath...
+					if(node.ul){
+						node.ul.removeChild(firstChild.li);
+						firstChild.li = null; // avoid leaks (DT issue 215)
+					}
+				}catch(e){}
+				if( node.children.length === 1 ){
+					node.children = [];
+				}else{
+					node.children.shift();
+				}
+			}
+		}
+		function _setStatusNode(data, type) {
+			// Create/modify the dedicated dummy node for 'loading...' or
+			// 'error!' status. (only called for direct child of the invisible
+			// system root)
+			var firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				$.extend(firstChild, data);
+				// tree._callHook("nodeRender", firstChild);
+				tree._callHook("nodeRenderTitle", firstChild);
+			} else {
+				data.key = "_statusNode";
+				node._setChildren([data]);
+				node.children[0].statusNodeType = type;
+				tree.render();
+			}
+			return node.children[0];
+		}
+
+		switch( status ){
+		case "ok":
+			_clearStatusNode();
+			// $(node.span).removeClass(cn.loading).removeClass(cn.error);
+			node._isLoading = false;
+			node._error = null;
+			node.renderStatus();
+			break;
+		case "loading":
+			// $(node.span).removeClass(cn.error).addClass(cn.loading);
+			if( !node.parent ) {
+				_setStatusNode({
+					title: tree.options.strings.loading + (message ? " (" + message + ") " : ""),
+					tooltip: details,
+					extraClasses: "fancytree-statusnode-wait"
+				}, status);
+			}
+			node._isLoading = true;
+			node._error = null;
+			node.renderStatus();
+			break;
+		case "error":
+			// $(node.span).removeClass(cn.loading).addClass(cn.error);
+			_setStatusNode({
+				title: tree.options.strings.loadError + (message ? " (" + message + ") " : ""),
+				tooltip: details,
+				extraClasses: "fancytree-statusnode-error"
+			}, status);
+			node._isLoading = false;
+			node._error = { message: message, details: details };
+			node.renderStatus();
+			break;
+		default:
+			$.error("invalid node status " + status);
+		}
+	},
+	/**
+	 *
+	 * @param {EventData} ctx
+	 */
+	nodeToggleExpanded: function(ctx) {
+		return this.nodeSetExpanded(ctx, !ctx.node.expanded);
+	},
+	/**
+	 * @param {EventData} ctx
+	 */
+	nodeToggleSelected: function(ctx) {
+		return this.nodeSetSelected(ctx, !ctx.node.selected);
+	},
+	/** Remove all nodes.
+	 * @param {EventData} ctx
+	 */
+	treeClear: function(ctx) {
+		var tree = ctx.tree;
+		tree.activeNode = null;
+		tree.focusNode = null;
+		tree.$div.find(">ul.fancytree-container").empty();
+		// TODO: call destructors and remove reference loops
+		tree.rootNode.children = null;
+	},
+	/** Widget was created (called only once, even it re-initialized).
+	 * @param {EventData} ctx
+	 */
+	treeCreate: function(ctx) {
+	},
+	/** Widget was destroyed.
+	 * @param {EventData} ctx
+	 */
+	treeDestroy: function(ctx) {
+		this.$div.find(">ul.fancytree-container").remove();
+		this.$source && this.$source.removeClass("ui-helper-hidden");
+	},
+	/** Widget was (re-)initialized.
+	 * @param {EventData} ctx
+	 */
+	treeInit: function(ctx) {
+		//this.debug("Fancytree.treeInit()");
+		this.treeLoad(ctx);
+	},
+	/** Parse Fancytree from source, as configured in the options.
+	 * @param {EventData} ctx
+	 * @param {object} [source] optional new source (use last data otherwise)
+	 */
+	treeLoad: function(ctx, source) {
+		var type, $ul,
+			tree = ctx.tree,
+			$container = ctx.widget.element,
+			dfd,
+			// calling context for root node
+			rootCtx = $.extend({}, ctx, {node: this.rootNode});
+
+		if(tree.rootNode.children){
+			this.treeClear(ctx);
+		}
+		source = source || this.options.source;
+
+		if(!source){
+			type = $container.data("type") || "html";
+			switch(type){
+			case "html":
+				$ul = $container.find(">ul:first");
+				$ul.addClass("ui-fancytree-source ui-helper-hidden");
+				source = $.ui.fancytree.parseHtml($ul);
+				// allow to init tree.data.foo from <ul data-foo=''>
+				this.data = $.extend(this.data, _getElementDataAsDict($ul));
+				break;
+			case "json":
+	//            $().addClass("ui-helper-hidden");
+				source = $.parseJSON($container.text());
+				if(source.children){
+					if(source.title){tree.title = source.title;}
+					source = source.children;
+				}
+				break;
+			default:
+				$.error("Invalid data-type: " + type);
+			}
+		}else if(typeof source === "string"){
+			// TODO: source is an element ID
+			$.error("Not implemented");
+		}
+
+		// Trigger fancytreeinit after nodes have been loaded
+		dfd = this.nodeLoadChildren(rootCtx, source).done(function(){
+			tree.render();
+			if( ctx.options.selectMode === 3 ){
+				tree.rootNode.fixSelection3FromEndNodes();
+			}
+			if( tree.activeNode && tree.options.activeVisible ) {
+				tree.activeNode.makeVisible();
+			}
+			tree._triggerTreeEvent("init", null, { status: true });
+		}).fail(function(){
+			tree.render();
+			tree._triggerTreeEvent("init", null, { status: false });
+		});
+		return dfd;
+	},
+	/** Node was inserted into or removed from the tree.
+	 * @param {EventData} ctx
+	 * @param {boolean} add
+	 * @param {FancytreeNode} node
+	 */
+	treeRegisterNode: function(ctx, add, node) {
+	},
+	/** Widget got focus.
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	treeSetFocus: function(ctx, flag, callOpts) {
+		flag = (flag !== false);
+
+		// this.debug("treeSetFocus(" + flag + "), callOpts: " + callOpts, this.hasFocus());
+		// this.debug("    focusNode: " + this.focusNode);
+		// this.debug("    activeNode: " + this.activeNode);
+		if( flag !== this.hasFocus() ){
+			this._hasFocus = flag;
+			if( !flag && this.focusNode ) {
+				// Node also looses focus if widget blurs
+				this.focusNode.setFocus(false);
+			}
+			this.$container.toggleClass("fancytree-treefocus", flag);
+			this._triggerTreeEvent(flag ? "focusTree" : "blurTree");
+		}
+	}
+});
+
+
+/* ******************************************************************************
+ * jQuery UI widget boilerplate
+ */
+
+/**
+ * The plugin (derrived from <a href=" http://api.jqueryui.com/jQuery.widget/">jQuery.Widget</a>).<br>
+ * This constructor is not called directly. Use `$(selector).fancytree({})`
+ * to initialize the plugin instead.<br>
+ * <pre class="sh_javascript sunlight-highlight-javascript">// Access widget methods and members:
+ * var tree = $("#tree").fancytree("getTree");
+ * var node = $("#tree").fancytree("getActiveNode", "1234");
+ * </pre>
+ *
+ * @mixin Fancytree_Widget
+ */
+
+$.widget("ui.fancytree",
+	/** @lends Fancytree_Widget# */
+	{
+	/**These options will be used as defaults
+	 * @type {FancytreeOptions}
+	 */
+	options:
+	{
+		activeVisible: true,
+		ajax: {
+			type: "GET",
+			cache: false, // false: Append random '_' argument to the request url to prevent caching.
+//          timeout: 0, // >0: Make sure we get an ajax error if server is unreachable
+			dataType: "json" // Expect json format and pass json object to callbacks.
+		},  //
+		aria: false, // TODO: default to true
+		autoActivate: true,
+		autoCollapse: false,
+//      autoFocus: false,
+		autoScroll: false,
+		checkbox: false,
+		/**defines click behavior*/
+		clickFolderMode: 4,
+		debugLevel: null, // 0..2 (null: use global setting $.ui.fancytree.debugInfo)
+		disabled: false, // TODO: required anymore?
+		enableAspx: true, // TODO: document
+		extensions: [],
+		// fx: { height: "toggle", duration: 200 },
+		// toggleEffect: { effect: "drop", options: {direction: "left"}, duration: 200 },
+		// toggleEffect: { effect: "slide", options: {direction: "up"}, duration: 200 },
+		toggleEffect: { effect: "blind", options: {direction: "vertical", scale: "box"}, duration: 200 },
+		generateIds: false,
+		icons: true,
+		idPrefix: "ft_",
+		focusOnSelect: false,
+		keyboard: true,
+		keyPathSeparator: "/",
+		minExpandLevel: 1,
+		quicksearch: false,
+		scrollOfs: {top: 0, bottom: 0},
+		scrollParent: null,
+		selectMode: 2,
+		strings: {
+			loading: "Loading&#8230;",
+			loadError: "Load error!"
+		},
+		tabbable: true,
+		titlesTabbable: false,
+		_classNames: {
+			node: "fancytree-node",
+			folder: "fancytree-folder",
+			combinedExpanderPrefix: "fancytree-exp-",
+			combinedIconPrefix: "fancytree-ico-",
+			hasChildren: "fancytree-has-children",
+			active: "fancytree-active",
+			selected: "fancytree-selected",
+			expanded: "fancytree-expanded",
+			lazy: "fancytree-lazy",
+			focused: "fancytree-focused",
+			partsel: "fancytree-partsel",
+			unselectable: "fancytree-unselectable",
+			lastsib: "fancytree-lastsib",
+			loading: "fancytree-loading",
+			error: "fancytree-error"
+		},
+		// events
+		lazyLoad: null,
+		postProcess: null
+	},
+	/* Set up the widget, Called on first $().fancytree() */
+	_create: function() {
+		this.tree = new Fancytree(this);
+
+		this.$source = this.source || this.element.data("type") === "json" ? this.element
+			: this.element.find(">ul:first");
+		// Subclass Fancytree instance with all enabled extensions
+		var extension, extName, i,
+			extensions = this.options.extensions,
+			base = this.tree;
+
+		for(i=0; i<extensions.length; i++){
+			extName = extensions[i];
+			extension = $.ui.fancytree._extensions[extName];
+			if(!extension){
+				$.error("Could not apply extension '" + extName + "' (it is not registered, did you forget to include it?)");
+			}
+			// Add extension options as tree.options.EXTENSION
+//			_assert(!this.tree.options[extName], "Extension name must not exist as option name: " + extName);
+			this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);
+			// Add a namespace tree.ext.EXTENSION, to hold instance data
+			_assert(this.tree.ext[extName] === undefined, "Extension name must not exist as Fancytree.ext attribute: '" + extName + "'");
+//			this.tree[extName] = extension;
+			this.tree.ext[extName] = {};
+			// Subclass Fancytree methods using proxies.
+			_subclassObject(this.tree, base, extension, extName);
+			// current extension becomes base for the next extension
+			base = extension;
+		}
+		//
+		this.tree._callHook("treeCreate", this.tree);
+		// Note: 'fancytreecreate' event is fired by widget base class
+//        this.tree._triggerTreeEvent("create");
+	},
+
+	/* Called on every $().fancytree() */
+	_init: function() {
+		this.tree._callHook("treeInit", this.tree);
+		// TODO: currently we call bind after treeInit, because treeInit
+		// might change tree.$container.
+		// It would be better, to move ebent binding into hooks altogether
+		this._bind();
+	},
+
+	/* Use the _setOption method to respond to changes to options */
+	_setOption: function(key, value) {
+		var callDefault = true,
+			rerender = false;
+		switch( key ) {
+		case "aria":
+		case "checkbox":
+		case "icons":
+		case "minExpandLevel":
+		case "tabbable":
+//		case "nolink":
+			this.tree._callHook("treeCreate", this.tree);
+			rerender = true;
+			break;
+		case "source":
+			callDefault = false;
+			this.tree._callHook("treeLoad", this.tree, value);
+			break;
+		}
+		this.tree.debug("set option " + key + "=" + value + " <" + typeof(value) + ">");
+		if(callDefault){
+			// In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget
+			$.Widget.prototype._setOption.apply(this, arguments);
+			// TODO: In jQuery UI 1.9 and above, you use the _super method instead
+//          this._super( "_setOption", key, value );
+		}
+		if(rerender){
+			this.tree.render(true, false);  // force, not-deep
+		}
+	},
+
+	/** Use the destroy method to clean up any modifications your widget has made to the DOM */
+	destroy: function() {
+		this._unbind();
+		this.tree._callHook("treeDestroy", this.tree);
+		// In jQuery UI 1.8, you must invoke the destroy method from the base widget
+		$.Widget.prototype.destroy.call(this);
+		// TODO: delete tree and nodes to make garbage collect easier?
+		// TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method
+	},
+
+	// -------------------------------------------------------------------------
+
+	/* Remove all event handlers for our namespace */
+	_unbind: function() {
+		var ns = this.tree._ns;
+		this.element.unbind(ns);
+		this.tree.$container.unbind(ns);
+		$(document).unbind(ns);
+	},
+	/* Add mouse and kyboard handlers to the container */
+	_bind: function() {
+		var that = this,
+			opts = this.options,
+			tree = this.tree,
+			ns = tree._ns
+			// selstartEvent = ( $.support.selectstart ? "selectstart" : "mousedown" )
+			;
+
+		// Remove all previuous handlers for this tree
+		this._unbind();
+
+		//alert("keydown" + ns + "foc=" + tree.hasFocus() + tree.$container);
+		// tree.debug("bind events; container: ", tree.$container);
+		tree.$container.on("focusin" + ns + " focusout" + ns, function(event){
+			var node = FT.getNode(event),
+				flag = (event.type === "focusin");
+			// tree.debug("Tree container got event " + event.type, node, event);
+			// tree.treeOnFocusInOut.call(tree, event);
+			if(node){
+				// For example clicking into an <input> that is part of a node
+				tree._callHook("nodeSetFocus", node, flag);
+			}else{
+				tree._callHook("treeSetFocus", tree, flag);
+			}
+		}).on("selectstart" + ns, "span.fancytree-title", function(event){
+			// prevent mouse-drags to select text ranges
+			// tree.debug("<span title> got event " + event.type);
+			event.preventDefault();
+		}).on("keydown" + ns, function(event){
+			// TODO: also bind keyup and keypress
+			// tree.debug("got event " + event.type + ", hasFocus:" + tree.hasFocus());
+			// if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){
+			if(opts.disabled || opts.keyboard === false ){
+				return true;
+			}
+			var res,
+				node = tree.focusNode, // node may be null
+				ctx = tree._makeHookContext(node || tree, event),
+				prevPhase = tree.phase;
+
+			try {
+				tree.phase = "userEvent";
+				// If a 'fancytreekeydown' handler returns false, skip the default
+				// handling (implemented by tree.nodeKeydown()).
+				if(node){
+					res = tree._triggerNodeEvent("keydown", node, event);
+				}else{
+					res = tree._triggerTreeEvent("keydown", event);
+				}
+				if ( res === "preventNav" ){
+					res = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls
+				} else if ( res !== false ){
+					res = tree._callHook("nodeKeydown", ctx);
+				}
+				return res;
+			} finally {
+				tree.phase = prevPhase;
+			}
+		}).on("click" + ns + " dblclick" + ns, function(event){
+			// that.tree.debug("event(" + event + "): !");
+			if(opts.disabled){
+				return true;
+			}
+			var ctx,
+				et = FT.getEventTarget(event),
+				node = et.node,
+				tree = that.tree,
+				prevPhase = tree.phase;
+
+			// that.tree.debug("event(" + event.type + "): node: ", node);
+			if( !node ){
+				return true;  // Allow bubbling of other events
+			}
+			ctx = tree._makeHookContext(node, event);
+//			that.tree.debug("event(" + event.type + "): node: ", node);
+			try {
+				tree.phase = "userEvent";
+				switch(event.type) {
+				case "click":
+					ctx.targetType = et.type;
+					return ( tree._triggerNodeEvent("click", ctx, event) === false ) ? false : tree._callHook("nodeClick", ctx);
+				case "dblclick":
+					ctx.targetType = et.type;
+					return ( tree._triggerNodeEvent("dblclick", ctx, event) === false ) ? false : tree._callHook("nodeDblclick", ctx);
+				}
+//             } catch(e) {
+// //                var _ = null; // DT issue 117 // TODO
+//                 $.error(e);
+			} finally {
+				tree.phase = prevPhase;
+			}
+		});
+	},
+	/** Return the active node or null.
+	 * @returns {FancytreeNode}
+	 */
+	getActiveNode: function() {
+		return this.tree.activeNode;
+	},
+	/** Return the matching node or null.
+	 * @param {string} key
+	 * @returns {FancytreeNode}
+	 */
+	getNodeByKey: function(key) {
+		return this.tree.getNodeByKey(key);
+	},
+	/** Return the invisible system root node.
+	 * @returns {FancytreeNode}
+	 */
+	getRootNode: function() {
+		return this.tree.rootNode;
+	},
+	/** Return the current tree instance.
+	 * @returns {Fancytree}
+	 */
+	getTree: function() {
+		return this.tree;
+	}
+});
+
+// $.ui.fancytree was created by the widget factory. Create a local shortcut:
+FT = $.ui.fancytree;
+
+/**
+ * Static members in the `$.ui.fancytree` namespace.<br>
+ * <br>
+ * <pre class="sh_javascript sunlight-highlight-javascript">// Access static members:
+ * var node = $.ui.fancytree.getNode(element);
+ * alert($.ui.fancytree.version);
+ * </pre>
+ *
+ * @mixin Fancytree_Static
+ */
+$.extend($.ui.fancytree,
+	/** @lends Fancytree_Static# */
+	{
+	/** @type {string} */
+	version: "2.13.0",      // Set to semver by 'grunt release'
+	/** @type {string} */
+	buildType: "production", // Set to 'production' by 'grunt build'
+	/** @type {int} */
+	debugLevel: 1,            // Set to 1 by 'grunt build'
+							  // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
+
+	_nextId: 1,
+	_nextNodeKey: 1,
+	_extensions: {},
+	// focusTree: null,
+
+	/** Expose class object as $.ui.fancytree._FancytreeClass */
+	_FancytreeClass: Fancytree,
+	/** Expose class object as $.ui.fancytree._FancytreeNodeClass */
+	_FancytreeNodeClass: FancytreeNode,
+	/* Feature checks to provide backwards compatibility */
+	jquerySupports: {
+		// http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+		positionMyOfs: isVersionAtLeast($.ui.version, 1, 9)
+		},
+	/** Throw an error if condition fails (debug method).
+	 * @param {boolean} cond
+	 * @param {string} msg
+	 */
+	assert: function(cond, msg){
+		return _assert(cond, msg);
+	},
+	/** Return a function that executes *fn* at most every *timeout* ms.
+	 * @param {integer} timeout
+	 * @param {function} fn
+	 * @param {boolean} [invokeAsap=false]
+	 * @param {any} [ctx]
+	 */
+	debounce: function(timeout, fn, invokeAsap, ctx) {
+		var timer;
+		if(arguments.length === 3 && typeof invokeAsap !== "boolean") {
+			ctx = invokeAsap;
+			invokeAsap = false;
+		}
+		return function() {
+			var args = arguments;
+			ctx = ctx || this;
+			invokeAsap && !timer && fn.apply(ctx, args);
+			clearTimeout(timer);
+			timer = setTimeout(function() {
+				invokeAsap || fn.apply(ctx, args);
+				timer = null;
+			}, timeout);
+		};
+	},
+	/** Write message to console if debugLevel >= 2
+	 * @param {string} msg
+	 */
+	debug: function(msg){
+		/*jshint expr:true */
+		($.ui.fancytree.debugLevel >= 2) && consoleApply("log", arguments);
+	},
+	/** Write error message to console.
+	 * @param {string} msg
+	 */
+	error: function(msg){
+		consoleApply("error", arguments);
+	},
+	/** Convert &lt;, &gt;, &amp;, &quot;, &#39;, &#x2F; to the equivalent entities.
+	 *
+	 * @param {string} s
+	 * @returns {string}
+	 */
+	escapeHtml: function(s){
+		return ("" + s).replace(/[&<>"'\/]/g, function (s) {
+			return ENTITY_MAP[s];
+		});
+	},
+	/** Make jQuery.position() arguments backwards compatible, i.e. if
+	 * jQuery UI version <= 1.8, convert
+	 *   { my: "left+3 center", at: "left bottom", of: $target }
+	 * to
+	 *   { my: "left center", at: "left bottom", of: $target, offset: "3  0" }
+	 *
+	 * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+	 * and http://jsfiddle.net/mar10/6xtu9a4e/
+	 */
+	fixPositionOptions: function(opts) {
+		if( opts.offset || ("" + opts.my + opts.at ).indexOf("%") >= 0 ) {
+		   $.error("expected new position syntax (but '%' is not supported)");
+		}
+		if( ! $.ui.fancytree.jquerySupports.positionMyOfs ) {
+			var // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]
+				myParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.my),
+				atParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.at),
+				// convert to numbers
+				dx = (myParts[2] ? (+myParts[2]) : 0) + (atParts[2] ? (+atParts[2]) : 0),
+				dy = (myParts[4] ? (+myParts[4]) : 0) + (atParts[4] ? (+atParts[4]) : 0);
+
+			opts = $.extend({}, opts, { // make a copy and overwrite
+				my: myParts[1] + " " + myParts[3],
+				at: atParts[1] + " " + atParts[3]
+			});
+			if( dx || dy ) {
+				opts.offset = "" + dx + " " + dy;
+			}
+		}
+		return opts;
+	},
+	/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+	 *
+	 * @param {Event} event Mouse event, e.g. click, ...
+	 * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+	 */
+	getEventTargetType: function(event){
+		return this.getEventTarget(event).type;
+	},
+	/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+	 *
+	 * @param {Event} event Mouse event, e.g. click, ...
+	 * @returns {object} Return a {node: FancytreeNode, type: TYPE} object
+	 *     TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+	 */
+	getEventTarget: function(event){
+		var tcn = event && event.target ? event.target.className : "",
+			res = {node: this.getNode(event.target), type: undefined};
+		// We use a fast version of $(res.node).hasClass()
+		// See http://jsperf.com/test-for-classname/2
+		if( /\bfancytree-title\b/.test(tcn) ){
+			res.type = "title";
+		}else if( /\bfancytree-expander\b/.test(tcn) ){
+			res.type = (res.node.hasChildren() === false ? "prefix" : "expander");
+		}else if( /\bfancytree-checkbox\b/.test(tcn) || /\bfancytree-radio\b/.test(tcn) ){
+			res.type = "checkbox";
+		}else if( /\bfancytree-icon\b/.test(tcn) ){
+			res.type = "icon";
+		}else if( /\bfancytree-node\b/.test(tcn) ){
+			// Somewhere near the title
+			res.type = "title";
+		}else if( event && event.target && $(event.target).closest(".fancytree-title").length ) {
+			// #228: clicking an embedded element inside a title
+			res.type = "title";
+		}
+		return res;
+	},
+	/** Return a FancytreeNode instance from element, event, or jQuery object.
+	 *
+	 * @param {Element | jQueryObject | Event} el
+	 * @returns {FancytreeNode} matching node or null
+	 */
+	getNode: function(el){
+		if(el instanceof FancytreeNode){
+			return el; // el already was a FancytreeNode
+		}else if(el.selector !== undefined){
+			el = el[0]; // el was a jQuery object: use the DOM element
+		}else if(el.originalEvent !== undefined){
+			el = el.target; // el was an Event
+		}
+		while( el ) {
+			if(el.ftnode) {
+				return el.ftnode;
+			}
+			el = el.parentNode;
+		}
+		return null;
+	},
+	/** Return a Fancytree instance, from element, index, event, or jQueryObject.
+	 *
+	 * @param {Element | jQueryObject | Event | integer | string} [el]
+	 * @returns {Fancytree} matching tree or null
+	 * @example
+	 * $.ui.fancytree.getTree();   // Get first Fancytree instance on page
+	 * $.ui.fancytree.getTree(1);  // Get second Fancytree instance on page
+	 * $.ui.fancytree.getTree("#tree"); // Get tree for this matching element
+	 *
+	 * @since 2.13
+	 */
+	getTree: function(el){
+		var widget;
+
+		if( el instanceof Fancytree ) {
+			return el; // el already was a Fancytree
+		}
+		if( el === undefined ) {
+			el = 0;  // get first tree
+		}
+		if( typeof el === "number" ) {
+			el = $(".fancytree-container").eq(el); // el was an integer: return nth instance
+		} else if( typeof el === "string" ) {
+			el = $(el).eq(0); // el was a selector: use first match
+		} else if( el.selector !== undefined ) {
+			el = el.eq(0); // el was a jQuery object: use the first DOM element
+		} else if( el.originalEvent !== undefined ) {
+			el = $(el.target); // el was an Event
+		}
+		el = el.closest(":ui-fancytree");
+		widget = el.data("ui-fancytree") || el.data("fancytree"); // the latter is required by jQuery <= 1.8
+		return widget ? widget.tree : null;
+	},
+	/** Write message to console if debugLevel >= 1
+	 * @param {string} msg
+	 */
+	info: function(msg){
+		/*jshint expr:true */
+		($.ui.fancytree.debugLevel >= 1) && consoleApply("info", arguments);
+	},
+	/** Convert a keydown or mouse event to a canonical string like 'ctrl+a', 'ctrl+shift+f2', 'shift+leftdblclick'.
+	 * This is especially handy for switch-statements in event handlers.
+	 * @param {event}
+	 * @returns {string}
+	 */
+	eventToString: function(event) {
+		// Poor-man's hotkeys. See here for a complete implementation:
+		//   https://github.com/jeresig/jquery.hotkeys
+		var which = event.which,
+			et = event.type,
+			s = [];
+
+		if( event.altKey ) { s.push("alt"); }
+		if( event.ctrlKey ) { s.push("ctrl"); }
+		if( event.metaKey ) { s.push("meta"); }
+		if( event.shiftKey ) { s.push("shift"); }
+
+		if( et === "click" || et === "dblclick" ) {
+			s.push(MOUSE_BUTTONS[event.button] + et);
+		} else {
+			if( !IGNORE_KEYCODES[which] ) {
+				s.push( SPECIAL_KEYCODES[which] || String.fromCharCode(which).toLowerCase() );
+			}
+		}
+		return s.join("+");
+	},
+	/* @deprecated: use eventToString(event) instead.
+	 */
+	keyEventToString: function(event) {
+		this.warn("keyEventToString() is deprecated: use eventToString()");
+		return this.eventToString(event);
+	},
+	/**
+	 * Parse tree data from HTML <ul> markup
+	 *
+	 * @param {jQueryObject} $ul
+	 * @returns {NodeData[]}
+	 */
+	parseHtml: function($ul) {
+		// TODO: understand this:
+		/*jshint validthis:true */
+		var classes, className, extraClasses, i, iPos, l, tmp, tmp2,
+			$children = $ul.find(">li"),
+			children = [];
+
+		$children.each(function() {
+			var allData, lowerCaseAttr,
+				$li = $(this),
+				$liSpan = $li.find(">span:first", this),
+				$liA = $liSpan.length ? null : $li.find(">a:first"),
+				d = { tooltip: null, data: {} };
+
+			if( $liSpan.length ) {
+				d.title = $liSpan.html();
+
+			} else if( $liA && $liA.length ) {
+				// If a <li><a> tag is specified, use it literally and extract href/target.
+				d.title = $liA.html();
+				d.data.href = $liA.attr("href");
+				d.data.target = $liA.attr("target");
+				d.tooltip = $liA.attr("title");
+
+			} else {
+				// If only a <li> tag is specified, use the trimmed string up to
+				// the next child <ul> tag.
+				d.title = $li.html();
+				iPos = d.title.search(/<ul/i);
+				if( iPos >= 0 ){
+					d.title = d.title.substring(0, iPos);
+				}
+			}
+			d.title = $.trim(d.title);
+
+			// Make sure all fields exist
+			for(i=0, l=CLASS_ATTRS.length; i<l; i++){
+				d[CLASS_ATTRS[i]] = undefined;
+			}
+			// Initialize to `true`, if class is set and collect extraClasses
+			classes = this.className.split(" ");
+			extraClasses = [];
+			for(i=0, l=classes.length; i<l; i++){
+				className = classes[i];
+				if(CLASS_ATTR_MAP[className]){
+					d[className] = true;
+				}else{
+					extraClasses.push(className);
+				}
+			}
+			d.extraClasses = extraClasses.join(" ");
+
+			// Parse node options from ID, title and class attributes
+			tmp = $li.attr("title");
+			if( tmp ){
+				d.tooltip = tmp; // overrides <a title='...'>
+			}
+			tmp = $li.attr("id");
+			if( tmp ){
+				d.key = tmp;
+			}
+			// Add <li data-NAME='...'> as node.data.NAME
+			allData = _getElementDataAsDict($li);
+			if( allData && !$.isEmptyObject(allData) ) {
+				// #507: convert data-hidecheckbox (lower case) to hideCheckbox
+				for( lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP ) {
+					if( allData.hasOwnProperty(lowerCaseAttr) ) {
+						allData[NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]] = allData[lowerCaseAttr];
+						delete allData[lowerCaseAttr];
+					}
+				}
+				// #56: Allow to set special node.attributes from data-...
+				for(i=0, l=NODE_ATTRS.length; i<l; i++){
+					tmp = NODE_ATTRS[i];
+					tmp2 = allData[tmp];
+					if( tmp2 != null ) {
+						delete allData[tmp];
+						d[tmp] = tmp2;
+					}
+				}
+				// All other data-... goes to node.data...
+				$.extend(d.data, allData);
+			}
+			// Recursive reading of child nodes, if LI tag contains an UL tag
+			$ul = $li.find(">ul:first");
+			if( $ul.length ) {
+				d.children = $.ui.fancytree.parseHtml($ul);
+			}else{
+				d.children = d.lazy ? undefined : null;
+			}
+			children.push(d);
+//            FT.debug("parse ", d, children);
+		});
+		return children;
+	},
+	/** Add Fancytree extension definition to the list of globally available extensions.
+	 *
+	 * @param {object} definition
+	 */
+	registerExtension: function(definition){
+		_assert(definition.name != null, "extensions must have a `name` property.");
+		_assert(definition.version != null, "extensions must have a `version` property.");
+		$.ui.fancytree._extensions[definition.name] = definition;
+	},
+	/** Inverse of escapeHtml().
+	 *
+	 * @param {string} s
+	 * @returns {string}
+	 */
+	unescapeHtml: function(s){
+		var e = document.createElement("div");
+		e.innerHTML = s;
+		return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
+	},
+	/** Write warning message to console.
+	 * @param {string} msg
+	 */
+	warn: function(msg){
+		consoleApply("warn", arguments);
+	}
+});
+
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.min.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.min.js
new file mode 100644
index 00000000000..13a2db40969
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/jquery.fancytree.min.js
@@ -0,0 +1,14 @@
+/*!
+ * jquery.fancytree.js
+ * Tree view control with support for lazy loading and much more.
+ * https://github.com/mar10/fancytree/
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+!function(a,b,c,d){"use strict";function e(b,c){b||(c=c?": "+c:"",a.error("Fancytree assertion failed"+c))}function f(a,c){var d,e,f=b.console?b.console[a]:null;if(f)try{f.apply(b.console,c)}catch(g){for(e="",d=0;d<c.length;d++)e+=c[d];f(e)}}function g(a){return!(!a.tree||a.statusNodeType===d)}function h(b){var c,d,e,f=a.map(a.trim(b).split("."),function(a){return parseInt(a,10)}),g=a.map(Array.prototype.slice.call(arguments,1),function(a){return parseInt(a,10)});for(c=0;c<g.length;c++)if(d=f[c]||0,e=g[c]||0,d!==e)return d>e;return!0}function i(a,b,c,d,e){var f=function(){var c=b[a],f=d[a],g=b.ext[e],h=function(){return c.apply(b,arguments)},i=function(a){return c.apply(b,a)};return function(){var a=b._local,c=b._super,d=b._superApply;try{return b._local=g,b._super=h,b._superApply=i,f.apply(b,arguments)}finally{b._local=a,b._super=c,b._superApply=d}}}();return f}function j(b,c,d,e){for(var f in d)"function"==typeof d[f]?"function"==typeof b[f]?b[f]=i(f,b,c,d,e):"_"===f.charAt(0)?b.ext[e][f]=i(f,b,c,d,e):a.error("Could not override tree."+f+". Use prefix '_' to create tree."+e+"._"+f):"options"!==f&&(b.ext[e][f]=d[f])}function k(b,c){return b===d?a.Deferred(function(){this.resolve()}).promise():a.Deferred(function(){this.resolveWith(b,c)}).promise()}function l(b,c){return b===d?a.Deferred(function(){this.reject()}).promise():a.Deferred(function(){this.rejectWith(b,c)}).promise()}function m(a,b){return function(){a.resolveWith(b)}}function n(b){var c=a.extend({},b.data()),d=c.json;return delete c.fancytree,delete c.uiFancytree,d&&(delete c.json,c=a.extend(c,d)),c}function o(a){return a=a.toLowerCase(),function(b){return b.title.toLowerCase().indexOf(a)>=0}}function p(a){var b=new RegExp("^"+a,"i");return function(a){return b.test(a.title)}}function q(b,c){var d,f,g,h;for(this.parent=b,this.tree=b.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},d=0,f=B.length;f>d;d++)g=B[d],this[g]=c[g];c.data&&a.extend(this.data,c.data);for(g in c)C[g]||a.isFunction(c[g])||E[g]||(this.data[g]=c[g]);null==this.key?this.tree.options.defaultKey?(this.key=this.tree.options.defaultKey(this),e(this.key,"defaultKey() must return a unique key")):this.key="_"+u._nextNodeKey++:this.key=""+this.key,c.active&&(e(null===this.tree.activeNode,"only one active node allowed"),this.tree.activeNode=this),c.selected&&(this.tree.lastSelectedNode=this),h=c.children,h?h.length?this._setChildren(h):this.children=this.lazy?[]:null:this.children=null,this.tree._callHook("treeRegisterNode",this.tree,!0,this)}function r(b){this.widget=b,this.$div=b.element,this.options=b.options,this.options&&(a.isFunction(this.options.lazyload)&&!a.isFunction(this.options.lazyLoad)&&(this.options.lazyLoad=function(){return u.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."),b.options.lazyload.apply(this,arguments)}),a.isFunction(this.options.loaderror)&&a.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."),this.options.fx!==d&&u.warn("The 'fx' options was replaced by 'toggleEffect' since 2014-11-30.")),this.ext={},this.data=n(this.$div),this._id=a.ui.fancytree._nextId++,this._ns=".fancytree-"+this._id,this.activeNode=null,this.focusNode=null,this._hasFocus=null,this.lastSelectedNode=null,this.systemFocusElement=null,this.lastQuicksearchTerm="",this.lastQuicksearchTime=0,this.statusClassPropName="span",this.ariaPropName="li",this.nodeContainerAttrName="li",this.$div.find(">ul.fancytree-container").remove();var c,e={tree:this};this.rootNode=new q(e,{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,c=a("<ul>",{"class":"ui-fancytree fancytree-container fancytree-plain"}).appendTo(this.$div),this.$container=c,this.rootNode.ul=c[0],null==this.options.debugLevel&&(this.options.debugLevel=u.debugLevel),this.$container.attr("tabindex",this.options.tabbable?"0":"-1"),this.options.aria&&this.$container.attr("role","tree").attr("aria-multiselectable",!0)}if(a.ui&&a.ui.fancytree)return void a.ui.fancytree.warn("Fancytree: ignored duplicate include");e(a.ui,"Fancytree requires jQuery UI (http://jqueryui.com)");var s,t,u=null,v={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"},w={16:!0,17:!0,18:!0},x={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},y={0:"",1:"left",2:"middle",3:"right"},z="active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),A={},B="expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "),C={},D={},E={active:!0,children:!0,data:!0,focus:!0};for(s=0;s<z.length;s++)A[z[s]]=!0;for(s=0;s<B.length;s++)t=B[s],C[t]=!0,t!==t.toLowerCase()&&(D[t.toLowerCase()]=t);q.prototype={_findDirectChild:function(a){var b,c,d=this.children;if(d)if("string"==typeof a){for(b=0,c=d.length;c>b;b++)if(d[b].key===a)return d[b]}else{if("number"==typeof a)return this.children[a];if(a.parent===this)return a}return null},_setChildren:function(a){e(a&&(!this.children||0===this.children.length),"only init supported"),this.children=[];for(var b=0,c=a.length;c>b;b++)this.children.push(new q(this,a[b]))},addChildren:function(b,c){var d,f,g,h=null,i=[];for(a.isPlainObject(b)&&(b=[b]),this.children||(this.children=[]),d=0,f=b.length;f>d;d++)i.push(new q(this,b[d]));return h=i[0],null==c?this.children=this.children.concat(i):(c=this._findDirectChild(c),g=a.inArray(c,this.children),e(g>=0,"insertBefore must be an existing child"),this.children.splice.apply(this.children,[g,0].concat(i))),(!this.parent||this.parent.ul||this.tr)&&this.render(),3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),h},addNode:function(a,b){switch((b===d||"over"===b)&&(b="child"),b){case"after":return this.getParent().addChildren(a,this.getNextSibling());case"before":return this.getParent().addChildren(a,this);case"firstChild":var c=this.children?this.children[0]:null;return this.addChildren(a,c);case"child":case"over":return this.addChildren(a)}e(!1,"Invalid mode: "+b)},appendSibling:function(a){return this.addNode(a,"after")},applyPatch:function(b){if(null===b)return this.remove(),k(this);var c,d,e,f={children:!0,expanded:!0,parent:!0};for(c in b)e=b[c],f[c]||a.isFunction(e)||(C[c]?this[c]=e:this.data[c]=e);return b.hasOwnProperty("children")&&(this.removeChildren(),b.children&&this._setChildren(b.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),d=b.hasOwnProperty("expanded")?this.setExpanded(b.expanded):k(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(a,b,c){return a.addNode(this.toDict(!0,c),b)},countChildren:function(a){var b,c,d,e=this.children;if(!e)return 0;if(d=e.length,a!==!1)for(b=0,c=d;c>b;b++)d+=e[b].countChildren();return d},debug:function(){this.tree.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},findAll:function(b){b=a.isFunction(b)?b:o(b);var c=[];return this.visit(function(a){b(a)&&c.push(a)}),c},findFirst:function(b){b=a.isFunction(b)?b:o(b);var c=null;return this.visit(function(a){return b(a)?(c=a,!1):void 0}),c},_changeSelectStatusAttrs:function(a){var b=!1;switch(a){case!1:b=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:b=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case d:b=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:e(!1,"invalid state: "+a)}return b&&this.renderStatus(),b},fixSelection3AfterClick:function(){var a=this.isSelected();this.visit(function(b){b._changeSelectStatusAttrs(a)}),this.fixSelection3FromEndNodes()},fixSelection3FromEndNodes:function(){function a(b){var c,e,f,g,h,i,j,k=b.children;if(k&&k.length){for(i=!0,j=!1,c=0,e=k.length;e>c;c++)f=k[c],g=a(f),g!==!1&&(j=!0),g!==!0&&(i=!1);h=i?!0:j?d:!1}else h=!!b.selected;return b._changeSelectStatusAttrs(h),h}e(3===this.tree.options.selectMode,"expected selectMode 3"),a(this),this.visitParents(function(a){var b,c,e,f,g=a.children,h=!0,i=!1;for(b=0,c=g.length;c>b;b++)e=g[b],(e.selected||e.partsel)&&(i=!0),e.unselectable||e.selected||(h=!1);f=h?!0:i?d:!1,a._changeSelectStatusAttrs(f)})},fromDict:function(b){for(var c in b)C[c]?this[c]=b[c]:"data"===c?a.extend(this.data,b.data):a.isFunction(b[c])||E[c]||(this.data[c]=b[c]);b.children&&(this.removeChildren(),this.addChildren(b.children)),this.renderTitle()},getChildren:function(){return this.hasChildren()===d?d:this.children},getFirstChild:function(){return this.children?this.children[0]:null},getIndex:function(){return a.inArray(this,this.parent.children)},getIndexHier:function(b){b=b||".";var c=[];return a.each(this.getParentList(!1,!0),function(a,b){c.push(b.getIndex()+1)}),c.join(b)},getKeyPath:function(a){var b=[],c=this.tree.options.keyPathSeparator;return this.visitParents(function(a){a.parent&&b.unshift(a.key)},!a),c+b.join(c)},getLastChild:function(){return this.children?this.children[this.children.length-1]:null},getLevel:function(){for(var a=0,b=this.parent;b;)a++,b=b.parent;return a},getNextSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=0,b=c.length-1;b>a;a++)if(c[a]===this)return c[a+1]}return null},getParent:function(){return this.parent},getParentList:function(a,b){for(var c=[],d=b?this:this.parent;d;)(a||d.parent)&&c.unshift(d),d=d.parent;return c},getPrevSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=1,b=c.length;b>a;a++)if(c[a]===this)return c[a-1]}return null},hasChildren:function(){return this.lazy?null==this.children?d:0===this.children.length?!1:1===this.children.length&&this.children[0].isStatusNode()?d:!0:!(!this.children||!this.children.length)},hasFocus:function(){return this.tree.hasFocus()&&this.tree.focusNode===this},info:function(){this.tree.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),f("info",arguments))},isActive:function(){return this.tree.activeNode===this},isChildOf:function(a){return this.parent&&this.parent===a},isDescendantOf:function(a){if(!a||a.tree!==this.tree)return!1;for(var b=this.parent;b;){if(b===a)return!0;b=b.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var a=this.parent;return!a||a.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var a=this.parent;return!a||a.children[a.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||this.hasChildren()!==d},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return this.hasChildren()===d},isVisible:function(){var a,b,c=this.getParentList(!1,!1);for(a=0,b=c.length;b>a;a++)if(!c[a].expanded)return!1;return!0},lazyLoad:function(a){return this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."),this.load(a)},load:function(a){var b,c,d=this;return e(this.isLazy(),"load() requires a lazy node"),a||this.isUndefined()?(this.isLoaded()&&this.resetLazy(),c=this.tree._triggerNodeEvent("lazyLoad",this),c===!1?k(this):(e("boolean"!=typeof c,"lazyLoad event must return source in data.result"),b=this.tree._callHook("nodeLoadChildren",this,c),this.expanded&&b.always(function(){d.render()}),b)):k(this)},makeVisible:function(b){var c,d=this,e=[],f=new a.Deferred,g=this.getParentList(!1,!1),h=g.length,i=!(b&&b.noAnimation===!0),j=!(b&&b.scrollIntoView===!1);for(c=h-1;c>=0;c--)e.push(g[c].setExpanded(!0,b));return a.when.apply(a,e).done(function(){j?d.scrollIntoView(i).done(function(){f.resolve()}):f.resolve()}),f.promise()},moveTo:function(b,c,f){(c===d||"over"===c)&&(c="child");var g,h=this.parent,i="child"===c?b:b.parent;if(this!==b){if(!this.parent)throw"Cannot move system root";if(i.isDescendantOf(this))throw"Cannot move a node to its own descendant";if(1===this.parent.children.length){if(this.parent===i)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else g=a.inArray(this,this.parent.children),e(g>=0,"invalid source parent"),this.parent.children.splice(g,1);if(this.parent=i,i.hasChildren())switch(c){case"child":i.children.push(this);break;case"before":g=a.inArray(b,i.children),e(g>=0,"invalid target parent"),i.children.splice(g,0,this);break;case"after":g=a.inArray(b,i.children),e(g>=0,"invalid target parent"),i.children.splice(g+1,0,this);break;default:throw"Invalid mode "+c}else i.children=[this];f&&b.visit(f,!0),this.tree!==b.tree&&(this.warn("Cross-tree moveTo is experimantal!"),this.visit(function(a){a.tree=b.tree},!0)),h.isDescendantOf(i)||h.render(),i.isDescendantOf(h)||i===h||i.render()}},navigate:function(b,c){function d(d){if(d){try{d.makeVisible()}catch(e){}return a(d.span).is(":visible")?c===!1?d.setFocus():d.setActive():(d.debug("Navigate: skipping hidden node"),void d.navigate(b,c))}}var e,f,g=!0,h=a.ui.keyCode,i=null;switch(b){case h.BACKSPACE:this.parent&&this.parent.parent&&d(this.parent);break;case h.LEFT:this.expanded?(this.setExpanded(!1),d(this)):this.parent&&this.parent.parent&&d(this.parent);break;case h.RIGHT:this.expanded||!this.children&&!this.lazy?this.children&&this.children.length&&d(this.children[0]):(this.setExpanded(),d(this));break;case h.UP:for(i=this.getPrevSibling();i&&!a(i.span).is(":visible");)i=i.getPrevSibling();for(;i&&i.expanded&&i.children&&i.children.length;)i=i.children[i.children.length-1];!i&&this.parent&&this.parent.parent&&(i=this.parent),d(i);break;case h.DOWN:if(this.expanded&&this.children&&this.children.length)i=this.children[0];else for(f=this.getParentList(!1,!0),e=f.length-1;e>=0;e--){for(i=f[e].getNextSibling();i&&!a(i.span).is(":visible");)i=i.getNextSibling();if(i)break}d(i);break;default:g=!1}},remove:function(){return this.parent.removeChild(this)},removeChild:function(a){return this.tree._callHook("nodeRemoveChild",this,a)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},render:function(a,b){return this.tree._callHook("nodeRender",this,a,b)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},resetLazy:function(){this.removeChildren(),this.expanded=!1,this.lazy=!0,this.children=d,this.renderStatus()},scheduleAction:function(a,b){this.tree.timer&&clearTimeout(this.tree.timer),this.tree.timer=null;var c=this;switch(a){case"cancel":break;case"expand":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger expand"),c.setExpanded(!0)},b);break;case"activate":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger activate"),c.setActive(!0)},b);break;default:throw"Invalid mode "+a}},scrollIntoView:function(f,h){h!==d&&g(h)&&(this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."),h={topNode:h});var i,j,l,m,n=a.extend({effects:f===!0?{duration:200,queue:!1}:f,scrollOfs:this.tree.options.scrollOfs,scrollParent:this.tree.options.scrollParent||this.tree.$container,topNode:null},h),o=new a.Deferred,p=this,q=a(this.span).height(),r=a(n.scrollParent),s=n.scrollOfs.top||0,t=n.scrollOfs.bottom||0,u=r.height(),v=r.scrollTop(),w=r,x=r[0]===b,y=n.topNode||null,z=null;return a(this.span).is(":visible")?(x?(j=a(this.span).offset().top,i=y&&y.span?a(y.span).offset().top:0,w=a("html,body")):(e(r[0]!==c&&r[0]!==c.body,"scrollParent should be an simple element or `window`, not document or body."),m=r.offset().top,j=a(this.span).offset().top-m+v,i=y?a(y.span).offset().top-m+v:0,l=Math.max(0,r.innerHeight()-r[0].clientHeight),u-=l),v+s>j?z=j-s:j+q>v+u-t&&(z=j+q-u+t,y&&(e(y.isRootNode()||a(y.span).is(":visible"),"topNode must be visible"),z>i&&(z=i-s))),null!==z?n.effects?(n.effects.complete=function(){o.resolveWith(p)},w.stop(!0).animate({scrollTop:z},n.effects)):(w[0].scrollTop=z,o.resolveWith(this)):o.resolveWith(this),o.promise()):(this.warn("scrollIntoView(): node is invisible."),k())},setActive:function(a,b){return this.tree._callHook("nodeSetActive",this,a,b)},setExpanded:function(a,b){return this.tree._callHook("nodeSetExpanded",this,a,b)},setFocus:function(a){return this.tree._callHook("nodeSetFocus",this,a)},setSelected:function(a){return this.tree._callHook("nodeSetSelected",this,a)},setStatus:function(a,b,c){return this.tree._callHook("nodeSetStatus",this,a,b,c)},setTitle:function(a){this.title=a,this.renderTitle()},sortChildren:function(a,b){var c,d,e=this.children;if(e){if(a=a||function(a,b){var c=a.title.toLowerCase(),d=b.title.toLowerCase();return c===d?0:c>d?1:-1},e.sort(a),b)for(c=0,d=e.length;d>c;c++)e[c].children&&e[c].sortChildren(a,"$norender$");"$norender$"!==b&&this.render()}},toDict:function(b,c){var d,e,f,g={},h=this;if(a.each(B,function(a,b){(h[b]||h[b]===!1)&&(g[b]=h[b])}),a.isEmptyObject(this.data)||(g.data=a.extend({},this.data),a.isEmptyObject(g.data)&&delete g.data),c&&c(g,h),b&&this.hasChildren())for(g.children=[],d=0,e=this.children.length;e>d;d++)f=this.children[d],f.isStatusNode()||g.children.push(f.toDict(!0,c));return g},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return"<FancytreeNode(#"+this.key+", '"+this.title+"')>"},visit:function(a,b){var c,d,e=!0,f=this.children;if(b===!0&&(e=a(this),e===!1||"skip"===e))return e;if(f)for(c=0,d=f.length;d>c&&(e=f[c].visit(a,!0),e!==!1);c++);return e},visitAndLoad:function(b,c,d){var e,f,g,h=this;return b&&c===!0&&(f=b(h),f===!1||"skip"===f)?d?f:k():h.children||h.lazy?(e=new a.Deferred,g=[],h.load().done(function(){for(var c=0,d=h.children.length;d>c;c++){if(f=h.children[c].visitAndLoad(b,!0,!0),f===!1){e.reject();break}"skip"!==f&&g.push(f)}a.when.apply(this,g).then(function(){e.resolve()})}),e.promise()):k()},visitParents:function(a,b){if(b&&a(this)===!1)return!1;for(var c=this.parent;c;){if(a(c)===!1)return!1;c=c.parent}return!0},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),f("warn",arguments)}},r.prototype={_makeHookContext:function(b,c,e){var f,g;return b.node!==d?(c&&b.originalEvent!==c&&a.error("invalid args"),f=b):b.tree?(g=b.tree,f={node:b,tree:g,widget:g.widget,options:g.widget.options,originalEvent:c}):b.widget?f={node:null,tree:b,widget:b.widget,options:b.widget.options,originalEvent:c}:a.error("invalid args"),e&&a.extend(f,e),f},_callHook:function(b,c){var d=this._makeHookContext(c),e=this[b],f=Array.prototype.slice.call(arguments,2);return a.isFunction(e)||a.error("_callHook('"+b+"') is not a function"),f.unshift(d),e.apply(this,f)},_requireExtension:function(b,c,d,f){d=!!d;var g=this._local.name,h=this.options.extensions,i=a.inArray(b,h)<a.inArray(g,h),j=c&&null==this.ext[b],k=!j&&null!=d&&d!==i;return e(g&&g!==b,"invalid or same name"),j||k?(f||(j||c?(f="'"+g+"' extension requires '"+b+"'",k&&(f+=" to be registered "+(d?"before":"after")+" itself")):f="If used together, `"+b+"` must be registered "+(d?"before":"after")+" `"+g+"`"),a.error(f),!1):!0},activateKey:function(a){var b=this.getNodeByKey(a);return b?b.setActive():this.activeNode&&this.activeNode.setActive(!1),b},applyPatch:function(b){var c,d,f,g,h,i,j=b.length,k=[];for(d=0;j>d;d++)f=b[d],e(2===f.length,"patchList must be an array of length-2-arrays"),g=f[0],h=f[1],i=null===g?this.rootNode:this.getNodeByKey(g),i?(c=new a.Deferred,k.push(c),i.applyPatch(h).always(m(c,i))):this.warn("could not find node with key '"+g+"'");return a.when.apply(a,k).promise()},count:function(){return this.rootNode.countChildren()},debug:function(){this.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},findAll:function(a){return this.rootNode.findAll(a)},findFirst:function(a){return this.rootNode.findFirst(a)},findNextNode:function(b,c){var d=null,e=c.parent.children,f=null,g=function(a,b,c){var d,e,f=a.children,h=f.length,i=f[b];if(i&&c(i)===!1)return!1;if(i&&i.children&&i.expanded&&g(i,0,c)===!1)return!1;for(d=b+1;h>d;d++)if(g(a,d,c)===!1)return!1;return e=a.parent,e?g(e,e.children.indexOf(a)+1,c):g(a,0,c)};return b="string"==typeof b?p(b):b,c=c||this.getFirstChild(),g(c.parent,e.indexOf(c),function(e){return e===d?!1:(d=d||e,a(e.span).is(":visible")?b(e)&&(f=e,f!==c)?!1:void 0:void e.debug("quicksearch: skipping hidden node"))}),f},generateFormElements:function(b,c,d){d=d||{};var e,f="string"==typeof b?b:"ft_"+this._id+"[]",g="string"==typeof c?c:"ft_"+this._id+"_active",h="fancytree_result_"+this._id,i=a("#"+h),j=3===this.options.selectMode&&d.stopOnParents!==!1;i.length?i.empty():i=a("<div>",{id:h}).hide().insertAfter(this.$container),b!==!1&&(e=this.getSelectedNodes(j),a.each(e,function(b,c){i.append(a("<input>",{type:"checkbox",name:f,value:c.key,checked:!0}))})),c!==!1&&this.activeNode&&i.append(a("<input>",{type:"radio",name:g,value:this.activeNode.key,checked:!0}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getNodeByKey:function(a,b){var d,e;return!b&&(d=c.getElementById(this.options.idPrefix+a))?d.ftnode?d.ftnode:null:(b=b||this.rootNode,e=null,b.visit(function(b){return b.key===a?(e=b,!1):void 0},!0),e)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(a){var b=[];return this.rootNode.visit(function(c){return c.selected&&(b.push(c),a===!0)?"skip":void 0}),b},hasFocus:function(){return!!this._hasFocus},info:function(){this.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),f("info",arguments))},loadKeyPath:function(b,c,e){function f(a,b,d){c.call(r,b,"loading"),b.load().done(function(){r.loadKeyPath.call(r,l[a],c,b).always(m(d,r))}).fail(function(){r.warn("loadKeyPath: error loading: "+a+" (parent: "+o+")"),c.call(r,b,"error"),d.reject()})}var g,h,i,j,k,l,n,o,p,q=this.options.keyPathSeparator,r=this;for(a.isArray(b)||(b=[b]),l={},i=0;i<b.length;i++)for(o=e||this.rootNode,j=b[i],j.charAt(0)===q&&(j=j.substr(1)),p=j.split(q);p.length;){if(k=p.shift(),n=o._findDirectChild(k),!n){this.warn("loadKeyPath: key not found: "+k+" (parent: "+o+")"),c.call(this,k,"error");break}if(0===p.length){c.call(this,n,"ok");break}if(n.lazy&&n.hasChildren()===d){c.call(this,n,"loaded"),l[k]?l[k].push(p.join(q)):l[k]=[p.join(q)];break}c.call(this,n,"loaded"),o=n}g=[];for(k in l)n=o._findDirectChild(k),h=new a.Deferred,g.push(h),f(k,n,h);return a.when.apply(a,g).promise()},reactivate:function(a){var b,c=this.activeNode;return c?(this.activeNode=null,b=c.setActive(),a&&c.setFocus(),b):k()},reload:function(a){return this._callHook("treeClear",this),this._callHook("treeLoad",this,a)},render:function(a,b){return this.rootNode.render(a,b)},setFocus:function(a){return this._callHook("treeSetFocus",this,a)},toDict:function(a,b){var c=this.rootNode.toDict(!0,b);return a?c:c.children},toString:function(){return"<Fancytree(#"+this._id+")>"},_triggerNodeEvent:function(a,b,c,e){var f=this._makeHookContext(b,c,e),g=this.widget._trigger(a,c,f);return g!==!1&&f.result!==d?f.result:g},_triggerTreeEvent:function(a,b,c){var e=this._makeHookContext(this,b,c),f=this.widget._trigger(a,b,e);return f!==!1&&e.result!==d?e.result:f},visit:function(a){return this.rootNode.visit(a,!1)},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),f("warn",arguments)}},a.extend(r.prototype,{nodeClick:function(a){var b,c,d=a.targetType,e=a.node;if("expander"===d){if(e.isLoading())return void e.debug("Got 2nd click while loading: ignored");this._callHook("nodeToggleExpanded",a)}else if("checkbox"===d)this._callHook("nodeToggleSelected",a),a.options.focusOnSelect&&this._callHook("nodeSetFocus",a,!0);else{if(c=!1,b=!0,e.folder)switch(a.options.clickFolderMode){case 2:c=!0,b=!1;break;case 3:b=!0,c=!0}b&&(this.nodeSetFocus(a),this._callHook("nodeSetActive",a,!0)),c&&this._callHook("nodeToggleExpanded",a)}},nodeCollapseSiblings:function(a,b){var c,d,e,f=a.node;if(f.parent)for(c=f.parent.children,d=0,e=c.length;e>d;d++)c[d]!==f&&c[d].expanded&&this._callHook("nodeSetExpanded",c[d],!1,b)},nodeDblclick:function(a){"title"===a.targetType&&4===a.options.clickFolderMode&&this._callHook("nodeToggleExpanded",a),"title"===a.targetType&&a.originalEvent.preventDefault()},nodeKeydown:function(b){var c,d,e,f,g=b.originalEvent,h=b.node,i=b.tree,j=b.options,k=g.which,l=String.fromCharCode(k),m=!(g.altKey||g.ctrlKey||g.metaKey||g.shiftKey),n=a(g.target),o=!0,p=!(g.ctrlKey||!j.autoActivate);if(h||(f=this.getActiveNode()||this.getFirstChild(),f&&(f.setFocus(),h=b.node=this.focusNode,h.debug("Keydown force focus on active node"))),j.quicksearch&&m&&/\w/.test(l)&&!n.is(":input:enabled"))return d=(new Date).getTime(),d-i.lastQuicksearchTime>500&&(i.lastQuicksearchTerm=""),i.lastQuicksearchTime=d,i.lastQuicksearchTerm+=l,c=i.findNextNode(i.lastQuicksearchTerm,i.getActiveNode()),c&&c.setActive(),void g.preventDefault();switch(u.eventToString(g)){case"+":case"=":i.nodeSetExpanded(b,!0);break;case"-":i.nodeSetExpanded(b,!1);break;case"space":j.checkbox?i.nodeToggleSelected(b):i.nodeSetActive(b,!0);break;case"return":i.nodeSetActive(b,!0);break;case"backspace":case"left":case"right":case"up":case"down":e=h.navigate(g.which,p);break;default:o=!1}o&&g.preventDefault()},nodeLoadChildren:function(b,c){var d,f,g,h=b.tree,i=b.node;return a.isFunction(c)&&(c=c()),c.url&&(d=a.extend({},b.options.ajax,c),d.debugDelay?(f=d.debugDelay,a.isArray(f)&&(f=f[0]+Math.random()*(f[1]-f[0])),i.debug("nodeLoadChildren waiting debug delay "+Math.round(f)+"ms"),d.debugDelay=!1,g=a.Deferred(function(b){setTimeout(function(){a.ajax(d).done(function(){b.resolveWith(this,arguments)}).fail(function(){b.rejectWith(this,arguments)})},f)})):g=a.ajax(d),c=new a.Deferred,g.done(function(d){var e,f;if("json"===this.dataType&&"string"==typeof d&&a.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),b.options.postProcess){if(f=h._triggerNodeEvent("postProcess",b,b.originalEvent,{response:d,error:null,dataType:this.dataType}),f.error)return e=a.isPlainObject(f.error)?f.error:{message:f.error},e=h._makeHookContext(i,null,e),void c.rejectWith(this,[e]);d=a.isArray(f)?f:d}else d&&d.hasOwnProperty("d")&&b.options.enableAspx&&(d="string"==typeof d.d?a.parseJSON(d.d):d.d);c.resolveWith(this,[d])}).fail(function(a,b,d){var e=h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:d,details:a.status+": "+d});c.rejectWith(this,[e])})),a.isFunction(c.then)&&a.isFunction(c["catch"])&&(g=c,c=new a.Deferred,g.then(function(a){c.resolve(a)},function(a){c.reject(a)})),a.isFunction(c.promise)&&(e(!i.isLoading(),"recursive load"),h.nodeSetStatus(b,"loading"),c.done(function(){h.nodeSetStatus(b,"ok")}).fail(function(a){var c;c=a.node&&a.error&&a.message?a:h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:a?a.message||a.toString():""}),h._triggerNodeEvent("loadError",c,null)!==!1&&h.nodeSetStatus(b,"error",c.message,c.details)})),a.when(c).done(function(b){var c;a.isPlainObject(b)&&(e(i.isRootNode(),"source may only be an object for root nodes (expecting an array of child objects otherwise)"),e(a.isArray(b.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),c=b,b=b.children,delete c.children,a.extend(h.data,c)),e(a.isArray(b),"expected array of children"),i._setChildren(b),h._triggerNodeEvent("loadChildren",i)})},nodeLoadKeyPath:function(){},nodeRemoveChild:function(b,c){var d,f=b.node,g=b.options,h=a.extend({},b,{node:c}),i=f.children;return 1===i.length?(e(c===i[0],"invalid single child"),this.nodeRemoveChildren(b)):(this.activeNode&&(c===this.activeNode||this.activeNode.isDescendantOf(c))&&this.activeNode.setActive(!1),this.focusNode&&(c===this.focusNode||this.focusNode.isDescendantOf(c))&&(this.focusNode=null),this.nodeRemoveMarkup(h),this.nodeRemoveChildren(h),d=a.inArray(c,i),e(d>=0,"invalid child"),c.visit(function(a){a.parent=null},!0),this._callHook("treeRegisterNode",this,!1,c),g.removeNode&&g.removeNode.call(b.tree,{type:"removeNode"},h),void i.splice(d,1))},nodeRemoveChildMarkup:function(b){var c=b.node;c.ul&&(c.isRootNode()?a(c.ul).empty():(a(c.ul).remove(),c.ul=null),c.visit(function(a){a.li=a.ul=null}))},nodeRemoveChildren:function(b){var c,d=b.tree,e=b.node,f=e.children,g=b.options;f&&(this.activeNode&&this.activeNode.isDescendantOf(e)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(e)&&(this.focusNode=null),this.nodeRemoveChildMarkup(b),c=a.extend({},b),e.visit(function(a){a.parent=null,d._callHook("treeRegisterNode",d,!1,a),g.removeNode&&(c.node=a,g.removeNode.call(b.tree,{type:"removeNode"},c))}),e.children=e.lazy?[]:null,e.isRootNode()||(e.expanded=!1),this.nodeRenderStatus(b))},nodeRemoveMarkup:function(b){var c=b.node;c.li&&(a(c.li).remove(),c.li=null),this.nodeRemoveChildMarkup(b)},nodeRender:function(b,d,f,g,h){var i,j,k,l,m,n,o,p=b.node,q=b.tree,r=b.options,s=r.aria,t=!1,u=p.parent,v=!u,w=p.children,x=null;if(v||u.ul){if(e(v||u.ul,"parent UL must exist"),v||(p.li&&(d||p.li.parentNode!==p.parent.ul)&&(p.li.parentNode===p.parent.ul?x=p.li.nextSibling:this.debug("Unlinking "+p+" (must be child of "+p.parent+")"),this.nodeRemoveMarkup(b)),p.li?this.nodeRenderStatus(b):(t=!0,p.li=c.createElement("li"),p.li.ftnode=p,p.key&&r.generateIds&&(p.li.id=r.idPrefix+p.key),p.span=c.createElement("span"),p.span.className="fancytree-node",s&&a(p.span).attr("aria-labelledby","ftal_"+p.key),p.li.appendChild(p.span),this.nodeRenderTitle(b),r.createNode&&r.createNode.call(q,{type:"createNode"},b)),r.renderNode&&r.renderNode.call(q,{type:"renderNode"},b)),w){if(v||p.expanded||f===!0){for(p.ul||(p.ul=c.createElement("ul"),(g===!0&&!h||!p.expanded)&&(p.ul.style.display="none"),s&&a(p.ul).attr("role","group"),p.li?p.li.appendChild(p.ul):p.tree.$div.append(p.ul)),l=0,m=w.length;m>l;l++)o=a.extend({},b,{node:w[l]}),this.nodeRender(o,d,f,!1,!0);for(i=p.ul.firstChild;i;)k=i.ftnode,k&&k.parent!==p?(p.debug("_fixParent: remove missing "+k,i),n=i.nextSibling,i.parentNode.removeChild(i),i=n):i=i.nextSibling;for(i=p.ul.firstChild,l=0,m=w.length-1;m>l;l++)j=w[l],k=i.ftnode,j!==k?p.ul.insertBefore(j.li,k.li):i=i.nextSibling}}else p.ul&&(this.warn("remove child markup for "+p),this.nodeRemoveChildMarkup(b));v||t&&u.ul.insertBefore(p.li,x)}},nodeRenderTitle:function(a,b){var c,e,f,g,h,i,j=a.node,k=a.tree,l=a.options,m=l.aria,n=j.getLevel(),o=[],p=j.data.icon;b!==d&&(j.title=b),j.span&&(n<l.minExpandLevel?(j.lazy||(j.expanded=!0),n>1&&o.push(m?"<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>":"<span class='fancytree-expander fancytree-expander-fixed''></span>")):o.push(m?"<span role='button' class='fancytree-expander'></span>":"<span class='fancytree-expander'></span>"),l.checkbox&&j.hideCheckbox!==!0&&!j.isStatusNode()&&o.push(m?"<span role='checkbox' class='fancytree-checkbox'></span>":"<span class='fancytree-checkbox'></span>"),g=m?" role='img'":"",(p===!0||p!==!1&&l.icons!==!1)&&(p&&"string"==typeof p?(p="/"===p.charAt(0)?p:(l.imagePath||"")+p,o.push("<img src='"+p+"' class='fancytree-icon' alt='' />")):(e=l.iconClass&&l.iconClass.call(k,{type:"iconClass"},a)||j.data.iconclass||null,o.push(e?"<span "+g+" class='fancytree-custom-icon "+e+"'></span>":"<span "+g+" class='fancytree-icon'></span>"))),f="",l.renderTitle&&(f=l.renderTitle.call(k,{type:"renderTitle"},a)||""),f||(i=j.tooltip?" title='"+u.escapeHtml(j.tooltip)+"'":"",c=m?" id='ftal_"+j.key+"'":"",g=m?" role='treeitem'":"",h=l.titlesTabbable?" tabindex='0'":"",f="<span "+g+" class='fancytree-title'"+c+i+h+">"+j.title+"</span>"),o.push(f),j.span.innerHTML=o.join(""),this.nodeRenderStatus(a))
+},nodeRenderStatus:function(b){var c=b.node,d=b.tree,e=b.options,f=c.hasChildren(),g=c.isLastSibling(),h=e.aria,i=a(c.span).find(".fancytree-title"),j=e._classNames,k=[],l=c[d.statusClassPropName];l&&(k.push(j.node),d.activeNode===c&&k.push(j.active),d.focusNode===c?(k.push(j.focused),h&&i.attr("aria-activedescendant",!0)):h&&i.removeAttr("aria-activedescendant"),c.expanded?(k.push(j.expanded),h&&i.attr("aria-expanded",!0)):h&&i.removeAttr("aria-expanded"),c.folder&&k.push(j.folder),f!==!1&&k.push(j.hasChildren),g&&k.push(j.lastsib),c.lazy&&null==c.children&&k.push(j.lazy),c.partsel&&k.push(j.partsel),c.unselectable&&k.push(j.unselectable),c._isLoading&&k.push(j.loading),c._error&&k.push(j.error),c.selected?(k.push(j.selected),h&&i.attr("aria-selected",!0)):h&&i.attr("aria-selected",!1),c.extraClasses&&k.push(c.extraClasses),k.push(f===!1?j.combinedExpanderPrefix+"n"+(g?"l":""):j.combinedExpanderPrefix+(c.expanded?"e":"c")+(c.lazy&&null==c.children?"d":"")+(g?"l":"")),k.push(j.combinedIconPrefix+(c.expanded?"e":"c")+(c.folder?"f":"")),l.className=k.join(" "),c.li&&(c.li.className=g?j.lastsib:""))},nodeSetActive:function(b,c,d){d=d||{};var f,g=b.node,h=b.tree,i=b.options,j=d.noEvents===!0,m=d.noFocus===!0,n=g===h.activeNode;return c=c!==!1,n===c?k(g):c&&!j&&this._triggerNodeEvent("beforeActivate",g,b.originalEvent)===!1?l(g,["rejected"]):(c?(h.activeNode&&(e(h.activeNode!==g,"node was active (inconsistency)"),f=a.extend({},b,{node:h.activeNode}),h.nodeSetActive(f,!1),e(null===h.activeNode,"deactivate was out of sync?")),i.activeVisible&&g.makeVisible({scrollIntoView:!1}),h.activeNode=g,h.nodeRenderStatus(b),m||h.nodeSetFocus(b),j||h._triggerNodeEvent("activate",g,b.originalEvent)):(e(h.activeNode===g,"node was not active (inconsistency)"),h.activeNode=null,this.nodeRenderStatus(b),j||b.tree._triggerNodeEvent("deactivate",g,b.originalEvent)),k(g))},nodeSetExpanded:function(b,c,e){e=e||{};var f,g,h,i,j,m,n=b.node,o=b.tree,p=b.options,q=e.noAnimation===!0,r=e.noEvents===!0;if(c=c!==!1,n.expanded&&c||!n.expanded&&!c)return k(n);if(c&&!n.lazy&&!n.hasChildren())return k(n);if(!c&&n.getLevel()<p.minExpandLevel)return l(n,["locked"]);if(!r&&this._triggerNodeEvent("beforeExpand",n,b.originalEvent)===!1)return l(n,["rejected"]);if(q||n.isVisible()||(q=e.noAnimation=!0),g=new a.Deferred,c&&!n.expanded&&p.autoCollapse){j=n.getParentList(!1,!0),m=p.autoCollapse;try{for(p.autoCollapse=!1,h=0,i=j.length;i>h;h++)this._callHook("nodeCollapseSiblings",j[h],e)}finally{p.autoCollapse=m}}return g.done(function(){var a=n.getLastChild();c&&p.autoScroll&&!q&&a?a.scrollIntoView(!0,{topNode:n}).always(function(){r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}):r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}),f=function(d){var e,f,g=p.toggleEffect;if(n.expanded=c,o._callHook("nodeRender",b,!1,!1,!0),n.ul)if(e="none"!==n.ul.style.display,f=!!n.expanded,e===f)n.warn("nodeSetExpanded: UL.style.display already set");else{if(g&&!q)return void a(n.ul).toggle(g.effect,g.options,g.duration,function(){d()});n.ul.style.display=n.expanded||!parent?"":"none"}d()},c&&n.lazy&&n.hasChildren()===d?n.load().done(function(){g.notifyWith&&g.notifyWith(n,["loaded"]),f(function(){g.resolveWith(n)})}).fail(function(a){f(function(){g.rejectWith(n,["load failed ("+a+")"])})}):f(function(){g.resolveWith(n)}),g.promise()},nodeSetFocus:function(b,c){var d,e=b.tree,f=b.node;if(c=c!==!1,e.focusNode){if(e.focusNode===f&&c)return;d=a.extend({},b,{node:e.focusNode}),e.focusNode=null,this._triggerNodeEvent("blur",d),this._callHook("nodeRenderStatus",d)}c&&(this.hasFocus()||(f.debug("nodeSetFocus: forcing container focus"),this._callHook("treeSetFocus",b,!0,{calledByNode:!0})),f.makeVisible({scrollIntoView:!1}),e.focusNode=f,this._triggerNodeEvent("focus",b),b.options.autoScroll&&f.scrollIntoView(),this._callHook("nodeRenderStatus",b))},nodeSetSelected:function(a,b){var c=a.node,d=a.tree,e=a.options;if(b=b!==!1,c.debug("nodeSetSelected("+b+")",a),!c.unselectable){if(c.selected&&b||!c.selected&&!b)return!!c.selected;if(this._triggerNodeEvent("beforeSelect",c,a.originalEvent)===!1)return!!c.selected;b&&1===e.selectMode?d.lastSelectedNode&&d.lastSelectedNode.setSelected(!1):3===e.selectMode&&(c.selected=b,c.fixSelection3AfterClick()),c.selected=b,this.nodeRenderStatus(a),d.lastSelectedNode=b?c:null,d._triggerNodeEvent("select",a)}},nodeSetStatus:function(b,c,d,e){function f(){var a=h.children?h.children[0]:null;if(a&&a.isStatusNode()){try{h.ul&&(h.ul.removeChild(a.li),a.li=null)}catch(b){}1===h.children.length?h.children=[]:h.children.shift()}}function g(b,c){var d=h.children?h.children[0]:null;return d&&d.isStatusNode()?(a.extend(d,b),i._callHook("nodeRenderTitle",d)):(b.key="_statusNode",h._setChildren([b]),h.children[0].statusNodeType=c,i.render()),h.children[0]}var h=b.node,i=b.tree;switch(c){case"ok":f(),h._isLoading=!1,h._error=null,h.renderStatus();break;case"loading":h.parent||g({title:i.options.strings.loading+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-wait"},c),h._isLoading=!0,h._error=null,h.renderStatus();break;case"error":g({title:i.options.strings.loadError+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-error"},c),h._isLoading=!1,h._error={message:d,details:e},h.renderStatus();break;default:a.error("invalid node status "+c)}},nodeToggleExpanded:function(a){return this.nodeSetExpanded(a,!a.node.expanded)},nodeToggleSelected:function(a){return this.nodeSetSelected(a,!a.node.selected)},treeClear:function(a){var b=a.tree;b.activeNode=null,b.focusNode=null,b.$div.find(">ul.fancytree-container").empty(),b.rootNode.children=null},treeCreate:function(){},treeDestroy:function(){this.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("ui-helper-hidden")},treeInit:function(a){this.treeLoad(a)},treeLoad:function(b,c){var d,e,f,g=b.tree,h=b.widget.element,i=a.extend({},b,{node:this.rootNode});if(g.rootNode.children&&this.treeClear(b),c=c||this.options.source)"string"==typeof c&&a.error("Not implemented");else switch(d=h.data("type")||"html"){case"html":e=h.find(">ul:first"),e.addClass("ui-fancytree-source ui-helper-hidden"),c=a.ui.fancytree.parseHtml(e),this.data=a.extend(this.data,n(e));break;case"json":c=a.parseJSON(h.text()),c.children&&(c.title&&(g.title=c.title),c=c.children);break;default:a.error("Invalid data-type: "+d)}return f=this.nodeLoadChildren(i,c).done(function(){g.render(),3===b.options.selectMode&&g.rootNode.fixSelection3FromEndNodes(),g.activeNode&&g.options.activeVisible&&g.activeNode.makeVisible(),g._triggerTreeEvent("init",null,{status:!0})}).fail(function(){g.render(),g._triggerTreeEvent("init",null,{status:!1})})},treeRegisterNode:function(){},treeSetFocus:function(a,b){b=b!==!1,b!==this.hasFocus()&&(this._hasFocus=b,!b&&this.focusNode&&this.focusNode.setFocus(!1),this.$container.toggleClass("fancytree-treefocus",b),this._triggerTreeEvent(b?"focusTree":"blurTree"))}}),a.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!1,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,debugLevel:null,disabled:!1,enableAspx:!0,extensions:[],toggleEffect:{effect:"blind",options:{direction:"vertical",scale:"box"},duration:200},generateIds:!1,icons:!0,idPrefix:"ft_",focusOnSelect:!1,keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,quicksearch:!1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading&#8230;",loadError:"Load error!"},tabbable:!0,titlesTabbable:!1,_classNames:{node:"fancytree-node",folder:"fancytree-folder",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",hasChildren:"fancytree-has-children",active:"fancytree-active",selected:"fancytree-selected",expanded:"fancytree-expanded",lazy:"fancytree-lazy",focused:"fancytree-focused",partsel:"fancytree-partsel",unselectable:"fancytree-unselectable",lastsib:"fancytree-lastsib",loading:"fancytree-loading",error:"fancytree-error"},lazyLoad:null,postProcess:null},_create:function(){this.tree=new r(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul:first");var b,c,f,g=this.options.extensions,h=this.tree;for(f=0;f<g.length;f++)c=g[f],b=a.ui.fancytree._extensions[c],b||a.error("Could not apply extension '"+c+"' (it is not registered, did you forget to include it?)"),this.tree.options[c]=a.extend(!0,{},b.options,this.tree.options[c]),e(this.tree.ext[c]===d,"Extension name must not exist as Fancytree.ext attribute: '"+c+"'"),this.tree.ext[c]={},j(this.tree,h,b,c),h=b;this.tree._callHook("treeCreate",this.tree)},_init:function(){this.tree._callHook("treeInit",this.tree),this._bind()},_setOption:function(b,c){var d=!0,e=!1;switch(b){case"aria":case"checkbox":case"icons":case"minExpandLevel":case"tabbable":this.tree._callHook("treeCreate",this.tree),e=!0;break;case"source":d=!1,this.tree._callHook("treeLoad",this.tree,c)}this.tree.debug("set option "+b+"="+c+" <"+typeof c+">"),d&&a.Widget.prototype._setOption.apply(this,arguments),e&&this.tree.render(!0,!1)},destroy:function(){this._unbind(),this.tree._callHook("treeDestroy",this.tree),a.Widget.prototype.destroy.call(this)},_unbind:function(){var b=this.tree._ns;this.element.unbind(b),this.tree.$container.unbind(b),a(c).unbind(b)},_bind:function(){var a=this,b=this.options,c=this.tree,d=c._ns;this._unbind(),c.$container.on("focusin"+d+" focusout"+d,function(a){var b=u.getNode(a),d="focusin"===a.type;b?c._callHook("nodeSetFocus",b,d):c._callHook("treeSetFocus",c,d)}).on("selectstart"+d,"span.fancytree-title",function(a){a.preventDefault()}).on("keydown"+d,function(a){if(b.disabled||b.keyboard===!1)return!0;var d,e=c.focusNode,f=c._makeHookContext(e||c,a),g=c.phase;try{return c.phase="userEvent",d=e?c._triggerNodeEvent("keydown",e,a):c._triggerTreeEvent("keydown",a),"preventNav"===d?d=!0:d!==!1&&(d=c._callHook("nodeKeydown",f)),d}finally{c.phase=g}}).on("click"+d+" dblclick"+d,function(c){if(b.disabled)return!0;var d,e=u.getEventTarget(c),f=e.node,g=a.tree,h=g.phase;if(!f)return!0;d=g._makeHookContext(f,c);try{switch(g.phase="userEvent",c.type){case"click":return d.targetType=e.type,g._triggerNodeEvent("click",d,c)===!1?!1:g._callHook("nodeClick",d);case"dblclick":return d.targetType=e.type,g._triggerNodeEvent("dblclick",d,c)===!1?!1:g._callHook("nodeDblclick",d)}}finally{g.phase=h}})},getActiveNode:function(){return this.tree.activeNode},getNodeByKey:function(a){return this.tree.getNodeByKey(a)},getRootNode:function(){return this.tree.rootNode},getTree:function(){return this.tree}}),u=a.ui.fancytree,a.extend(a.ui.fancytree,{version:"2.13.0",buildType: "production",debugLevel: 1,_nextId:1,_nextNodeKey:1,_extensions:{},_FancytreeClass:r,_FancytreeNodeClass:q,jquerySupports:{positionMyOfs:h(a.ui.version,1,9)},assert:function(a,b){return e(a,b)},debounce:function(a,b,c,d){var e;return 3===arguments.length&&"boolean"!=typeof c&&(d=c,c=!1),function(){var f=arguments;d=d||this,c&&!e&&b.apply(d,f),clearTimeout(e),e=setTimeout(function(){c||b.apply(d,f),e=null},a)}},debug:function(){a.ui.fancytree.debugLevel>=2&&f("log",arguments)},error:function(){f("error",arguments)},escapeHtml:function(a){return(""+a).replace(/[&<>"'\/]/g,function(a){return v[a]})},fixPositionOptions:function(b){if((b.offset||(""+b.my+b.at).indexOf("%")>=0)&&a.error("expected new position syntax (but '%' is not supported)"),!a.ui.fancytree.jquerySupports.positionMyOfs){var c=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(b.my),d=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(b.at),e=(c[2]?+c[2]:0)+(d[2]?+d[2]:0),f=(c[4]?+c[4]:0)+(d[4]?+d[4]:0);b=a.extend({},b,{my:c[1]+" "+c[3],at:d[1]+" "+d[3]}),(e||f)&&(b.offset=""+e+" "+f)}return b},getEventTargetType:function(a){return this.getEventTarget(a).type},getEventTarget:function(b){var c=b&&b.target?b.target.className:"",e={node:this.getNode(b.target),type:d};return/\bfancytree-title\b/.test(c)?e.type="title":/\bfancytree-expander\b/.test(c)?e.type=e.node.hasChildren()===!1?"prefix":"expander":/\bfancytree-checkbox\b/.test(c)||/\bfancytree-radio\b/.test(c)?e.type="checkbox":/\bfancytree-icon\b/.test(c)?e.type="icon":/\bfancytree-node\b/.test(c)?e.type="title":b&&b.target&&a(b.target).closest(".fancytree-title").length&&(e.type="title"),e},getNode:function(a){if(a instanceof q)return a;for(a.selector!==d?a=a[0]:a.originalEvent!==d&&(a=a.target);a;){if(a.ftnode)return a.ftnode;a=a.parentNode}return null},getTree:function(b){var c;return b instanceof r?b:(b===d&&(b=0),"number"==typeof b?b=a(".fancytree-container").eq(b):"string"==typeof b?b=a(b).eq(0):b.selector!==d?b=b.eq(0):b.originalEvent!==d&&(b=a(b.target)),b=b.closest(":ui-fancytree"),c=b.data("ui-fancytree")||b.data("fancytree"),c?c.tree:null)},info:function(){a.ui.fancytree.debugLevel>=1&&f("info",arguments)},eventToString:function(a){var b=a.which,c=a.type,d=[];return a.altKey&&d.push("alt"),a.ctrlKey&&d.push("ctrl"),a.metaKey&&d.push("meta"),a.shiftKey&&d.push("shift"),"click"===c||"dblclick"===c?d.push(y[a.button]+c):w[b]||d.push(x[b]||String.fromCharCode(b).toLowerCase()),d.join("+")},keyEventToString:function(a){return this.warn("keyEventToString() is deprecated: use eventToString()"),this.eventToString(a)},parseHtml:function(b){var c,e,f,g,h,i,j,k,l=b.find(">li"),m=[];return l.each(function(){var l,o,p=a(this),q=p.find(">span:first",this),r=q.length?null:p.find(">a:first"),s={tooltip:null,data:{}};for(q.length?s.title=q.html():r&&r.length?(s.title=r.html(),s.data.href=r.attr("href"),s.data.target=r.attr("target"),s.tooltip=r.attr("title")):(s.title=p.html(),h=s.title.search(/<ul/i),h>=0&&(s.title=s.title.substring(0,h))),s.title=a.trim(s.title),g=0,i=z.length;i>g;g++)s[z[g]]=d;for(c=this.className.split(" "),f=[],g=0,i=c.length;i>g;g++)e=c[g],A[e]?s[e]=!0:f.push(e);if(s.extraClasses=f.join(" "),j=p.attr("title"),j&&(s.tooltip=j),j=p.attr("id"),j&&(s.key=j),l=n(p),l&&!a.isEmptyObject(l)){for(o in D)l.hasOwnProperty(o)&&(l[D[o]]=l[o],delete l[o]);for(g=0,i=B.length;i>g;g++)j=B[g],k=l[j],null!=k&&(delete l[j],s[j]=k);a.extend(s.data,l)}b=p.find(">ul:first"),s.children=b.length?a.ui.fancytree.parseHtml(b):s.lazy?d:null,m.push(s)}),m},registerExtension:function(b){e(null!=b.name,"extensions must have a `name` property."),e(null!=b.version,"extensions must have a `version` property."),a.ui.fancytree._extensions[b.name]=b},unescapeHtml:function(a){var b=c.createElement("div");return b.innerHTML=a,0===b.childNodes.length?"":b.childNodes[0].nodeValue},warn:function(){f("warn",arguments)}})}(jQuery,window,document);
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.css
new file mode 100644
index 00000000000..58eab4630eb
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.css
@@ -0,0 +1,361 @@
+/*!
+ * Fancytree "awesome" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0em 0em;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 1em;
+  height: 1em;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-position: 0em 0em;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 0px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 0.5em;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 1em;
+  height: 1em;
+  margin-left: 0.5em;
+  margin-top: 0px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 0.5em;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 0.5em;
+}
+/* Documents */
+/* Folders */
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url("loading.gif");
+}
+/* Status node icons */
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 1em;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 1em;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 0.5em;
+  border: 1px solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 2em;
+  position: absolute;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 4em;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0em 0em;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+ul.fancytree-container ul {
+  padding: 0.3em 0 0 1em;
+  margin: 0;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.less
new file mode 100644
index 00000000000..f2b48163134
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.less
@@ -0,0 +1,53 @@
+/*!
+ * Fancytree "awesome" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Borders have NO radius and NO gradients are used!
+
+// both:
+//    unselected background: white
+//    hover bar (unselected, inactive): #E5F3FB (border: #70C0E7) 'very light blue'
+//    active node: #CBE8F6 (border: #26A0DA)  'light blue'
+//    active node with hover: wie active node
+
+// Tree view:
+//    active node, tree inactive: #F7F7F7 (border: #DEDEDE) 'light gray, selected, but tree not active'
+
+// List view: 
+//    selected bar: --> active bar
+//    focus  bar: transparent(white) + border 1px solid #3399FF  ()
+
+//    table left/right border: #EDEDED 'light gray'
+
+// local vars
+@fancy-my-icon-size: 16px;
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: false;     // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: true;
+
+@fancy-icon-width: 1em;
+@fancy-icon-height: 1em;
+@fancy-line-height: 1em;
+@fancy-icon-spacing: 0.5em;
+
+ul.fancytree-container ul
+{
+	padding: 0.3em 0 0 1em;
+	margin: 0;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.min.css
new file mode 100644
index 00000000000..2fcc7174281
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-awesome/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "awesome" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:1em;height:1em;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:left;background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:0}span.fancytree-custom-icon{display:inline-block;margin-left:.5em}img.fancytree-icon{width:1em;height:1em;margin-left:.5em;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}span.fancytree-checkbox{margin-left:.5em}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}span.fancytree-icon{margin-left:.5em}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(loading.gif)}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:1em}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:1em;padding:0 3px;margin:0 0 0 .5em;border:1px solid transparent;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}#fancytree-drop-marker{width:2em;position:absolute;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:4em}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-container ul{padding:.3em 0 0 1em;margin:0}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.css
new file mode 100644
index 00000000000..54beaa42986
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.css
@@ -0,0 +1,441 @@
+/*!
+ * Fancytree "bootstrap" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0em 0em;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 1em;
+  height: 1em;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-position: 0em 0em;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 0px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 0.5em;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 1em;
+  height: 1em;
+  margin-left: 0.5em;
+  margin-top: 0px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 0.5em;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 0.5em;
+}
+/* Documents */
+/* Folders */
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url("loading.gif");
+}
+/* Status node icons */
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 1em;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 1em;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 0.5em;
+  border: 1px solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 2em;
+  position: absolute;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 4em;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0em 0em;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+ul.fancytree-container ul {
+  padding: 0 0 0 1.5em;
+  margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+  outline: none;
+}
+span.fancytree-node {
+  border: 1px solid transparent;
+  border-radius: 3px;
+  padding-left: 8px;
+}
+span.fancytree-title {
+  border-radius: 3px;
+}
+span.fancytree-node.fancytree-selected {
+  background-color: #80c780;
+  border-color: #80c780;
+}
+span.fancytree-node.fancytree-selected span.fancytree-title {
+  background-color: #80c780;
+}
+span.fancytree-node.fancytree-active {
+  background-color: #6aa3d5;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node:hover {
+  background-color: #e9f2f9;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused {
+  border-color: #428bca;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected {
+  background-color: #5cb85c;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title {
+  background-color: #5cb85c;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active {
+  background-color: #428bca;
+  border-color: #428bca;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+  border: 1px solid #eeeeee;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  background-color: #80c780;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-node {
+  background-color: #80c780;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-title {
+  background-color: #80c780;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+  background-color: #6aa3d5;
+}
+table.fancytree-ext-table tbody tr.fancytree-active span.fancytree-node {
+  background-color: #6aa3d5;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr:hover {
+  background-color: #e9f2f9;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-focused span.fancytree-title {
+  outline: 1px dotted #428bca;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+  background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-node {
+  background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-title {
+  background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+  background-color: #428bca;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active span.fancytree-node {
+  background-color: #428bca;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.less
new file mode 100644
index 00000000000..6871248db6c
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.less
@@ -0,0 +1,173 @@
+/*!
+ * Fancytree "bootstrap" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+
+// local vars
+@fancy-my-icon-size: 16px;
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: false;  // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: true;
+
+@fancy-icon-width: 1em;
+@fancy-icon-height: 1em;
+@fancy-line-height: 1em;
+@fancy-icon-spacing: 0.5em;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS 
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+
+ul.fancytree-container ul {
+	padding: 0 0 0 1.5em;
+	margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+	outline: none; 
+}
+ 
+/////
+// Original bootstrap colors (http://getbootstrap.com/css/#responsive-utilities)
+@gray-darker:  lighten(#000, 13.5%); // #222
+@gray-dark:    lighten(#000, 20%);   // #333
+@gray:         lighten(#000, 33.5%); // #555
+@gray-light:   lighten(#000, 60%);   // #999
+@gray-lighter: lighten(#000, 93.5%); // #eee
+
+@brand-primary: #428bca;  // blue
+@brand-success: #5cb85c;  // green
+@brand-info:    #5bc0de;  // light blue
+@brand-warning: #f0ad4e;  // orange
+@brand-danger:  #d9534f;  // red
+
+@border-radius-base:  4px;
+@border-radius-large: 6px;
+@border-radius-small: 3px;
+/////////////
+
+span.fancytree-node {
+	border: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover
+	border-radius: @border-radius-small;
+	padding-left: 8px;
+}
+span.fancytree-title {
+	border-radius: @border-radius-small;
+}
+// Inactive tree:
+span.fancytree-node.fancytree-selected { // selected nodes inside inactive tree
+	background-color: lighten(@brand-success, 10%);
+	border-color: lighten(@brand-success, 10%);
+	span.fancytree-title {
+		background-color: lighten(@brand-success, 10%); // green title, even when active
+	}
+}
+span.fancytree-node.fancytree-active { // active nodes inside inactive tree
+	background-color: lighten(@brand-primary, 10%);
+}
+// Active tree:
+.fancytree-container.fancytree-treefocus {
+	span.fancytree-node:hover {
+		background-color: lighten(@brand-primary, 42%);
+	}
+	span.fancytree-node.fancytree-focused {
+		border-color: @brand-primary;
+	}
+	span.fancytree-node.fancytree-selected {
+		background-color: @brand-success;
+		span.fancytree-title {
+			background-color: @brand-success; // green title, even when active
+		}
+	}
+	span.fancytree-node.fancytree-active {
+		background-color: @brand-primary;
+		border-color: @brand-primary;
+	}
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody {
+	tr td {
+	  border: 1px solid @gray-lighter;
+	}
+	// span.fancytree-node,
+	// span.fancytree-node:hover { // undo standard tree css
+	// 	border: none;
+	// 	background: none;
+	// }
+	// // Title get's a white background, when hovered. Undo standard node formatting
+	// span.fancytree-title:hover {
+	//   border: none;
+	//   background: inherit;
+	//   background: transparent;
+	//   background: none;
+	//   filter: none;
+	// }
+	// dimmed, if inside inactive tree
+	tr.fancytree-selected {  
+		background-color: lighten(@brand-success, 10%);
+		span.fancytree-node {
+			background-color: lighten(@brand-success, 10%);
+		}
+		span.fancytree-title {
+			background-color: lighten(@brand-success, 10%); // green title, even when active
+		}
+	}
+	tr.fancytree-active {  // dimmed, if inside inactive tree
+		background-color: lighten(@brand-primary, 10%);
+		span.fancytree-node {
+			background-color: lighten(@brand-primary, 10%);
+		}
+	}
+}
+
+table.fancytree-ext-table.fancytree-treefocus tbody {
+	tr:hover  {
+		background-color: lighten(@brand-primary, 42%);
+	    // outline: 1px solid @brand-primary;
+	}
+	tr.fancytree-focused span.fancytree-title {
+		outline: 1px dotted @brand-primary;
+	}
+	tr.fancytree-active:hover,
+	tr.fancytree-selected:hover {
+		// background-color: #CBE8F6;
+	 //    outline: 1px solid #26A0DA;
+	}
+	tr.fancytree-selected {
+		background-color: @brand-success;
+		span.fancytree-node {
+			background-color: @brand-success;
+		}
+		span.fancytree-title {
+			background-color: @brand-success; // green title, even when active
+		}
+	}
+	tr.fancytree-active {
+		background-color: @brand-primary;
+		span.fancytree-node {
+			background-color: @brand-primary;
+		}
+	}
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.min.css
new file mode 100644
index 00000000000..ba00e2a31c1
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap-n/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "bootstrap" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:1em;height:1em;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:left;background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:0}span.fancytree-custom-icon{display:inline-block;margin-left:.5em}img.fancytree-icon{width:1em;height:1em;margin-left:.5em;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}span.fancytree-checkbox{margin-left:.5em}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}span.fancytree-icon{margin-left:.5em}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(loading.gif)}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:1em}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:1em;padding:0 3px;margin:0 0 0 .5em;border:1px solid transparent;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}#fancytree-drop-marker{width:2em;position:absolute;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:4em}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-container ul{padding:0 0 0 1.5em;margin:0}.fancytree-container:focus{outline:0}span.fancytree-node{border:1px solid transparent;border-radius:3px;padding-left:8px}span.fancytree-title{border-radius:3px}span.fancytree-node.fancytree-selected{background-color:#80c780;border-color:#80c780}span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#80c780}span.fancytree-node.fancytree-active{background-color:#6aa3d5}.fancytree-container.fancytree-treefocus span.fancytree-node:hover{background-color:#e9f2f9}.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused{border-color:#428bca}.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected,.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#5cb85c}.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active{background-color:#428bca;border-color:#428bca}table.fancytree-ext-table tbody tr td{border:1px solid #eee}table.fancytree-ext-table tbody tr.fancytree-selected,table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-node,table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-title{background-color:#80c780}table.fancytree-ext-table tbody tr.fancytree-active,table.fancytree-ext-table tbody tr.fancytree-active span.fancytree-node{background-color:#6aa3d5}table.fancytree-ext-table.fancytree-treefocus tbody tr:hover{background-color:#e9f2f9}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted #428bca}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected,table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-node,table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-title{background-color:#5cb85c}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active,table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active span.fancytree-node{background-color:#428bca}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.css
new file mode 100644
index 00000000000..487a0ee05e3
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.css
@@ -0,0 +1,492 @@
+/*!
+ * Fancytree "bootstrap" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0em 0em;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 1em;
+  height: 1em;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-position: 0em 0em;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 2px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 0.5em;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 1em;
+  height: 1em;
+  margin-left: 0.5em;
+  margin-top: 2px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 0.5em;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 0.5em;
+}
+/* Documents */
+/* Folders */
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: none;
+}
+/* Status node icons */
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 0px;
+  min-height: 1em;
+}
+span.fancytree-title {
+  color: #333333;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 1em;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 0.5em;
+  border: 1px solid transparent;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  -ms-border-radius: 3px;
+  -o-border-radius: 3px;
+  border-radius: 3px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #d9534f;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 2em;
+  position: absolute;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 4em;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0em 0em;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #333333;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #333333;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Plain tree
+ * Modifier classes on <ul> container:
+ * table-hover                : Enable a light mouse hover effect
+ * fancytree-colorize-selected: Give selected (checked) rows a color
+ */
+ul.fancytree-container ul {
+  padding: 0 0 0 1.5em;
+  margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+  outline: none;
+}
+.fancytree-container .fancytree-active span.fancytree-title input,
+.fancytree-container.fancytree-colorize-selected .fancytree-selected span.fancytree-title input {
+  color: black;
+}
+div.fancytree-drag-helper.fancytree-drop-reject,
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-title {
+  color: #d9534f;
+}
+span.fancytree-node.fancytree-drag-source {
+  background-color: #5bc0de !important;
+}
+span.fancytree-node.fancytree-drop-target.fancytree-drop-reject span.fancytree.title {
+  background-color: #d9534f !important;
+}
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected,
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected span.fancytree-title {
+  background-color: #80c780;
+  border-color: #80c780;
+  color: #ffffff;
+}
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+  background-color: #6ec06e;
+}
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title {
+  color: #80c780;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-title:hover {
+  background-color: #f5f5f5;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title {
+  background-color: #5cb85c;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+  background-color: #4cae4c;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title {
+  color: #5cb85c;
+}
+.fancytree-plain.fancytree-container span.fancytree-node {
+  margin-top: 2px;
+  margin-bottom: 2px;
+}
+.fancytree-plain.fancytree-container span.fancytree-title {
+  border: 1px solid transparent;
+  border-radius: 3px;
+  outline-radius: 3px;
+}
+.fancytree-plain.fancytree-container span.fancytree-title:hover {
+  background-color: #f5f5f5;
+}
+.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active span.fancytree-title {
+  background-color: #5094ce;
+  color: #ffffff;
+}
+.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active:hover span.fancytree-title {
+  background-color: #3c87c8;
+}
+.fancytree-plain.fancytree-container.fancytree-ext-wide span.fancytree-node.fancytree-active {
+  color: #ffffff;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused span.fancytree-title {
+  border-color: #337ab7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active span.fancytree-title {
+  background-color: #337ab7;
+  border-color: #337ab7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active:hover span.fancytree-title {
+  background-color: #2e6da4;
+}
+/*******************************************************************************
+ * 'table' extension
+ * Modifier classes on <table>:
+ * table-hover                : Enable a light mouse hover effect
+ * fancytree-colorize-selected: Give selected (checked) rows a color
+ */
+table.fancytree-ext-table > tbody > tr > td span.fancytree-title {
+  border: none;
+}
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-selected > td {
+  background-color: #80c780;
+}
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-selected > td,
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-selected > td span.fancytree-title {
+  color: #ffffff;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus > tbody > tr.fancytree-selected > td {
+  background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.table-hover > tbody > tr.fancytree-selected:hover > td {
+  background-color: #6ec06e;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover > tbody > tr.fancytree-selected:hover > td {
+  background-color: #4cae4c;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover > tbody > tr.fancytree-selected.fancytree-active:hover > td,
+table.fancytree-ext-table.fancytree-colorize-selected.table-hover > tbody > tr.fancytree-selected.fancytree-active:hover > td {
+  background-color: #2e6da4;
+}
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-active.fancytree-selected {
+  outline-width: 2px;
+  outline-offset: -2px;
+  outline-style: solid;
+  outline-color: #80c780;
+}
+table.fancytree-ext-table.fancytree-container > tbody > tr.fancytree-active > td {
+  background-color: #5094ce;
+}
+table.fancytree-ext-table.fancytree-container > tbody > tr.fancytree-active > td,
+table.fancytree-ext-table.fancytree-container > tbody > tr.fancytree-active > td span.fancytree-title {
+  color: #ffffff;
+}
+table.fancytree-ext-table.fancytree-treefocus.fancytree-container > tbody > tr.fancytree-focused span.fancytree-title {
+  outline: 1px dotted #000;
+}
+table.fancytree-ext-table.fancytree-treefocus.fancytree-container > tbody > tr.fancytree-active > td {
+  background-color: #337ab7;
+}
+table.fancytree-ext-table.fancytree-treefocus.fancytree-container.table-hover > tbody > tr.fancytree-active:hover > td {
+  background-color: #2e6da4;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.less
new file mode 100644
index 00000000000..b5857532892
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.less
@@ -0,0 +1,333 @@
+/*!
+ * Fancytree "bootstrap" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+
+// local vars
+// @fancy-my-icon-size: 16px;
+
+//------------------------------------------------------------------------------
+// Original bootstrap colors 
+// See http://getbootstrap.com/css/#less-variables-colors and
+//     https://github.com/twbs/bootstrap/blob/master/less/variables.less
+@gray-base:              #000;
+@gray-darker:            lighten(@gray-base, 13.5%); // #222
+@gray-dark:              lighten(@gray-base, 20%);   // #333
+@gray:                   lighten(@gray-base, 33.5%); // #555
+@gray-light:             lighten(@gray-base, 46.7%); // #777
+@gray-lighter:           lighten(@gray-base, 93.5%); // #eee
+
+@brand-primary:         darken(#428bca, 6.5%); // blue,  #337ab7
+@brand-success:         #5cb85c;  // green
+@brand-info:            #5bc0de;  // light blue
+@brand-warning:         #f0ad4e;  // orange
+@brand-danger:          #d9534f;  // red
+
+@font-family-sans-serif:  "Helvetica Neue", Helvetica, Arial, sans-serif;
+@font-family-serif:       Georgia, "Times New Roman", Times, serif;
+//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
+@font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace;
+@font-family-base:        @font-family-sans-serif;
+
+@font-size-base:          14px;
+@font-size-large:         ceil((@font-size-base * 1.25)); // ~18px
+@font-size-small:         ceil((@font-size-base * 0.85)); // ~12px
+
+@border-radius-base:  4px;
+@border-radius-large: 6px;
+@border-radius-small: 3px;
+
+@text-color: @gray-dark;
+//** Default background color used for all tables.
+@table-bg:                      transparent;
+//** Background color used for `.table-striped`.
+@table-bg-accent:               #f9f9f9;
+//** Background color used for `.table-hover`.
+@table-bg-hover:                #f5f5f5;
+@table-bg-active:               @table-bg-hover;
+
+//** Border color for table and cell borders.
+@table-border-color:            #ddd;
+
+//------------------------------------------------------------------------------
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: false;     // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: true;
+@fancy-loading-url: none;
+
+@fancy-line-height: 1em;       // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 0px;    // gap between two node borders
+@fancy-icon-width: 1em;
+@fancy-icon-height: 1em;
+@fancy-icon-spacing: 0.5em;    // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 2px;      // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px;     // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: @border-radius-small;
+@fancy-node-outline-width: 1px;
+
+@fancy-font-family: @font-family-base;
+@fancy-font-size: @font-size-base;
+@fancy-font-color: @text-color;
+@fancy-font-color-dimm: @gray-dark;
+@fancy-font-error-color: @brand-danger;
+
+@fancy-active-text: #fff;
+@fancy-active-color: @brand-primary;
+@fancy-select-color: @brand-success;
+@fancy-hover-color: @table-bg-hover;
+
+/*******************************************************************************
+ * Plain tree
+ * Modifier classes on <ul> container:
+ * table-hover                : Enable a light mouse hover effect
+ * fancytree-colorize-selected: Give selected (checked) rows a color
+ */
+ul.fancytree-container ul {
+	padding: 0 0 0 1.5em;
+	margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+	outline: none; 
+}
+
+// Active and (optionally) selected nodes are white on colored bg. Undo this for input controls:
+.fancytree-container .fancytree-active span.fancytree-title input,
+.fancytree-container.fancytree-colorize-selected .fancytree-selected span.fancytree-title input  {
+  color: black;
+}
+
+// ------------------------------------------------------------------------------
+//  * Drag'n'drop support
+//  *----------------------------------------------------------------------------
+// div.fancytree-drag-helper {
+// }
+// div.fancytree-drag-helper a {
+// 	border: 1px solid gray;
+// 	background-color: white;
+// 	padding-left: 5px;
+// 	padding-right: 5px;
+// 	opacity: 0.8;
+// }
+// span.fancytree-drag-helper-img {
+// // position: relative;
+// // left: -16px;
+// }
+div.fancytree-drag-helper.fancytree-drop-reject,
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-title
+{
+	color: @fancy-font-error-color;
+}
+// div.fancytree-drop-accept span.fancytree-drag-helper-img {
+// 	.useSprite(2, 7);
+// }
+// div.fancytree-drop-reject span.fancytree-drag-helper-img {
+// 	.useSprite(1, 7);
+// }
+
+// //--- Drop marker icon ---------------------------------------------------------
+// #fancytree-drop-marker {
+// 	width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// 	position: absolute;
+// 	.useSprite(0, 8);
+// 	margin: 0;
+// 	&.fancytree-drop-after,
+// 	&.fancytree-drop-before {
+// 		width: 4 * @fancy-icon-width; // 64px;
+// 		.useSprite(0, 9);
+// 	}
+// 	&.fancytree-drop-copy {
+// 		.useSprite(4, 8);
+// 	}
+// 	&.fancytree-drop-move {
+// 		.useSprite(2, 8);
+// 	}
+// }
+
+//--- Source node while dragging -----------------------------------------------
+
+span.fancytree-node.fancytree-drag-source {
+	background-color: @brand-info !important;
+	span.fancytree.title {
+		// outline: 1px solid @brand-info;
+		// color: @brand-primary;
+	}
+}
+
+//--- Target node while dragging cursor is over it -----------------------------
+
+span.fancytree-node.fancytree-drop-target {
+	&.fancytree-drop-accept span.fancytree.title {
+		// background-color: @brand-danger !important;
+		// outline: 1px solid @brand-success;
+		// color: white !important;
+	}
+	&.fancytree-drop-reject span.fancytree.title {
+		background-color: @brand-danger !important;
+		// outline: 1px solid @brand-danger;
+		// color: white !important;
+	}
+}
+
+// Inactive tree:
+.fancytree-plain {
+	&.fancytree-colorize-selected {
+		span.fancytree-node.fancytree-selected,
+		span.fancytree-node.fancytree-selected span.fancytree-title { // selected nodes inside inactive tree
+			background-color: lighten(@fancy-select-color, 10%);
+			border-color: lighten(@fancy-select-color, 10%);
+			color: @fancy-active-text;
+		}
+		span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+			background-color: lighten(@fancy-select-color, 5%);
+		}
+		span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title { // active nodes inside inactive tree
+			color: lighten(@fancy-select-color, 10%);
+		}
+		&.fancytree-treefocus {
+			span.fancytree-title:hover {
+				background-color: @fancy-hover-color;
+			}
+			span.fancytree-node.fancytree-selected span.fancytree-title {
+				background-color: @fancy-select-color;
+			}
+			span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+				background-color: darken(@fancy-select-color, 5%);
+			}
+			span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title {
+				color: @fancy-select-color;
+			}
+		}
+	}
+
+	&.fancytree-container {  // adding this class to increase specificity, so we can override .fancytree-colorize-selected
+		span.fancytree-node {
+			margin-top: 2px;
+			margin-bottom: 2px;
+		}
+		span.fancytree-title {
+			border: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover
+			border-radius: @border-radius-small;
+			outline-radius: @border-radius-small;
+		}
+		span.fancytree-title:hover {
+			background-color: @fancy-hover-color;
+		}
+		span.fancytree-node.fancytree-active span.fancytree-title { // active nodes inside inactive tree
+			background-color: lighten(@fancy-active-color, 10%);
+			color: @fancy-active-text;
+		}
+		span.fancytree-node.fancytree-active:hover span.fancytree-title {
+			background-color: lighten(@fancy-active-color, 5%);
+		}
+		&.fancytree-ext-wide span.fancytree-node.fancytree-active { // in wide mode, icons of active nodes must be white-on-color
+			color: @fancy-active-text;
+		}
+
+		// Active tree:
+		&.fancytree-treefocus {
+			span.fancytree-node.fancytree-focused span.fancytree-title {
+				border-color: @brand-primary;
+			}
+			span.fancytree-node.fancytree-active span.fancytree-title {
+				background-color: @fancy-active-color;
+				border-color: @fancy-active-color;
+			}
+			span.fancytree-node.fancytree-active:hover span.fancytree-title {
+				background-color: darken(@fancy-active-color, 5%);
+			}
+		}
+	}
+}
+
+/*******************************************************************************
+ * 'table' extension
+ * Modifier classes on <table>:
+ * table-hover                : Enable a light mouse hover effect
+ * fancytree-colorize-selected: Give selected (checked) rows a color
+ */
+table.fancytree-ext-table {
+	>tbody >tr >td span.fancytree-title {
+		border: none;
+	}
+
+	// Give a separate color for selected (checked) rows
+	// Define *before* the .fancytree-active rules, because active color should
+	// override selected color.
+	&.fancytree-colorize-selected {
+		>tbody >tr.fancytree-selected >td {
+			// dimmed, if inside inactive tree
+			background-color: lighten(@fancy-select-color, 10%);
+			// white text for selected nodes
+			&,
+			span.fancytree-title {
+				color: @fancy-active-text;
+			}
+		}
+		&.fancytree-treefocus >tbody >tr.fancytree-selected >td {
+			background-color: @fancy-select-color;
+		}
+		&.table-hover >tbody >tr.fancytree-selected:hover >td { 
+			// dimmed, if inside inactive tree
+			background-color: lighten(@fancy-select-color, 5%);
+		}
+		&.fancytree-treefocus.table-hover >tbody >tr.fancytree-selected:hover >td {
+			background-color: darken(@fancy-select-color, 5%);
+		}
+		&.fancytree-treefocus.table-hover >tbody >tr.fancytree-selected.fancytree-active:hover >td,
+		&.table-hover >tbody >tr.fancytree-selected.fancytree-active:hover >td {
+			background-color: darken(@fancy-active-color, 5%);
+		}
+		>tbody >tr.fancytree-active.fancytree-selected  {
+			outline-width: 2px;
+			outline-offset: -2px;
+			outline-style: solid;
+			outline-color: lighten(@fancy-select-color, 10%);
+		}
+	}
+
+	// General tree (slightly dimmed, since we also define colors for inactive 
+	// mode here). 
+
+	&.fancytree-container >tbody >tr.fancytree-active >td {
+		background-color: lighten(@fancy-active-color, 10%);
+		// white text for selected nodes
+		&,
+		span.fancytree-title {
+			color: @fancy-active-text;
+		}
+	}
+
+	// Reset to standard colors if tree has keyboard focus.
+	// We add .fancytree-container to increase specificity, so we can override
+	// .fancytree-colorize-selected defined above
+	
+	&.fancytree-treefocus.fancytree-container {
+		>tbody >tr.fancytree-focused span.fancytree-title {
+			outline: 1px dotted #000;
+		}
+		>tbody >tr.fancytree-active >td {
+			background-color: @fancy-active-color;
+		}
+		&.table-hover >tbody >tr.fancytree-active:hover >td {
+			background-color: darken(@fancy-active-color, 5%);
+		}
+	}
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.min.css
new file mode 100644
index 00000000000..8d7e4dd622e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-bootstrap/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "bootstrap" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:1em;height:1em;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:left;background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:2px}span.fancytree-custom-icon{display:inline-block;margin-left:.5em}img.fancytree-icon{width:1em;height:1em;margin-left:.5em;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}span.fancytree-checkbox{margin-left:.5em}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}span.fancytree-icon{margin-left:.5em}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:none}span.fancytree-node{display:inherit;width:100%;margin-top:0;min-height:1em}span.fancytree-title{color:#333;cursor:pointer;display:inline-block;vertical-align:top;min-height:1em;padding:0 3px;margin:0 0 0 .5em;border:1px solid transparent;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}span.fancytree-node.fancytree-error span.fancytree-title{color:#d9534f}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}#fancytree-drop-marker{width:2em;position:absolute;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:4em}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:#333;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:#333;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-container ul{padding:0 0 0 1.5em;margin:0}.fancytree-container:focus{outline:0}.fancytree-container .fancytree-active span.fancytree-title input,.fancytree-container.fancytree-colorize-selected .fancytree-selected span.fancytree-title input{color:#000}div.fancytree-drag-helper.fancytree-drop-reject,div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-title{color:#d9534f}span.fancytree-node.fancytree-drag-source{background-color:#5bc0de!important}span.fancytree-node.fancytree-drop-target.fancytree-drop-reject span.fancytree.title{background-color:#d9534f!important}.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected,.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#80c780;border-color:#80c780;color:#fff}.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected:hover span.fancytree-title{background-color:#6ec06e}.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title{color:#80c780}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-title:hover{background-color:#f5f5f5}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#5cb85c}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected:hover span.fancytree-title{background-color:#4cae4c}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title{color:#5cb85c}.fancytree-plain.fancytree-container span.fancytree-node{margin-top:2px;margin-bottom:2px}.fancytree-plain.fancytree-container span.fancytree-title{border:1px solid transparent;border-radius:3px;outline-radius:3px}.fancytree-plain.fancytree-container span.fancytree-title:hover{background-color:#f5f5f5}.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active span.fancytree-title{background-color:#5094ce;color:#fff}.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active:hover span.fancytree-title{background-color:#3c87c8}.fancytree-plain.fancytree-container.fancytree-ext-wide span.fancytree-node.fancytree-active{color:#fff}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused span.fancytree-title{border-color:#337ab7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active span.fancytree-title{background-color:#337ab7;border-color:#337ab7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active:hover span.fancytree-title{background-color:#2e6da4}table.fancytree-ext-table>tbody>tr>td span.fancytree-title{border:0}table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-selected>td{background-color:#80c780}table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-selected>td,table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-selected>td span.fancytree-title{color:#fff}table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus>tbody>tr.fancytree-selected>td{background-color:#5cb85c}table.fancytree-ext-table.fancytree-colorize-selected.table-hover>tbody>tr.fancytree-selected:hover>td{background-color:#6ec06e}table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover>tbody>tr.fancytree-selected:hover>td{background-color:#4cae4c}table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover>tbody>tr.fancytree-selected.fancytree-active:hover>td,table.fancytree-ext-table.fancytree-colorize-selected.table-hover>tbody>tr.fancytree-selected.fancytree-active:hover>td{background-color:#2e6da4}table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-active.fancytree-selected{outline-width:2px;outline-offset:-2px;outline-style:solid;outline-color:#80c780}table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td{background-color:#5094ce}table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td,table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td span.fancytree-title{color:#fff}table.fancytree-ext-table.fancytree-treefocus.fancytree-container>tbody>tr.fancytree-focused span.fancytree-title{outline:1px dotted #000}table.fancytree-ext-table.fancytree-treefocus.fancytree-container>tbody>tr.fancytree-active>td{background-color:#337ab7}table.fancytree-ext-table.fancytree-treefocus.fancytree-container.table-hover>tbody>tr.fancytree-active:hover>td{background-color:#2e6da4}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-common.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-common.less
new file mode 100644
index 00000000000..1275f503157
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-common.less
@@ -0,0 +1,685 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true;      // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: true;  // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px;      // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px;    // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px;      // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px;      // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px;     // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+@fancy-image-dir: ".";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+@fancy-loading-url: url("@{fancy-image-dir}/loading.gif");
+// @fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false;
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: silver;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond){
+	background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond){
+	background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+	background-image: url("@{fancy-image-dir}/@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+	background-image: data-uri("@{fancy-image-dir}/@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites){
+	.setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+  -webkit-border-radius: @radius;
+  -moz-border-radius: @radius;
+  -ms-border-radius: @radius;
+  -o-border-radius: @radius;
+  border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor){
+	border-color: @bordercolor;
+	background: @bgcolor;
+	color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor){
+	.spanStyleMixin(@color, @bgcolor, @bordercolor);
+	// @c-start: argb(@startColor);
+	// @c-end: argb(@stopColor);
+	background: -moz-linear-gradient(top, @startColor 0%, @stopColor 100%); // FF3.6+
+	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@startColor), color-stop(100%,@stopColor)); // Chrome,Safari4+
+	background: -webkit-linear-gradient(top, @startColor 0%,@stopColor 100%); // Chrome10+,Safari5.1+
+	background: -o-linear-gradient(top, @startColor 0%,@stopColor 100%); // Opera 11.10+
+	background: -ms-linear-gradient(top, @startColor 0%,@stopColor 100%); // IE10+
+	background: linear-gradient(to bottom, @startColor 0%,@stopColor 100%); // W3C
+	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+.ui-helper-hidden { 
+	display: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+	font-family: @fancy-font-family;
+	font-size: @fancy-font-size;
+	white-space: nowrap;
+	padding: 3px;
+	margin: 0; // DT issue 201
+	background-color: white;
+	border: 1px dotted gray;
+	overflow: auto;
+//	height: 100%; // DT issue 263, 470
+	min-height: 0%; // #192
+	position: relative; // #235
+	ul {
+		padding: 0 0 0 @fancy-level-indent;
+		margin: 0;
+	}
+	li {
+		list-style-image: none;
+		list-style-position: outside;
+		list-style-type: none;
+		-moz-background-clip: border;
+		-moz-background-inline-policy: continuous;
+		-moz-background-origin: padding;
+		background-attachment: scroll;
+		background-color: transparent;
+		.setBgPos(0, 0);
+		background-repeat: repeat-y;
+		background-image: none;  // no v-lines
+
+		margin: 0;
+//		padding: 1px 0 0 0; // issue #246
+	}
+	// Suppress lines for last child node
+	li.fancytree-lastsib {
+		background-image: none;
+	}
+}
+
+// Suppress lines if level is fixed expanded (option minExpandLevel) 
+ul.fancytree-no-connector > li {
+	background-image: none;
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+	opacity: 0.5;
+//	filter: alpha(opacity=50); // Yields a css warning 
+	background-color: silver;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+	width: @fancy-icon-width;
+	height: @fancy-icon-height;
+//	display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+//	-moz-box-align: start; /* issue 221 */
+	display: inline-block; // Required to make a span sizeable
+	vertical-align: top;
+	background-repeat: no-repeat;
+	background-position: left;
+	.setBgImageUrl("icons.gif");
+	.setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+	margin-top: @fancy-icon-ofs-top;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+	display: inline-block;
+	margin-left: @fancy-icon-spacing;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+	width: @fancy-icon-width;
+	height: @fancy-icon-height;
+	margin-left: @fancy-icon-spacing;
+	margin-top: @fancy-icon-ofs-top;
+	vertical-align: top;
+	border-style: none;
+}
+
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+	// .useSprite(0, 5);
+	cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// 	// .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander, 
+.fancytree-exp-nl span.fancytree-expander {
+	.clearBgImage( @fancy-hide-connectors );
+	cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,       // End-node, not last sibling
+.fancytree-exp-n span.fancytree-expander:hover {
+	.useSprite(0, 4);
+}
+.fancytree-exp-nl span.fancytree-expander,      // End-node, last sibling
+.fancytree-exp-nl span.fancytree-expander:hover {
+	.useSprite(1, 4);
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander { // Collapsed, not delayed, not last sibling
+	.useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+	.useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander { // Collapsed, not delayed, last sibling
+	.useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+	.useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander { // Collapsed, delayed, not last sibling
+	.useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+	.useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander { // Collapsed, delayed, last sibling
+	.useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+	.useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander,   // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander { // Expanded, delayed, not last sibling
+	.useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+	.useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander,   // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander { // Expanded, delayed, last sibling
+	.useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,  
+.fancytree-exp-edl span.fancytree-expander:hover {
+	.useSprite(3, 6);
+}
+
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-checkbox {
+	margin-left: @fancy-icon-spacing;
+	.useSprite(0, 2);
+	&:hover { .useSprite(1, 2); }
+}
+.fancytree-partsel span.fancytree-checkbox {
+	.useSprite(4, 2);
+	&:hover { .useSprite(5, 2); }
+}
+// selected after partsel, so it takes precedence:
+.fancytree-selected span.fancytree-checkbox {
+	.useSprite(2, 2);
+	&:hover { .useSprite(3, 2); }
+}
+// Unselectable is dimmed, without hover effects
+.fancytree-unselectable {
+	span.fancytree-checkbox {
+		opacity: 0.4;
+		filter: alpha(opacity=40);
+	}
+	span.fancytree-checkbox:hover {
+		.useSprite(0, 2);
+	}
+	&.fancytree-partsel span.fancytree-checkbox:hover {
+		.useSprite(4, 2);
+	}
+	&.fancytree-selected span.fancytree-checkbox:hover {
+		.useSprite(2, 2);
+	}
+}
+
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+
+.fancytree-radio {
+	span.fancytree-checkbox {
+		.useSprite(0, 3);
+		&:hover { .useSprite(1, 3); }
+	}
+	.fancytree-partsel span.fancytree-checkbox {
+		.useSprite(4, 3);
+		&:hover { .useSprite(5, 3); }
+	}
+	// Selected after partsel, so it takes precedence:
+	.fancytree-selected span.fancytree-checkbox {
+		.useSprite(2, 3);
+		&:hover { .useSprite(3, 3); }
+	}
+	// Unselectable is dimmed, without hover effects
+	.fancytree-unselectable {
+		span.fancytree-checkbox,
+		span.fancytree-checkbox:hover {
+			.useSprite(0, 3);
+		}
+	}
+}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon { // Default icon
+	margin-left: @fancy-icon-spacing;
+	.useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon  { // Collapsed folder (empty)
+	// .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+	.useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon  { // Collapsed folder (not empty)
+	.useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+	.useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon  { // Expanded folder
+	.useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+	.useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon  { // Collapsed folder (empty)
+	.useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+	.useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon  { // Collapsed folder (not empty)
+	.useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+	.useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon  { // Expanded folder
+	.useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+	.useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+	background-image: @fancy-loading-url;
+	.useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+	.useSprite(0, 7);
+}
+
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+	/* See #117 */
+	display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+	width: 100%;
+	margin-top: @fancy-node-v-spacing;
+	min-height: @fancy-line-height;
+}
+span.fancytree-title {
+	color: @fancy-font-color; // inherit doesn't work on IE
+	cursor: pointer;
+	display: inline-block; // Better alignment, when title contains <br>
+	vertical-align: top;
+	min-height: @fancy-line-height;
+	padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+	margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+	// margin: 0px;
+	// margin-top: @fancy-line-ofs-top;
+	// margin-left: @fancy-icon-spacing;
+    border: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover
+    .rounded-corners(@fancy-node-border-radius);
+//  outline: 0; // @ Firefox, prevent dotted border after click 
+// Set transparent border to prevent jumping when active node gets a border
+//	   (we can do this, because this theme doesn't use vertical lines)
+//	border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+	color: @fancy-font-error-color;
+}
+
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper {
+	span.fancytree-childcounter,
+	span.fancytree-dnd-modifier {
+		display: inline-block;
+		color: #fff;
+		background: #337ab7;  // bootstrap blue
+		border: 1px solid gray;
+		min-width: 10px;
+		// min-height: 16px;
+		height: 10px;
+		line-height: 1;
+		vertical-align: baseline;
+		border-radius: 10px;
+		padding: 2px;
+		text-align: center;
+		font-size: 9px;
+	}
+	span.fancytree-childcounter {
+		position: absolute;
+		// left: 16px;
+		top: -6px;
+		right: -6px;
+	}
+	span.fancytree-dnd-modifier {
+		background: #5cb85c;  // bootstrap green
+		border: none;
+		// min-height: 16px;
+		// font-size: 12px;
+		font-weight: bolder;
+	}
+	&.fancytree-drop-accept {
+		span.fancytree-drag-helper-img {
+			.useSprite(2, 7);
+		}
+	}
+	&.fancytree-drop-reject {
+		span.fancytree-drag-helper-img {
+			.useSprite(1, 7);
+		}
+	}
+}
+
+
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+	width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+	position: absolute;
+	.useSprite(0, 8);
+	margin: 0;
+	&.fancytree-drop-after,
+	&.fancytree-drop-before {
+		width: 4 * @fancy-icon-width; // 64px;
+		.useSprite(0, 9);
+	}
+	&.fancytree-drop-copy {
+		.useSprite(4, 8);
+	}
+	&.fancytree-drop-move {
+		.useSprite(2, 8);
+	}
+}
+
+/*** Source node while dragging ***********************************************/
+
+span.fancytree-drag-source {
+	&.fancytree-drag-remove {
+//		text-decoration: line-through;
+		opacity: 0.15;
+	}
+}
+
+/*** Target node while dragging cursor is over it *****************************/
+
+span.fancytree-drop-target {
+	&.fancytree-drop-accept {
+		// outline: 1px dotted #5cb85c; // bootstrap sucess
+	}
+}
+span.fancytree-drop-reject {
+	// outline: 1px dotted #d9534f; // boostrap warning
+}
+
+
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+
+table.fancytree-ext-table {
+	border-collapse: collapse;
+	span.fancytree-node {
+		display: inline-block; // #117
+	}
+}
+
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+
+table.fancytree-ext-columnview {
+// 	border-collapse: collapse;
+// 	width: 100%;
+	tbody tr td {
+		position: relative;
+		border: 1px solid gray;
+		vertical-align: top;
+		overflow: auto;
+		>ul {
+			padding: 0;
+			li {
+				list-style-image: none;
+				list-style-position: outside;
+				list-style-type: none;
+				-moz-background-clip:border;
+				-moz-background-inline-policy: continuous;
+				-moz-background-origin: padding;
+				background-attachment: scroll;
+				background-color: transparent;
+				.setBgPos(0, 0);
+				background-repeat: repeat-y;
+				background-image: none;  /* no v-lines */
+
+				margin: 0;
+//				padding: 1px 0 0 0;  // issue #246
+			}
+		}
+	}
+	span.fancytree-node {
+		position: relative; /* allow positioning of embedded spans */
+		display: inline-block; // #117
+	}
+	span.fancytree-node.fancytree-expanded {
+		background-color: #CBE8F6;
+	}
+	// table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+	// 	background-color: royalblue;
+	// }
+	.fancytree-has-children span.fancytree-cv-right {
+		position: absolute;
+		right: 3px;
+		.useSprite(0, 5);
+		&:hover {
+			.useSprite(1, 5);
+		}
+	}
+}
+
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+
+.fancytree-ext-filter-dimm {
+	span.fancytree-node span.fancytree-title {
+		color: @fancy-font-color-dimm;
+		font-weight: lighter;
+	}
+	tr.fancytree-submatch span.fancytree-title,
+	span.fancytree-node.fancytree-submatch span.fancytree-title {
+		color: black;
+		font-weight: normal;
+	}
+	tr.fancytree-match span.fancytree-title,
+	span.fancytree-node.fancytree-match span.fancytree-title {
+		color: black;
+		font-weight: bold;
+	}
+}
+.fancytree-ext-filter-hide {
+	tr.fancytree-hide,
+	span.fancytree-node.fancytree-hide {
+		display: none;
+	}
+	tr.fancytree-submatch span.fancytree-title,
+	span.fancytree-node.fancytree-submatch span.fancytree-title {
+		color: @fancy-font-color-dimm;
+		font-weight: lighter;
+	}
+	tr.fancytree-match span.fancytree-title,
+	span.fancytree-node.fancytree-match span.fancytree-title {
+		color: black;
+		font-weight: normal;
+	}
+}
+
+.fancytree-ext-childcounter,
+.fancytree-ext-filter {
+	// span.fancytree-title mark {
+	// 	font-style: normal;
+	// 	background-color: #ead61c; // yellow
+	// 	border-radius: 3px;
+	// }
+	span.fancytree-icon {
+		position: relative;
+	}
+	span.fancytree-childcounter {
+		color: #fff;
+		background: #777;  // #337ab7;  // bootstrap blue
+		border: 1px solid gray;
+		position: absolute;
+		top: -6px;
+		right: -6px;
+		min-width: 10px;
+		height: 10px;
+		line-height: 1;
+		vertical-align: baseline;
+		border-radius: 10px;
+		padding: 2px;
+		text-align: center;
+		font-size: 9px;
+	}
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-ext-wide {
+	position: relative;
+	min-width: 100%;
+	z-index: 2;
+
+	-webkit-box-sizing: border-box;
+	-moz-box-sizing: border-box;
+	box-sizing: border-box;
+
+	span.fancytree-node >span {
+		position: relative;
+		z-index: 2;
+	}
+	span.fancytree-node span.fancytree-title {
+		position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+		z-index: 1; // Behind expander and checkbox
+		left: 0px;
+		width: 100%;
+		margin-left: 0;
+		margin-right: 0;
+
+		-webkit-box-sizing: border-box;
+		-moz-box-sizing: border-box;
+		box-sizing: border-box;
+	}
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-custom-1/README.md b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-custom-1/README.md
new file mode 100644
index 00000000000..da573d61e4c
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-custom-1/README.md
@@ -0,0 +1,14 @@
+### Creating Custom Skins
+
+1. Create a folder like this (recommended name: 'src/skin-custom-...')
+2. For a start copy files from one of the existing skin folders (src/skin-...) 
+   to the custom folder:
+   - ui.fancytree.less  (required)
+   - icons.gif (if needed)
+   - loading.gif (if needed)
+3. cd to your fancytree folder and run `grunt dev` from the connsole.<br>
+   Note: NPM and Grunt are required. 
+   Read [how to install the toolset](https://github.com/mar10/fancytree/wiki/HowtoContribute#install-the-source-code-and-tools-for-debugging-and-contributing).
+4. Edit and save your ui.fancytree.less file.<br>
+   The `ui.fancytree.css` will be generated and updated automatically from 
+   the LESS file.
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..305d75bd7539f224f8c85429b7701c0c537d28c6
GIT binary patch
literal 5906
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
a7jqlG%xQyjxJ~mq*7LgC=450bmj4IAEko%5

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4
GIT binary patch
literal 1849
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
EAHN$8j{pDw

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.css
new file mode 100644
index 00000000000..4ae213c3186
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.css
@@ -0,0 +1,565 @@
+/*!
+ * Fancytree "Lion" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*
+ Lion colors:
+	gray highlight bar: #D4D4D4
+	blue highlight-bar and -border #3875D7
+
+*/
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-image: url("icons.gif");
+  background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 0px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 3px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 16px;
+  height: 16px;
+  margin-left: 3px;
+  margin-top: 0px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+  background-position: 0px -64px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+  background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+  background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+  background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+  background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+  background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+  background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+  background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+  background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+  background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+  background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+  background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+  background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+  background-position: -48px -96px;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 3px;
+  background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+  background-position: -16px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -32px;
+}
+.fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -32px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -32px -32px;
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+.fancytree-radio span.fancytree-checkbox {
+  background-position: 0px -48px;
+}
+.fancytree-radio span.fancytree-checkbox:hover {
+  background-position: -16px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -48px;
+}
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -48px;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 3px;
+  background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+  background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+  background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+  background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+  background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+  background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+  background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+  background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url('data:image/gif;base64,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');
+  background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+  background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 16px;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 16px;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 3px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+  background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+  background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 32px;
+  position: absolute;
+  background-position: 0px -128px;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 64px;
+  background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+  background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+  background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+  background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+  background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+  border: 1px solid transparent;
+  border-radius: 0;
+}
+span.fancytree-focused span.fancytree-title {
+  outline: 1px dotted black;
+}
+span.fancytree-selected span.fancytree-title,
+span.fancytree-active span.fancytree-title {
+  background-color: #D4D4D4;
+}
+span.fancytree-selected span.fancytree-title {
+  font-style: italic;
+}
+.fancytree-treefocus span.fancytree-selected span.fancytree-title,
+.fancytree-treefocus span.fancytree-active span.fancytree-title {
+  color: white;
+  background-color: #3875D7;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+  background-color: #99DEFD;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+  background-color: royalblue;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  background-color: #99DEFD;
+}
+/*******************************************************************************
+ * 'columnview' extension
+ */
+table.fancytree-ext-columnview tbody tr td {
+  border: 1px solid gray;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #ccc;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+  background-color: royalblue;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.less
new file mode 100644
index 00000000000..7baf8380e65
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.less
@@ -0,0 +1,95 @@
+ /*!
+ * Fancytree "Lion" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+/*
+ Lion colors:
+	gray highlight bar: #D4D4D4
+	blue highlight-bar and -border #3875D7
+
+*/
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: true;      // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: true;
+
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-line-height: 16px;
+@fancy-icon-spacing: 3px;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+@fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS 
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+	border: 1px solid transparent; // reserve some space for status borders
+	border-radius: 0;
+}
+span.fancytree-focused span.fancytree-title {
+	outline: 1px dotted black;
+}
+span.fancytree-selected span.fancytree-title,
+span.fancytree-active span.fancytree-title {
+	background-color: #D4D4D4; // gray
+}
+span.fancytree-selected span.fancytree-title {
+	font-style: italic;
+}
+.fancytree-treefocus span.fancytree-selected span.fancytree-title,
+.fancytree-treefocus span.fancytree-active span.fancytree-title {
+	color: white;
+	background-color: #3875D7; // blue
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+	border-collapse: collapse;
+	tbody {
+	    tr.fancytree-focused {
+			background-color: #99DEFD;
+		}
+	    tr.fancytree-active {
+			background-color: royalblue;
+		}
+	    tr.fancytree-selected {
+			background-color: #99DEFD;
+		}
+	}
+}
+
+/*******************************************************************************
+ * 'columnview' extension
+ */
+
+table.fancytree-ext-columnview tbody tr td {
+	border: 1px solid gray;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+	background-color: #ccc;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+	background-color: royalblue;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.min.css
new file mode 100644
index 00000000000..d21c5fbbd7a
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-lion/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Lion" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:0}span.fancytree-custom-icon{display:inline-block;margin-left:3px}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(data:image/gif;base64,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);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px;margin:0 0 0 3px;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}span.fancytree-title{border:1px solid transparent;border-radius:0}span.fancytree-focused span.fancytree-title{outline:1px dotted #000}span.fancytree-active span.fancytree-title,span.fancytree-selected span.fancytree-title{background-color:#D4D4D4}span.fancytree-selected span.fancytree-title{font-style:italic}.fancytree-treefocus span.fancytree-active span.fancytree-title,.fancytree-treefocus span.fancytree-selected span.fancytree-title{color:#fff;background-color:#3875D7}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused{background-color:#99DEFD}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#4169e1}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#99DEFD}table.fancytree-ext-columnview tbody tr td{border:1px solid gray}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#ccc}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#4169e1}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..813eb8385c40a954a85b0fc8379a6446aec3acd8
GIT binary patch
literal 5492
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ef88497ccc2f6c2a3a0c5e41f3cbfc7a18ff5329
GIT binary patch
literal 3234
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
RGR}AoOL=)|H48+m{|ju`J$C>A

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.css
new file mode 100644
index 00000000000..07961f26f92
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.css
@@ -0,0 +1,505 @@
+/*
+ * Fancytree for use with ext-themeroller extension.
+ */
+.ui-helper-hidden {
+	display: none;
+}
+
+.fancytree-container
+{
+	white-space: nowrap;
+	padding: 3px;
+	margin: 0; /* issue 201 */
+	overflow: auto;
+/*	height: 100%; /* issue 263 */
+/*
+	font-family: tahoma, arial, helvetica;
+	font-size: 10pt;
+	background-color: white;
+	border: 1px dotted gray;
+*/
+}
+
+ul.fancytree-container ul
+{
+	padding: 0 0 0 16px;
+	margin: 0;
+}
+
+ul.fancytree-container li
+{
+	list-style-image: none;
+	list-style-position: outside;
+	list-style-type: none;
+	-moz-background-clip:border;
+	-moz-background-inline-policy: continuous;
+	-moz-background-origin: padding;
+	background-attachment: scroll;
+	background-color: transparent;
+	background-position: 0 0;
+	background-repeat: repeat-y;
+	background-image: none;  /* no v-lines */
+
+	margin:0;
+	padding:1px 0 0 0;
+}
+/* Suppress lines for last child node */
+ul.fancytree-container li.fancytree-lastsib
+{
+	background-image: none;
+}
+/* Suppress lines if level is fixed expanded (option minExpandLevel) */
+ul.fancytree-no-connector > li
+{
+	background-image: none;
+}
+
+/* Style, when control is disabled */
+/*
+.ui-fancytree-disabled ul.fancytree-container
+{
+	opacity: 0.5;
+}
+*/
+
+span.fancytree-node
+{
+	display: inline-block;
+	width: 100%;
+	border: 1px solid transparent;
+}
+
+/*******************************************************************************
+ * Common icon definitions
+ */
+span.fancytree-empty,
+span.fancytree-vline,
+/*span.fancytree-connector,*/
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker
+{
+	width: 16px;
+	height: 16px;
+	display: inline-block; /* Required to make a span sizable */
+	vertical-align: top;
+	background-repeat: no-repeat;
+	background-position: left;
+	background-image: url("icons.gif");
+	background-position: 0 0;
+}
+/** Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+	display: inline-block;
+}
+/** Used by 'icon' node option: */
+.fancytree-container img
+{
+	width: 16px;
+	height: 16px;
+	margin-left: 3px;
+	vertical-align: top;
+	border-style: none;
+}
+
+
+/*******************************************************************************
+ * Lines and connectors
+ */
+/* span.fancytree-connector
+{
+	background-image: none;
+}
+ */
+/*******************************************************************************
+ * Expander icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ */
+
+span.fancytree-expander
+{
+	background-position: 0px -80px;
+	cursor: pointer;
+}
+span.fancytree-expander:hover
+{
+	background-position: -16px -80px;
+}
+.fancytree-exp-n span.fancytree-expander:hover /* Collapsed, not delayed, not last sibling */
+{
+	background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander /* Collapsed, not delayed, last sibling */
+{
+}
+.fancytree-exp-cd span.fancytree-expander /* Collapsed, delayed, not last sibling */
+{
+}
+.fancytree-exp-cdl span.fancytree-expander /* Collapsed, delayed, last sibling */
+{
+}
+.fancytree-exp-e span.fancytree-expander,  /* Expanded, not delayed, not last sibling */
+.fancytree-exp-ed span.fancytree-expander,  /* Expanded, delayed, not last sibling */
+.fancytree-exp-el span.fancytree-expander,  /* Expanded, not delayed, last sibling */
+.fancytree-exp-edl span.fancytree-expander  /* Expanded, delayed, last sibling */
+{
+	background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,  /* Expanded, not delayed, not last sibling */
+.fancytree-exp-ed span.fancytree-expander:hover,  /* Expanded, delayed, not last sibling */
+.fancytree-exp-el span.fancytree-expander:hover,  /* Expanded, not delayed, last sibling */
+.fancytree-exp-edl span.fancytree-expander:hover  /* Expanded, delayed, last sibling */
+{
+	background-position: -48px -80px;
+}
+.fancytree-loading span.fancytree-expander  /* 'Loading' status overrides all others */
+{
+	background-position: 0 0;
+	background-image: url("loading.gif");
+}
+
+.fancytree-exp-n span.fancytree-expander, /* Connector instead of expander, if node has no children */
+.fancytree-exp-nl span.fancytree-expander
+{
+	background-image: none;
+	cursor: default;
+}
+
+
+/*******************************************************************************
+ * Checkbox icon
+ */
+span.fancytree-checkbox
+{
+	margin-left: 3px;
+	background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover
+{
+	background-position: -16px -32px;
+}
+
+.fancytree-partsel span.fancytree-checkbox
+{
+	background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover
+{
+	background-position: -80px -32px;
+}
+
+.fancytree-selected span.fancytree-checkbox
+{
+	background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover
+{
+	background-position: -48px -32px;
+}
+
+/*******************************************************************************
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ */
+.fancytree-radio span.fancytree-checkbox
+{
+	margin-left: 3px;
+	background-position: 0px -48px;
+}
+.fancytree-radio span.fancytree-checkbox:hover
+{
+	background-position: -16px -48px;
+}
+
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox
+{
+	background-position: -64px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover
+{
+	background-position: -80px -48px;
+}
+
+.fancytree-radio .fancytree-selected span.fancytree-checkbox
+{
+	background-position: -32px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover
+{
+	background-position: -48px -48px;
+}
+
+
+/*******************************************************************************
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ */
+
+span.fancytree-icon /* Default icon */
+{
+	margin-left: 3px;
+	background-position: 0px 0px;
+}
+
+.fancytree-has-children span.fancytree-icon /* Default icon */
+{
+/*    background-position: 0px -16px; */
+}
+
+.fancytree-ico-cf span.fancytree-icon  /* Collapsed Folder */
+{
+	background-position: 0px -16px;
+}
+
+.fancytree-ico-ef span.fancytree-icon  /* Expanded Folder */
+{
+	background-position: -64px -16px;
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-wait span.fancytree-icon
+{
+	background-image: url("loading.gif");
+}
+
+.fancytree-statusnode-error span.fancytree-icon
+{
+	background-position: 0px -112px;
+/*	background-image: url("ltError.gif");*/
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+
+span.fancytree-title
+{
+	display: inline-block;
+}
+.fancytree-title
+{
+	display: inline-block; /* Better alignment, when title contains <br> */
+	padding-left: 3px;
+	padding-right: 3px; /* Otherwise italic font will be outside bounds */
+/*	color: black; /* inherit doesn't work on IE */
+	vertical-align: top;
+	margin: 0px;
+	margin-left: 3px;
+	cursor: pointer;
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+
+/*
+table.fancytree-ext-table {
+	border-collapse: collapse;
+	width: 100%;
+}
+table.fancytree-ext-table tbody tr:nth-child(even){
+	background-color: #f4f4f8;
+}
+table.fancytree-ext-table tbody tr td {
+	border: 1px solid lightgray;
+}
+*/
+table.fancytree-ext-table {
+	border-collapse: collapse;
+}
+
+/*******************************************************************************
+ * 'columnview' extension
+ */
+
+/*
+table.fancytree-ext-columnview {
+	border-collapse: collapse;
+	width: 100%;
+}
+*/
+table.fancytree-ext-columnview td
+{
+	position: relative;
+}
+table.fancytree-ext-columnview td >ul
+{
+	padding: 0;
+}
+table.fancytree-ext-columnview td >ul li
+{
+	list-style-image: none;
+	list-style-position: outside;
+	list-style-type: none;
+	-moz-background-clip:border;
+	-moz-background-inline-policy: continuous;
+	-moz-background-origin: padding;
+	background-attachment: scroll;
+	background-color: transparent;
+	background-position: 0 0;
+	background-repeat: repeat-y;
+	background-image: none;  /* no v-lines */
+
+	margin: 0;
+	padding: 1px 0 0 0;
+}
+/*
+table.fancytree-ext-columnview tbody tr[0] {
+	height: 200px;
+}
+*/
+table.fancytree-ext-columnview tbody tr td {
+	border: 1px solid gray;
+	vertical-align: top;
+	overflow: auto;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+	position: relative; /* allow positioning of embedded spans*/
+}
+/*
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+	background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+	background-color: royalblue;
+}
+*/
+table.fancytree-ext-columnview span.fancytree-cv-right {
+	background-position: 0px -80px;
+	position: absolute;
+	right: 3px;
+}
+
+/*******************************************************************************
+ * 'filter' extension
+ */
+.fancytree-ext-filter .fancytree-node .fancytree-title {
+	color: silver;
+	font-weight: lighter;
+}
+.fancytree-ext-filter .fancytree-node.fancytree-submatch .fancytree-title {
+	color: black;
+	font-weight: normal;
+}
+.fancytree-ext-filter .fancytree-node.fancytree-match .fancytree-title {
+	color: black;
+	font-weight: bold;
+}
+
+
+/*******************************************************************************
+ * Drag'n'drop support
+ */
+
+/*** Helper object ************************************************************/
+div.fancytree-drag-helper
+{
+}
+div.fancytree-drag-helper a
+{
+	border: 1px solid gray;
+	background-color: white;
+	padding-left: 5px;
+	padding-right: 5px;
+	opacity: 0.8;
+}
+span.fancytree-drag-helper-img
+{
+	/*
+	position: relative;
+	left: -16px;
+	*/
+}
+div.fancytree-drag-helper /*.fancytree-drop-accept*/
+{
+/*    border-color: green;
+	background-color: red;*/
+}
+div.fancytree-drop-accept span.fancytree-drag-helper-img
+{
+	background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject
+{
+	border-color: red;
+}
+div.fancytree-drop-reject span.fancytree-drag-helper-img
+{
+	background-position: -16px -112px;
+}
+
+/*** Drop marker icon *********************************************************/
+
+#fancytree-drop-marker
+{
+	width: 24px;
+	position: absolute;
+	background-position: 0 -128px;
+	margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before
+{
+	width:64px;
+	background-position: 0 -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy
+{
+	background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move
+{
+	background-position: -64px -128px;
+}
+
+/*** Source node while dragging ***********************************************/
+
+span.fancytree-drag-source
+{
+	/* border: 1px dotted gray; */
+	background-color: #e0e0e0;
+}
+span.fancytree-drag-source a
+{
+	color: gray;
+}
+
+/*** Target node while dragging cursor is over it *****************************/
+
+span.fancytree-drop-target
+{
+	/*border: 1px solid gray;*/
+}
+span.fancytree-drop-target a
+{
+}
+span.fancytree-drop-target.fancytree-drop-accept a
+{
+	/*border: 1px solid green;*/
+	background-color: #3169C6 !important;
+	color: white !important; /* @ IE6 */
+	text-decoration: none;
+}
+span.fancytree-drop-target.fancytree-drop-reject
+{
+	/*border: 1px solid red;*/
+}
+span.fancytree-drop-target.fancytree-drop-after a
+{
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.min.css
new file mode 100644
index 00000000000..cc276ec9dd6
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-themeroller/ui.fancytree.min.css
@@ -0,0 +1 @@
+.ui-helper-hidden{display:none}.fancytree-container{white-space:nowrap;padding:3px;margin:0;overflow:auto}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0;padding:1px 0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}span.fancytree-node{display:inline-block;width:100%;border:1px solid transparent}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-custom-icon{display:inline-block}.fancytree-container img{width:16px;height:16px;margin-left:3px;vertical-align:top;border-style:none}span.fancytree-expander{background-position:0 -80px;cursor:pointer}.fancytree-exp-n span.fancytree-expander:hover,span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander,.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover,.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-loading span.fancytree-expander{background-position:0 0;background-image:url(loading.gif)}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-radio span.fancytree-checkbox{margin-left:3px;background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-statusnode-wait span.fancytree-icon{background-image:url(loading.gif)}.fancytree-statusnode-error span.fancytree-icon{background-position:0 -112px}span.fancytree-title{display:inline-block}.fancytree-title{display:inline-block;padding-left:3px;padding-right:3px;vertical-align:top;margin:0;margin-left:3px;cursor:pointer}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-columnview td{position:relative}table.fancytree-ext-columnview td >ul{padding:0}table.fancytree-ext-columnview td >ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0;padding:1px 0 0}table.fancytree-ext-columnview tbody tr td{border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview span.fancytree-node{position:relative}table.fancytree-ext-columnview span.fancytree-cv-right{background-position:0 -80px;position:absolute;right:3px}.fancytree-ext-filter .fancytree-node .fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter .fancytree-node.fancytree-submatch .fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter .fancytree-node.fancytree-match .fancytree-title{color:#000;font-weight:700}div.fancytree-drag-helper a{border:1px solid gray;background-color:#fff;padding-left:5px;padding-right:5px;opacity:.8}div.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject{border-color:red}div.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:24px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy,#fancytree-drop-marker.fancytree-drop-move{background-position:-64px -128px}span.fancytree-drag-source{background-color:#e0e0e0}span.fancytree-drag-source a{color:gray}span.fancytree-drop-target.fancytree-drop-accept a{background-color:#3169C6!important;color:#fff!important;text-decoration:none}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..65719ccc28fb0b78fbed90cb04341280b4cd6ac0
GIT binary patch
literal 5492
zcmV-)6^rUeNk%w1VPF8r0QUd@000005OfF`dKCp~DltMqNLpE2SV~oFQDJ=mDVHBG
zjRZNT8&ZV;Laq*4$N*x=0BhI)bl^a9oJo6<RdJG4dYV>xt$KU48I>Fur5PrzBRaz{
zajh+Wxi>|<MSp>QYrSP@y=!v4ZFs$OOxIIF&S6Z}XmH18a>jE2g@gcr<^YZP0F?Rw
zoc{!+{Q&>}AkOwggp^E-mQR_BR+*Mmg|A<Pq*bedSha&+wu^a%g=~zcXpF6EjI?W%
zu5O&KZ<Dljl%sZ*vSGEDbiA2yrmJwRrFpHUcD|>3wWd#$)?dBdd7{>Nwe5b!qF=`U
zT-X14&i!`Y{ht5;{{R6000{pZ6#pI`|05^=K1BaWO#e|-|5;c6VqpJjX#aV8jlx2f
z$w|khKJTtD#-&BXtwPAGO2w^T&#hF=woA{oU)8oo-M&rGv{}`?Qq;X!&%JEby>#)#
zAJ@fL-^Nqk##-IRVcf=O-_B>(#d_P%d*H@Q=FVZ}&uQVtaOKZ%>CJcN)^6?BckbSN
zgN1^Njf#wvn~9yAl9Z8~otcHLyN$KBiM70uwY{RBqot*ss;!-*rlYH^s;sTIrM0`X
zwzIUgzPr7;h_1<%wZw+I?xnTJt-ZvezSXY1(Y(FKwY1o^yx)z-hK$FHlg^Wy&Xk$X
znwZ72lINzV)}pK5qrSntweP>2z}17_|C7T1mdpR1&HI$r|F*`=w#M1L&eXTv%c0Bj
zsM7nf-~Y7O{I}fyzu*0`@W#9F$D`=~tmpr)?*Fyt|Nnx9|BsIUoSFZmr2o9S>DGhp
z--Phhg!0{s?&py9=ZpE~nfLFk`R}Ir_N)K*wEg$G#mB_W%g@cv%f-gf!Oh#$*3;eJ
z+|t+J+1BXK_t(Ve|IP3J-{9)f>iyLC;NSM=-uL|E-rfDm$o<;d;oa}&=iTJ+-T3y!
z=IG_`@8#m_^Wg0J?(g~N_Ui8N?d<XN=>PEU|M~Fu?DzKV@%Q@n_W$ty@%H%i{rC3&
z|Mvd>`~Uy|A^8LW00930EC2ui0AK*f000R80RR14MX;bjfd~g0T$oVcLWT_=9*iiF
zU_*r!FRtR(&!0zs9jRT4$nhgce<DeC{1|d%!i_6Ewp3|y=F5^SQMyF9Y9G#z)b{Nh
z=rg9rphJ89JSy~MQIjZ}@_cF%snexVhhEx8)#If~m3D6J>hEh<gkzVQ70XpEShi%>
zqHSwbuE4Qm*_DHvckf)fCiU`ND)?{T!A1+;<qFtjCBtO>JzmTh>*RlUBVW#J8FFWV
zl^8encsaD_rKLraO?}!Z>&mVXnuhIIwrZ|1UyIId`!;XTxA*=2H+%O--HeA9-`x>;
z^5(sLLkAwb-*n=^g<oI(TrxsQ*|kgm`X1i;c!A)vn<uZn-}!&(tGj0}|9$-6{OpJK
zsXu&v`uO#i-GAuqM<9Ir?IU1z3kKKVZ4aszp=j?Vl3*eTS-2mD0%;f?hyQq(9f%?Z
zN8*JDA(9{>DX!S!ek=;4B8)GF7vn!O+K3P#2@<knk3a6`qd+_g8Dw}v{!=892z}t>
zlTbd{WRz5XFlCicUWuiXT5j1TmI*b}%reQ4sf;p$AajwJWSWVlnhmj8W-@1{x#pO2
z)(K~rc)Dq4oPE;yW}MOV<4iJoOrz*D((L(9Gld?S=%S5=87ZQRGU_O#hGI(Trk75t
zXr%~oDru&q3e=1=(s+bN9?y*b`bU_ox(chTw6^NctFbaVYpJ#FdaJLw+S;o$zp5H6
zuebtRs~vG5Bh53<;E`*q&`L|Kwa#K2?X=Zi>rb}ea;xmK-)<`|x$1W7&m3_8@(eW2
z+#xQ!^3rRsyZFvq@4fN*yYIQJ_Ny<z`Tpx{p>M$PhcnD9Gw`FVGVCzK66b31!x2xs
zsx%v8>~Y2YG|X|v3zvLx#|b3^@-zLop~fA{ETfFM|F|3t%ret#GtN5mJaf%AxBPO<
zL;q~_&Pe-QG(tf)O*GIuL$glLXa>@U9Z*+&^~_ms-Sxa*-w`&~0wv=$)`Dn_cFt>q
z-L}|i$8Gl9ZznS^Gt8v_(S{vb^C3^(d-wf!;DbY5xZi;HAvodC@Xa{lkV}5J<B6xe
z_~nlyG)UykAd?0fZ}7oK9hv|0Ip3m_ZaV63uO9m7rJtU<?5)=hyXT<i{`&2`)BgM0
zfv_&R8E(`;2OaXffl%?GAD{g4%|CB^8ptcpyz>G<kBs!%SKs~h*;CK`Ki-3HzV+Yh
zQ3e@q(6PrJOPpVP`|rm;fBozu<39ZIqo4hv_dop!uzv*%ApgdPKLGCUe0^x&9m*hv
zHO%jT0*RpiCRo7>F7O{3)B^`C_&|h&aD*O&padyMLJWd%g&i!RK=80ZJFxJAZ14j@
zXedG(#&8cg++hv>Z#cgo&Txo7G~z#acn2T0P>D=*A`W$kkU6~Jiut?Z8>m=CEoSkG
zToi~Eu?RmchVdU`e8U&F*pM`?@r-UPBN#98k36K|40ODR9r2jQgzT}8e!L?f5%R}D
z)=`j#Or#<g$;d`J@{y2?q$Cr`fJ$2Ol9ogWCO270O>z>Gp8RAc1tQ8zhO(5JOouAd
z!47t`Lmu+D$37UK$uZdSmbe@PElIgbR=N_FvfSlA7?8_i3X=i7Y~?FsIm=oW6PL$a
zWh>bMOs*Vr406b(HnpkCRH|~C)odmyvANA{c9WN;7=<WC!Ol^TA{F8sCOONQ&2tX(
zo2>+<Kdf2*OF4iumi~}~J(1~4YQ{1H{2Zr0^LbE#MspM)2!RMD8UhrIBA&#QLqsPk
zf{HpcmH)hlNA}^5Yc5ou0Uc;Tftdk>mb9M?y+=zw%1cpz;HDwKsVH8m(3^rFr$43X
zFk9&llzzmdMFprwgvx+cW`LzF^@vHIdeE5;lpQt=!3a<=0*RV}r}C7;Pq*4t5ir%2
z9uX;2km?V$F7>MIXsJwFN>Z?9RIV*W=vi$l0<NMU1ScScU9ky*zHSw;OnoI(Ou|;E
zBvu}IrR!1q8CjPmRumHL>t9juRg-2G1)F86QP<i}w|+#lu*_>+rP@!(N;aj(l*cH3
zx>>FN3f82wt*BN-E6dd~wx3*a>_C~hj|?o<q+BuXX@@Hc5!_S+T|Gf(`{~@mMwh9*
z_3dO8O3!*8GrRjFEqA*+(0imp6r@NmDbSmW!FJcXnq<skSv$^W-tw68o$od6YfJnF
zSHI5W?=ef+Nm3Gczyv;}C>8uk26J+f5RR~fCrsfATlm5lhNLHKzyKR~Vvrk7frmlN
z;SmFJ!yW$ciA${FK8D!DbfiUxDWMHcaJUw9tc8dvF$PZTAO$$Sh>UH(i5l;K0YPp^
zEjrAJ9v?Z$3Bd-FRpDa>&?3hoZnBSoe34pIfX3<2hATIG<%D>d$Jn&xENlSff6$`;
z0-W&WE6J>6INMU7V_0*Wy}Sukq{7dtSaX>X;^ii%InQiv2m`<@=4H-8m;y-wkIR|o
z6ev2*%5*fOhuLIGKU&e00Q8^#{ON?Gpws4@g{2X)VQqx@m$8%w4_droa<=1@_1poi
zZNSQOsKNuLXoo%aF>6-afSkWJMLm76Yf(G9*aE3_HdR6GWw+P{l=$W{<-wITBLv&n
zyfrN4Ay8V_;M<s11qn8w0aI|L7UvcSk+G?6c9){u@%{&qM@{WN`x)NorZ=^#JqB}Y
z($z8Lc0&J=0$Y!JAN5@IFdOZG4Qv1d7+{P^<xuerWB>#3B_*Io&TnBheA)y5S4G6p
z?aF0}2H^7U^ur-O2AJ!c6R$Ld20mU2k{Ueb*wi`C1!{95lf2)mD0-(;uJW4ad&Aq#
zFSP&Ri5-wr;q?>(t#<%Rb(jJJrr@?ew9aa)XR{O-xVJ#b9_=0Qo8-(cJF=_2_7)Fw
z7UA6Ik{gnOS<JJZI#x8^MdJ|}3;yp!-!ube@%BGUneTq5bl}ZwgIN$B-h&nhy#0P?
zc<;IL^4*8$m0bBd+j8`jXZ*;`{dvyg8TAQ~F%K+X3mzaD%RHb(&4s{aAv1snwb%zO
zgmC*VGr$MBuLbejED#wZKk2q-{y%h#{N4ASjwpt49$##C?6a7}DF(m)_PsCS?q~S?
z=uf};Ckcr~wtxK)js*PYkKy+x(*E>+r2O;G{|MuMkpI_zinM<MSb&byehByv3HW~t
zsDKU_fCfl_1~`HDM}Zb5ffks77Xg792uT>&fgQ+!AlOJBID!@^f+jeCDY$|x*n%$j
zf-o3^hGY$kBn1XYgNkH>16YD|1OqV8NS9CuiWCe`Fi4TWgBRh01IP{_0!T0b3_qwy
zmjD0&kVwDq0xw{MOqfVd7==dY5A1LweFOvF0ELM(g$7WCgLH+ikcEI031BFOc|?Y0
z_=R9-B~JJa-yjTLm`7-shHLl&uF!^d$PRcohI+_{Ul@jlM2CI<NJoDNh<y|cf;fn7
z*hg^4h=b&ah7<`~*ocZaNQFR!R49af1O-@#g+=&=pSX#kXoN`E5K1V3N2o}%ID<8K
zgSjY!yx5Dr_=~_8jKVmKGKhnTq=N!zjE01aofwM=af?!DiiSjluxN{qh>5M}gmrj^
zRA_}*sD({9hTHgtaoC7uc#V(<0FnquY<P)zl!<cKgXh?Z9$|=^n26|@5PztKeZ+=@
zNRD@Sk9(Mp2mz1gIF9LP01C;EbVP}R_>Y)aj`xU=bmWQQIESy;N25rJ(nv?Bn2M{2
zjThO28HtI`h!D`2f3?Vk1lbVEI7rOMe=iA0F-eRz>5IqzFbrKV4CZhV^YxSdFoIM-
z1%Px6T2KW;Nd;BF1wDxnKsjF^n3P0GM_z!GSHJ~bzy(%71y)cDPWhBj5tT_f1s6dK
zRbT~Qa1I{94_jabRd5AO36^2mfl^7932_crKn29`5&X~vRe%LsKm}SL5KpOGA0d`Q
zX_p9L3{-FhYUvMsd6vg;3{_AC=kO0e8C52Mm{g#c0x=ANxt4xu1;^kKSU?5FfSDg*
zn0Ymq8d#SN(FIh{1&}$KrRfn`Km}i*njR5Vt?8Pt*_odC51^R^kx7~+k(a4y5|ss&
zBRB=a`48rBmRlg1CP55TfCYrfoSL~<LOGQe!3A73i3PXm5$AvfRp6Dpxtc)9nRH|h
zZn*{JX$)CF1zGTwa_JGA8J+)740-vNT7aI}c?|fOpa0(poq1#qN12pWpao62o%tD*
z&&i*6X$-|+3=dkMa(R;p5uy6Yp&*)qzzJdSun%;k5Ai?``aoeQs-lkM4;K&s7a*Ys
z(V{EbNZc?00ssyd5f7-)4JkTdJ_@At&`ACe07y!s0x_gP%1EFv06NN}2{8^OU;?ZV
z4>t;7RBEMI%1B3=qz$p9SDK}OWD=nu00N)@=rE-v;0s(zrgWrTP{9@dK&5Uvri0{L
z39zRhL8o^5rh~);3oxjJI;ah>rUD@jB_IyHU;^Es5A^^@`M?AZP^p$`sZ3y^ipr>t
z3aOIH1Pu_XqAIGH`VX7hsE-<{ee?hh(5kNLs{cv=4+24@;vf#bu&An<NB(fByjrP2
zNvpPst7XcnullMF@T-d&tm2TXbkqb9@T}1KtSayh*)Xe%>ZYj*Nc+$P5YVmO>a9({
zqqK^xp4vy-`mN~N1nf|!*V?JfN=GJ<3oEb!EbtE6fDnI*r`oz&lVAy-a1EAl4cD*@
z?0TnN3P>gT5h}2-9{~>6P_TfiNV(7gE#Lywnh^0&rTPkC85^;R<PY<@0!sQ19lNoK
z6b==8u^9WKE-GO|+Omt}4;0%1Bm1&&YDn;q5B_kk4WSP{d$W@Cvp_pY@DK$p5Cu|N
zqdyy>2muc80EQ3Cv{E~@R9m(GP@*TAqW?onj5)faJ^G_f8lq1crD3YE2WyjNil%DH
zrUrYX4C#x4TBwA2s0eYY?)nei2#my9tgRZW)>^B#x~zChiiBIZhI_b&i?@pVwiV{A
z(F(28TCMDAt9P5Xz!<OdTCY3{vHHrmz&NofE4fQ*wp$yFC~L8zyQC~zy1|&UJ9`mA
zYqhdFyR<ukH*f<pkh?Mv0~1gKosbYiFa)=oyECx6z5Ba7Q4y=45z5;T?%)p`zybcy
z3YdTiLU6r8&=Aloz0_;H*xL{{Km$fV13wT1jKBzu&<KlQ0SOVl<6FMxo4)IN6GmYZ
zJh2q^tD0dD1|Q)L{_75!KmlL5zyJOFzX9C7J<tP~pa>G+2w`Csm4JgckiZMvzz+--
z5$q6=VHHz>6&(Bz9I(G&00z>_3nq*YnsC4%EW#x04<^hDD6GQ&Fu_0o1eqWK){qTQ
zaUL{m!#J$NCUG8VQ5SFV7jAJDD+~r5&;cd93%h_1P>cWq5yDE$#4hZ_P>c^!ED$$P
z!#~gn!TSgX;SW6Q#f>lli6F)WLB^DE7=}R@exaIH>=C@M3%YQ}TD+Zee8qRH3wg}N
zK=1=!JOP(*3EuDu;Xn@luzy`F$Y)&0hn&cZ+{Qj}3sA8cr(wyp@ei%Ay)InGeT)l#
z+{w}V$##6lqP)d3`~yW$1pjB8#;;%j!0-f<yvnWo%8wAsvs}xwaSQu!3;m$U-a#F|
z{L8_790Gv}CgH@PEXoIv%*%Yrx_}GLj1V}`%0;jUgnS9#01MwB3$=XBt*p(3+|A$2
z%c5}$>Z}~;yw1q{514=tCM?a=OwI1_%<wGFpp44(e9zWg1V(TKM}Wp^Oc4ISA=ezx
z1D(cW%ps<s&JgX+tP#-=Jsm<Y5A)2=)Eo=$PyhmP(HT9>^~}*8Ef6@M&`A&jg*;8{
zaL^`=(kgukEbY<=!Wa;Z8}m^hHm%M$eI6Ih%p$$fB>mCz0Mzx23$ZZNCVd1+(9|)&
z&})p)OzqTAZO|MNAOF6b)omdlTJ6jHLDclT(Xapu9SzpajMQUY)+XK5Nq__~J<~CQ
z18nWqD?LsA5F__d%oGA3dd(O<jSr_h(y=hs^H9=40N5Ix)P!Bq{~*_G?bcPj3U|HM
zkNwmIE!i<rBDZlO8zK-CunqVy5C1#b^H2>0;Mt%p+N15irG45ajRdgm1TjDj)G%(a
z<Or`F+p}HUwvF33;vzBv+(JMB#Ek$5Z~zBT0Lone1hB=!UEIf=+{@kE)|>;uO9V2Y
z13GXBhF}PZ;0V-U($+l$*sa~%?cLx_BtW9xMv{KEa0*8t1BUe8@eN2@k|hFh-%?V$
q{N3OF{oeo{;2Q!y-~?Xa27cfOp5O|;;0)g24*uW}9^nZQ5CA*)3eHCW

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ef88497ccc2f6c2a3a0c5e41f3cbfc7a18ff5329
GIT binary patch
literal 3234
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
RGR}AoOL=)|H48+m{|ju`J$C>A

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.css
new file mode 100644
index 00000000000..df1637f60e6
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.css
@@ -0,0 +1,571 @@
+/*!
+ * Fancytree "Vista" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*
+both:
+   unselected background: #FCFCFC 'nearly white'
+   hover bar (unselected, inactive): #F8FCFE..#EFF9FE (border: #D8F0FA) 'very light blue'
+   active node: #F6FBFD..#D5EFFC (border: #99DEFD)  'light blue'
+   active node with hover: #F2F9FD..#C4E8FA (border: #B6E6FB)
+
+Tree view:
+   active node, tree inactive: #FAFAFB..#E5E5E5 (border: #D9D9D9) 'light gray, selected, but tree not active'
+
+List view:
+   selected bar: --> active bar
+   focus  bar: active + border 1px dotted #090402 (inside the blue border)
+
+   table left/right border: #EDEDED 'light gray'
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-image: url("icons.gif");
+  background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 0px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 3px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 16px;
+  height: 16px;
+  margin-left: 3px;
+  margin-top: 0px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+  background-position: 0px -64px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+  background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+  background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+  background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+  background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+  background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+  background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+  background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+  background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+  background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+  background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+  background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+  background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+  background-position: -48px -96px;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 3px;
+  background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+  background-position: -16px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -32px;
+}
+.fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -32px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -32px -32px;
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+.fancytree-radio span.fancytree-checkbox {
+  background-position: 0px -48px;
+}
+.fancytree-radio span.fancytree-checkbox:hover {
+  background-position: -16px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -48px;
+}
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -48px;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 3px;
+  background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+  background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+  background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+  background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+  background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+  background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+  background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+  background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url('data:image/gif;base64,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');
+  background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+  background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 16px;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 16px;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 3px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+  background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+  background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 32px;
+  position: absolute;
+  background-position: 0px -128px;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 64px;
+  background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+  background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+  background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+  background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+  background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+  border: 1px solid transparent;
+}
+span.fancytree-title:hover {
+  background-color: #F2F7FD;
+  border-color: #B8D6FB;
+}
+span.fancytree-focused span.fancytree-title {
+  background-color: #EFEBDE;
+  outline: 1px dotted gray;
+}
+span.fancytree-selected span.fancytree-title {
+  font-style: italic;
+}
+span.fancytree-active span.fancytree-title {
+  border: 1px solid #99DEFD;
+  background-color: #D8F0FA;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+  background-color: #99DEFD;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+  background-color: royalblue;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  background-color: #99FDDE;
+}
+/*******************************************************************************
+ * 'columnview' extension
+ */
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #ccc;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+  background-color: royalblue;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.less
new file mode 100644
index 00000000000..06d55deb21e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.less
@@ -0,0 +1,112 @@
+/*!
+ * Fancytree "Vista" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+/*
+both:
+   unselected background: #FCFCFC 'nearly white'
+   hover bar (unselected, inactive): #F8FCFE..#EFF9FE (border: #D8F0FA) 'very light blue'
+   active node: #F6FBFD..#D5EFFC (border: #99DEFD)  'light blue'
+   active node with hover: #F2F9FD..#C4E8FA (border: #B6E6FB)
+
+Tree view:
+   active node, tree inactive: #FAFAFB..#E5E5E5 (border: #D9D9D9) 'light gray, selected, but tree not active'
+
+List view:
+   selected bar: --> active bar
+   focus  bar: active + border 1px dotted #090402 (inside the blue border)
+
+   table left/right border: #EDEDED 'light gray'
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: true;  // false: suppress all background images (i.e. icons)
+
+@fancy-hide-connectors: true;
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-line-height: 16px;
+@fancy-icon-spacing: 3px;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+@fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS 
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+  border: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover
+}
+span.fancytree-title:hover {
+   background-color: #F2F7FD; // light blue
+   border-color: #B8D6FB; // darker light blue
+}
+.fancytree-folder span.fancytree-title {
+   // font-weight: bold;
+}
+span.fancytree-focused span.fancytree-title {
+   background-color: #EFEBDE; // gray
+   outline: 1px dotted gray;
+}
+span.fancytree-has-children span.fancytree-title {
+  // font-style: oblique;
+}
+span.fancytree-expanded span.fancytree-title {
+}
+span.fancytree-selected span.fancytree-title {
+   font-style: italic;
+}
+span.fancytree-active span.fancytree-title {
+   border: 1px solid #99DEFD;
+   background-color: #D8F0FA;
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+
+table.fancytree-ext-table {
+   border-collapse: collapse;
+   tbody tr.fancytree-focused {
+      background-color: #99DEFD;
+   }
+   tbody tr.fancytree-active {
+      background-color: royalblue;
+   }
+   tbody tr.fancytree-selected {
+      background-color: #99FDDE;
+   }
+}
+
+/*******************************************************************************
+ * 'columnview' extension
+ */
+
+table.fancytree-ext-columnview {
+   span.fancytree-node.fancytree-expanded {
+      background-color: #ccc;
+   }
+   span.fancytree-node.fancytree-active {
+      background-color: royalblue;
+   }
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.min.css
new file mode 100644
index 00000000000..c11c6489c9a
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-vista/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Vista" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:0}span.fancytree-custom-icon{display:inline-block;margin-left:3px}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(data:image/gif;base64,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);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px;margin:0 0 0 3px;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}span.fancytree-title{border:1px solid transparent}span.fancytree-title:hover{background-color:#F2F7FD;border-color:#B8D6FB}span.fancytree-focused span.fancytree-title{background-color:#EFEBDE;outline:1px dotted gray}span.fancytree-selected span.fancytree-title{font-style:italic}span.fancytree-active span.fancytree-title{border:1px solid #99DEFD;background-color:#D8F0FA}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused{background-color:#99DEFD}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#4169e1}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#99FDDE}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#ccc}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#4169e1}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..65719ccc28fb0b78fbed90cb04341280b4cd6ac0
GIT binary patch
literal 5492
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ef88497ccc2f6c2a3a0c5e41f3cbfc7a18ff5329
GIT binary patch
literal 3234
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
RGR}AoOL=)|H48+m{|ju`J$C>A

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.css
new file mode 100644
index 00000000000..0ef494ab7d8
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.css
@@ -0,0 +1,630 @@
+/*!
+ * Fancytree "Win7" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-image: url("icons.gif");
+  background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 2px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 3px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 16px;
+  height: 16px;
+  margin-left: 3px;
+  margin-top: 2px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+  background-position: 0px -64px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+  background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+  background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+  background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+  background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+  background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+  background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+  background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+  background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+  background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+  background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+  background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+  background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+  background-position: -48px -96px;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 3px;
+  background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+  background-position: -16px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -32px;
+}
+.fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -32px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -32px -32px;
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+.fancytree-radio span.fancytree-checkbox {
+  background-position: 0px -48px;
+}
+.fancytree-radio span.fancytree-checkbox:hover {
+  background-position: -16px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -48px;
+}
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -48px;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 3px;
+  background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+  background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+  background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+  background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+  background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+  background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+  background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+  background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url('data:image/gif;base64,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');
+  background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+  background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 20px;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 20px;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 3px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  -ms-border-radius: 3px;
+  -o-border-radius: 3px;
+  border-radius: 3px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+  background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+  background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 32px;
+  position: absolute;
+  background-position: 0px -128px;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 64px;
+  background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+  background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+  background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+  background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+  background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-active .fancytree-title,
+span.fancytree-selected .fancytree-title {
+  border-color: #d9d9d9;
+  background: #e5e5e5;
+  color: inherit;
+  background: -moz-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafb), color-stop(100%, #e5e5e5));
+  background: -webkit-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+  background: -o-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+  background: -ms-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+  background: linear-gradient(to bottom, #fafafb 0%, #e5e5e5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafb', endColorstr='#e5e5e5', GradientType=0);
+}
+span.fancytree-selected .fancytree-title {
+  font-style: italic;
+}
+.fancytree-treefocus span.fancytree-active .fancytree-title,
+.fancytree-treefocus span.fancytree-selected .fancytree-title {
+  border-color: #99defd;
+  background: #f6fbfd;
+  color: inherit;
+  background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f6fbfd), color-stop(100%, #d5effc));
+  background: -webkit-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: -o-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: -ms-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: linear-gradient(to bottom, #f6fbfd 0%, #d5effc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0);
+}
+.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+  border: 1px solid #719acb;
+}
+span.fancytree-title:hover {
+  border-color: #d8f0fa;
+  background: #f8fcfe;
+  color: inherit;
+  background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8fcfe), color-stop(100%, #eff9fe));
+  background: -webkit-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: -o-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: -ms-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: linear-gradient(to bottom, #f8fcfe 0%, #eff9fe 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0);
+}
+span.fancytree-active .fancytree-title:hover,
+span.fancytree-selected .fancytree-title:hover {
+  border-color: #719acb;
+  background: #f2f9fd;
+  color: inherit;
+  background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f9fd), color-stop(100%, #c4e8fa));
+  background: -webkit-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: -o-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: -ms-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: linear-gradient(to bottom, #f2f9fd 0%, #c4e8fa 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0);
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+  border: 1px solid #ededed;
+}
+table.fancytree-ext-table tbody tr:hover {
+  border-color: inherit;
+  background: #f8fcfe;
+  color: inherit;
+  background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8fcfe), color-stop(100%, #eff9fe));
+  background: -webkit-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: -o-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: -ms-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+  background: linear-gradient(to bottom, #f8fcfe 0%, #eff9fe 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0);
+  outline: 1px solid #d8f0fa;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+  outline: 1px dotted #090402;
+}
+table.fancytree-ext-table tbody span.fancytree-focused span.fancytree-title {
+  outline: solid dotted black;
+}
+table.fancytree-ext-table tbody span.fancytree-title:hover {
+  border: 1px solid transparent;
+  background: inherit;
+  background: transparent;
+  background: none;
+  filter: none;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+  border-color: inherit;
+  background: #f2f9fd;
+  color: inherit;
+  background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f9fd), color-stop(100%, #c4e8fa));
+  background: -webkit-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: -o-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: -ms-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+  background: linear-gradient(to bottom, #f2f9fd 0%, #c4e8fa 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0);
+  outline: 1px solid #B6E6FB;
+}
+table.fancytree-ext-table tbody tr.fancytree-active,
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  border-color: inherit;
+  background: #f6fbfd;
+  color: inherit;
+  background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f6fbfd), color-stop(100%, #d5effc));
+  background: -webkit-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: -o-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: -ms-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+  background: linear-gradient(to bottom, #f6fbfd 0%, #d5effc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0);
+  outline: 1px solid #99DEFD;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.less
new file mode 100644
index 00000000000..24c8414760e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.less
@@ -0,0 +1,152 @@
+/*!
+ * Fancytree "Win7" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Fancytree Win7 styles
+
+// both: 
+//    unselected background: #FCFCFC 'nearly white', no border
+//
+//    hover bar (unselected, inactive): #fcfdfe..#EFF9FE (border: #b8d6fb) 'very light blue'
+//         background: #f8fcfe; //
+//         background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); 
+
+//    active node: #F6FBFD..#D5EFFC (border: #719acb)  'light blue'
+//         background: #f6fbfd; 
+//         background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+
+//    active node with hover: #F2F9FD..#C4E8FA (border: #B6E6FB) 
+//         background: #f2f9fd; 
+//         background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); 
+
+// Tree view:
+//    active node, tree inactive: #FAFAFB..#E5E5E5 (border: #D9D9D9) 'light gray, selected, but tree not active'
+//         background: #fafafb; 
+//         background: -moz-linear-gradient(top, #fafafb 0%, #e5e5e5 100%); 
+
+// List view:
+//    selected bar: --> active bar
+//    focus  bar: active + border 1px dotted #090402 (inside the blue border)
+   
+//    table left/right border: #EDEDED 'light gray'
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: true;      // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: true;
+
+@fancy-line-height: 20px;      // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px;    // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px;      // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 2px;      // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px;     // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 3px;
+@fancy-node-outline-width: 1px;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+@fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS 
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+
+ul.fancytree-container {
+
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+}
+// active nodes inside an UN-focused tree are gray instead of blue
+span.fancytree-active .fancytree-title,
+span.fancytree-selected .fancytree-title {
+    .spanStyleMixin(inherit, #e5e5e5, #d9d9d9, #fafafb, #e5e5e5);
+}
+span.fancytree-selected .fancytree-title {
+    font-style: italic;
+}
+// Markers inside an active tree
+.fancytree-treefocus {
+    span.fancytree-active .fancytree-title,
+    span.fancytree-selected .fancytree-title {
+        .spanStyleMixin(inherit, #f6fbfd, #99defd, #f6fbfd, #d5effc);
+    }
+    span.fancytree-focused span.fancytree-title {
+        border: @fancy-node-border-width solid #719acb;
+    }
+}
+// Hover is always colored (even if tree is inactive)
+span.fancytree-title:hover {
+    .spanStyleMixin(inherit, #f8fcfe, #d8f0fa, #f8fcfe, #eff9fe);
+}
+span.fancytree-active .fancytree-title:hover,
+span.fancytree-selected .fancytree-title:hover {
+    .spanStyleMixin(inherit, #f2f9fd, #719acb, #f2f9fd, #c4e8fa);
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+
+table.fancytree-ext-table tbody {
+  tr td {
+    border: 1px solid #ededed;
+  }
+  tr:hover  {
+    .spanStyleMixin(inherit, #f8fcfe, inherit, #f8fcfe, #eff9fe);
+    outline: 1px solid #d8f0fa;
+  }
+  // tr:hover td {
+  //   outline: 1px solid #D8F0FA;
+  // }
+  tr.fancytree-focused {
+    // background-color: #99DEFD;
+    outline: 1px dotted #090402;
+  }
+  span.fancytree-focused span.fancytree-title {
+    outline: solid dotted black;
+  }
+
+  // Title get's a white background, when hovered. Undo standard node formatting
+  span.fancytree-title:hover {
+    border: 1px solid transparent;
+    background: inherit;
+    background: transparent;
+    background: none;
+    filter: none;
+  }
+
+  tr.fancytree-active:hover,
+  tr.fancytree-selected:hover {
+    .spanStyleMixin(inherit, #f2f9fd, inherit, #f2f9fd, #c4e8fa);
+    outline: 1px solid #B6E6FB;
+  }
+  tr.fancytree-active,
+  tr.fancytree-selected {
+    .spanStyleMixin(inherit, #f6fbfd, inherit, #f6fbfd, #d5effc);
+    outline: 1px solid #99DEFD;
+  }
+  // tr.fancytree-selected .fancytree-title {
+  //   font-style: italic;
+  // }
+
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.min.css
new file mode 100644
index 00000000000..1aaa9e97b58
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win7/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Win7" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:2px}span.fancytree-custom-icon{display:inline-block;margin-left:3px}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(data:image/gif;base64,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);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:20px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:20px;padding:0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}span.fancytree-active .fancytree-title,span.fancytree-selected .fancytree-title{border-color:#d9d9d9;color:inherit;background:-moz-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#fafafb),color-stop(100%,#e5e5e5));background:-webkit-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-o-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-ms-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:linear-gradient(to bottom,#fafafb 0,#e5e5e5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafb', endColorstr='#e5e5e5', GradientType=0)}span.fancytree-selected .fancytree-title{font-style:italic}.fancytree-treefocus span.fancytree-active .fancytree-title,.fancytree-treefocus span.fancytree-selected .fancytree-title{border-color:#99defd;color:inherit;background:-moz-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f6fbfd),color-stop(100%,#d5effc));background:-webkit-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-o-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-ms-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:linear-gradient(to bottom,#f6fbfd 0,#d5effc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0)}.fancytree-treefocus span.fancytree-focused span.fancytree-title{border:1px solid #719acb}span.fancytree-title:hover{border-color:#d8f0fa;color:inherit;background:-moz-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f8fcfe),color-stop(100%,#eff9fe));background:-webkit-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-o-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-ms-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:linear-gradient(to bottom,#f8fcfe 0,#eff9fe 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0)}span.fancytree-active .fancytree-title:hover,span.fancytree-selected .fancytree-title:hover{border-color:#719acb;color:inherit;background:-moz-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f2f9fd),color-stop(100%,#c4e8fa));background:-webkit-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-o-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-ms-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:linear-gradient(to bottom,#f2f9fd 0,#c4e8fa 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0)}table.fancytree-ext-table tbody tr td{border:1px solid #ededed}table.fancytree-ext-table tbody tr:hover{border-color:inherit;color:inherit;background:-moz-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f8fcfe),color-stop(100%,#eff9fe));background:-webkit-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-o-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-ms-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:linear-gradient(to bottom,#f8fcfe 0,#eff9fe 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0);outline:1px solid #d8f0fa}table.fancytree-ext-table tbody tr.fancytree-focused{outline:1px dotted #090402}table.fancytree-ext-table tbody span.fancytree-focused span.fancytree-title{outline:solid dotted #000}table.fancytree-ext-table tbody span.fancytree-title:hover{border:1px solid transparent;background:inherit;background:0 0;background:0 0;filter:none}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{border-color:inherit;color:inherit;background:-moz-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f2f9fd),color-stop(100%,#c4e8fa));background:-webkit-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-o-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-ms-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:linear-gradient(to bottom,#f2f9fd 0,#c4e8fa 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0);outline:1px solid #B6E6FB}table.fancytree-ext-table tbody tr.fancytree-active,table.fancytree-ext-table tbody tr.fancytree-selected{border-color:inherit;color:inherit;background:-moz-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f6fbfd),color-stop(100%,#d5effc));background:-webkit-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-o-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-ms-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:linear-gradient(to bottom,#f6fbfd 0,#d5effc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0);outline:1px solid #99DEFD}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..813eb8385c40a954a85b0fc8379a6446aec3acd8
GIT binary patch
literal 5492
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ef88497ccc2f6c2a3a0c5e41f3cbfc7a18ff5329
GIT binary patch
literal 3234
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
RGR}AoOL=)|H48+m{|ju`J$C>A

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.css
new file mode 100644
index 00000000000..653b54215df
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.css
@@ -0,0 +1,575 @@
+/*!
+ * Fancytree "win8" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-image: url("icons.gif");
+  background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 0px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 3px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 16px;
+  height: 16px;
+  margin-left: 3px;
+  margin-top: 0px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+  background-position: 0px -64px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+  background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+  background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+  background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+  background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+  background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+  background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+  background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+  background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+  background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+  background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+  background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+  background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+  background-position: -48px -96px;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 3px;
+  background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+  background-position: -16px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -32px;
+}
+.fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -32px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -32px -32px;
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+.fancytree-radio span.fancytree-checkbox {
+  background-position: 0px -48px;
+}
+.fancytree-radio span.fancytree-checkbox:hover {
+  background-position: -16px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -48px;
+}
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -48px;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 3px;
+  background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+  background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+  background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+  background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+  background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+  background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+  background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+  background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url('data:image/gif;base64,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');
+  background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+  background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 16px;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 16px;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 3px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+  background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+  background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 32px;
+  position: absolute;
+  background-position: 0px -128px;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 64px;
+  background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+  background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+  background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+  background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+  background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-node {
+  border: 1px solid transparent;
+}
+.fancytree-plain span.fancytree-node:hover {
+  background-color: #E5F3FB;
+  border-color: #70C0E7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused {
+  border-color: #3399FF;
+}
+.fancytree-plain span.fancytree-node.fancytree-active,
+.fancytree-plain span.fancytree-node.fancytree-selected {
+  background-color: #F7F7F7;
+  border-color: #DEDEDE;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active,
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected,
+.fancytree-plain span.fancytree-node.fancytree-active:hover,
+.fancytree-plain span.fancytree-node.fancytree-selected:hover {
+  background-color: #CBE8F6;
+  border-color: #26A0DA;
+}
+.fancytree-plain .fancytree-node.fancytree-selected {
+  font-style: italic;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+  border: 1px solid #EDEDED;
+}
+table.fancytree-ext-table tbody span.fancytree-node,
+table.fancytree-ext-table tbody span.fancytree-node:hover {
+  border: none;
+  background: none;
+}
+table.fancytree-ext-table tbody tr:hover {
+  background-color: #E5F3FB;
+  outline: 1px solid #70C0E7;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {
+  outline: 1px dotted black;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+  background-color: #CBE8F6;
+  outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+  background-color: #F7F7F7;
+  outline: 1px solid #DEDEDE;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  background-color: #F7F7F7;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+  background-color: #CBE8F6;
+  outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+  background-color: #CBE8F6;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.less
new file mode 100644
index 00000000000..a016c788d90
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.less
@@ -0,0 +1,143 @@
+/*!
+ * Fancytree "win8" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Borders have NO radius and NO gradients are used!
+
+// both:
+//    unselected background: white
+//    hover bar (unselected, inactive): #E5F3FB (border: #70C0E7) 'very light blue'
+//    active node: #CBE8F6 (border: #26A0DA)  'light blue'
+//    active node with hover: wie active node
+
+// Tree view:
+//    active node, tree inactive: #F7F7F7 (border: #DEDEDE) 'light gray, selected, but tree not active'
+
+// List view: 
+//    selected bar: --> active bar
+//    focus  bar: transparent(white) + border 1px solid #3399FF  ()
+
+//    table left/right border: #EDEDED 'light gray'
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: true;  // false: suppress all background images (i.e. icons)
+// Set to `true` to inline icon sprite into CSS:
+// @fancy-inline-sprites: true;
+@fancy-hide-connectors: true;
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-line-height: 16px;
+@fancy-icon-spacing: 3px;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+@fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS 
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain  {
+	span.fancytree-node {
+		border: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover
+	}
+	span.fancytree-node:hover {
+		background-color: #E5F3FB;
+		border-color: #70C0E7;
+	}
+	&.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused {
+		border-color: #3399FF;
+	//	outline: 1px solid #3399FF; 
+	}
+	span.fancytree-node.fancytree-active,
+	span.fancytree-node.fancytree-selected { // active/selcted nodes inside inactive tree
+		background-color: #F7F7F7;
+		border-color: #DEDEDE;
+	}
+	&.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active,
+	&.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected,
+	span.fancytree-node.fancytree-active:hover,
+	span.fancytree-node.fancytree-selected:hover {
+		background-color: #CBE8F6;
+		border-color: #26A0DA;
+	}
+	.fancytree-node.fancytree-selected {
+		font-style: italic;
+	}
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody {
+	tr td {
+	  border: 1px solid #EDEDED;
+	}
+	span.fancytree-node,
+	span.fancytree-node:hover { // undo standard tree css
+		border: none;
+		background: none;
+	}
+	// Title get's a white background, when hovered. Undo standard node formatting
+	// span.fancytree-title:hover {
+	//   border: none; //1px solid transparent;
+	//   background: inherit;
+	//   background: transparent;
+	//   background: none;
+	//   filter: none;
+	// }
+	tr:hover  {
+		background-color: #E5F3FB;
+	    outline: 1px solid #70C0E7;
+	}
+	// tr:hover td {
+	//   outline: 1px solid #D8F0FA;
+	// }
+	// tr.fancytree-focused {
+	// 	border-color: #3399FF;
+ //    	outline: 1px dotted black;
+	// }
+	tr.fancytree-focused span.fancytree-title {
+	  outline: 1px dotted black;
+	}
+
+	tr.fancytree-active:hover,
+	tr.fancytree-selected:hover {
+		background-color: #CBE8F6;
+	    outline: 1px solid #26A0DA;
+	}
+	tr.fancytree-active {  // dimmed, if inside inactive tree
+		background-color: #F7F7F7;
+	    outline: 1px solid #DEDEDE;
+	}
+	tr.fancytree-selected {  // dimmed, if inside inactive tree
+		background-color: #F7F7F7;
+	}
+}
+
+table.fancytree-ext-table.fancytree-treefocus tbody {
+	tr.fancytree-active {
+		background-color: #CBE8F6;
+	    outline: 1px solid #26A0DA;
+	}
+	tr.fancytree-selected {
+		background-color: #CBE8F6;
+	}
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.min.css
new file mode 100644
index 00000000000..7b0dffc67e9
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-n/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "win8" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:0}span.fancytree-custom-icon{display:inline-block;margin-left:3px}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(data:image/gif;base64,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);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-plain span.fancytree-node{border:1px solid transparent}.fancytree-plain span.fancytree-node:hover{background-color:#E5F3FB;border-color:#70C0E7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused{border-color:#39F}.fancytree-plain span.fancytree-node.fancytree-active,.fancytree-plain span.fancytree-node.fancytree-selected{background-color:#F7F7F7;border-color:#DEDEDE}.fancytree-plain span.fancytree-node.fancytree-active:hover,.fancytree-plain span.fancytree-node.fancytree-selected:hover,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected{background-color:#CBE8F6;border-color:#26A0DA}.fancytree-plain .fancytree-node.fancytree-selected{font-style:italic}table.fancytree-ext-table tbody tr td{border:1px solid #EDEDED}table.fancytree-ext-table tbody span.fancytree-node,table.fancytree-ext-table tbody span.fancytree-node:hover{border:0;background:0 0}table.fancytree-ext-table tbody tr:hover{background-color:#E5F3FB;outline:1px solid #70C0E7}table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted #000}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{background-color:#CBE8F6;outline:1px solid #26A0DA}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#F7F7F7;outline:1px solid #DEDEDE}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#F7F7F7}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#CBE8F6;outline:1px solid #26A0DA}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#CBE8F6}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4dd72bbe0b93c71eceeb75abe2763bebcd2c64d1
GIT binary patch
literal 20860
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8031e4407ac35ba3f2e75668042a2a6a2069a70f
GIT binary patch
literal 6243
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.css
new file mode 100644
index 00000000000..6b999dd7781
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.css
@@ -0,0 +1,583 @@
+/*!
+ * Fancytree "Win8" 32x32 skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 32px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 32px;
+  height: 32px;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-image: url("icons.gif");
+  background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 0px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 6px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 32px;
+  height: 32px;
+  margin-left: 6px;
+  margin-top: 0px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+  background-position: 0px -128px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+  background-position: -32px -128px;
+}
+.fancytree-exp-c span.fancytree-expander {
+  background-position: 0px -160px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+  background-position: -32px -160px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+  background-position: 0px -192px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+  background-position: -32px -192px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+  background-position: -128px -160px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+  background-position: -160px -160px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+  background-position: -128px -192px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+  background-position: -160px -192px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+  background-position: -64px -160px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+  background-position: -96px -160px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+  background-position: -64px -192px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+  background-position: -96px -192px;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 6px;
+  background-position: 0px -64px;
+}
+span.fancytree-checkbox:hover {
+  background-position: -32px -64px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+  background-position: -128px -64px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -160px -64px;
+}
+.fancytree-selected span.fancytree-checkbox {
+  background-position: -64px -64px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -96px -64px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -64px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -128px -64px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -64px -64px;
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+.fancytree-radio span.fancytree-checkbox {
+  background-position: 0px -96px;
+}
+.fancytree-radio span.fancytree-checkbox:hover {
+  background-position: -32px -96px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
+  background-position: -128px -96px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -160px -96px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox {
+  background-position: -64px -96px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -96px -96px;
+}
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -96px;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 6px;
+  background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+  background-position: -64px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -96px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+  background-position: -128px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+  background-position: -160px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+  background-position: 0px -32px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -32px -32px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+  background-position: -64px -32px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -96px -32px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+  background-position: -128px -32px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+  background-position: -160px -32px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url('data:image/gif;base64,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');
+  background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+  background-position: 0px -224px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 32px;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 32px;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 6px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+  background-position: -64px -224px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+  background-position: -32px -224px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 64px;
+  position: absolute;
+  background-position: 0px -256px;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 128px;
+  background-position: 0px -288px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+  background-position: -128px -256px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+  background-position: -64px -256px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+  background-position: 0px -160px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+  background-position: -32px -160px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-title {
+  border: 1px solid transparent;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+  border-color: #3399ff;
+}
+.fancytree-plain span.fancytree-active span.fancytree-title,
+.fancytree-plain span.fancytree-selected span.fancytree-title {
+  background-color: #f7f7f7;
+  border-color: #dedede;
+}
+.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title {
+  font-style: italic;
+}
+.fancytree-plain span.fancytree-node:hover span.fancytree-title {
+  background-color: #eff9fe;
+  border-color: #70c0e7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title {
+  background-color: #cbe8f6;
+  border-color: #26a0da;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+  border: 1px solid #EDEDED;
+}
+table.fancytree-ext-table tbody span.fancytree-node,
+table.fancytree-ext-table tbody span.fancytree-node:hover {
+  border: none;
+  background: none;
+}
+table.fancytree-ext-table tbody tr:hover {
+  background-color: #E5F3FB;
+  outline: 1px solid #70C0E7;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {
+  outline: 1px dotted black;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+  background-color: #CBE8F6;
+  outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+  background-color: #F7F7F7;
+  outline: 1px solid #DEDEDE;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  background-color: #F7F7F7;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+  background-color: #CBE8F6;
+  outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+  background-color: #CBE8F6;
+}
+ul.fancytree-container {
+  font-size: 20pt;
+  padding: 6px;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.less
new file mode 100644
index 00000000000..139d9314897
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.less
@@ -0,0 +1,37 @@
+/*!
+ * Fancytree "Win8" 32x32 skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+// Import standard win8
+@import "../skin-win8/ui.fancytree.less";
+
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: true;      // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: true;
+
+@fancy-level-indent: 32px;
+@fancy-line-height: 32px;      // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px;    // gap between two node borders
+@fancy-icon-width: 32px;
+@fancy-icon-height: 32px;
+@fancy-icon-spacing: 6px;      // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px;      // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px;     // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+ul.fancytree-container {
+//	font-family: tahoma, arial, helvetica;
+	font-size: 20pt;
+	padding: 6px;
+}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.min.css
new file mode 100644
index 00000000000..57542b7cbe0
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8-xxl/ui.fancytree.min.css
@@ -0,0 +1,11 @@
+/*!
+ * Fancytree "Win8" 32x32 skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;white-space:nowrap;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 32px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:32px;height:32px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:0}span.fancytree-custom-icon{display:inline-block;margin-left:6px}img.fancytree-icon{width:32px;height:32px;margin-left:6px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -128px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-32px -128px}.fancytree-exp-c span.fancytree-expander{background-position:0 -160px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-32px -160px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -192px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-32px -192px}.fancytree-exp-cd span.fancytree-expander{background-position:-128px -160px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-160px -160px}.fancytree-exp-cdl span.fancytree-expander{background-position:-128px -192px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-160px -192px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-64px -160px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-96px -160px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-64px -192px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-96px -192px}span.fancytree-checkbox{margin-left:6px;background-position:0 -64px}span.fancytree-checkbox:hover{background-position:-32px -64px}.fancytree-partsel span.fancytree-checkbox{background-position:-128px -64px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-160px -64px}.fancytree-selected span.fancytree-checkbox{background-position:-64px -64px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-96px -64px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -64px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-128px -64px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-64px -64px}.fancytree-radio span.fancytree-checkbox{background-position:0 -96px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-32px -96px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-128px -96px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-160px -96px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-64px -96px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-96px -96px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -96px}span.fancytree-icon{margin-left:6px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-64px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-96px 0}.fancytree-ico-e span.fancytree-icon{background-position:-128px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-160px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -32px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-32px -32px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-64px -32px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-96px -32px}.fancytree-ico-ef span.fancytree-icon{background-position:-128px -32px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-160px -32px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(data:image/gif;base64,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);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -224px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:32px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:32px;padding:0 3px;margin:0 0 0 6px;border:1px solid transparent;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-64px -224px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-32px -224px}#fancytree-drop-marker{width:64px;position:absolute;background-position:0 -256px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:128px;background-position:0 -288px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-128px -256px}#fancytree-drop-marker.fancytree-drop-move{background-position:-64px -256px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -160px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-32px -160px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-plain span.fancytree-title{border:1px solid transparent}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title{border-color:#39f}.fancytree-plain span.fancytree-active span.fancytree-title,.fancytree-plain span.fancytree-selected span.fancytree-title{background-color:#f7f7f7;border-color:#dedede}.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title{font-style:italic}.fancytree-plain span.fancytree-node:hover span.fancytree-title{background-color:#eff9fe;border-color:#70c0e7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title{background-color:#cbe8f6;border-color:#26a0da}table.fancytree-ext-table tbody tr td{border:1px solid #EDEDED}table.fancytree-ext-table tbody span.fancytree-node,table.fancytree-ext-table tbody span.fancytree-node:hover{border:0;background:0 0}table.fancytree-ext-table tbody tr:hover{background-color:#E5F3FB;outline:1px solid #70C0E7}table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted #000}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{background-color:#CBE8F6;outline:1px solid #26A0DA}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#F7F7F7;outline:1px solid #DEDEDE}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#F7F7F7}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#CBE8F6;outline:1px solid #26A0DA}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#CBE8F6}ul.fancytree-container{font-size:20pt;padding:6px}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..813eb8385c40a954a85b0fc8379a6446aec3acd8
GIT binary patch
literal 5492
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ef88497ccc2f6c2a3a0c5e41f3cbfc7a18ff5329
GIT binary patch
literal 3234
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
RGR}AoOL=)|H48+m{|ju`J$C>A

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.css
new file mode 100644
index 00000000000..e14b5c29f17
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.css
@@ -0,0 +1,573 @@
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-image: url("icons.gif");
+  background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 2px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 3px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 16px;
+  height: 16px;
+  margin-left: 3px;
+  margin-top: 2px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  background-image: none;
+  cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+  background-position: 0px -64px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+  background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+  background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+  background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+  background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+  background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+  background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+  background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+  background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+  background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+  background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+  background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+  background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+  background-position: -48px -96px;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 3px;
+  background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+  background-position: -16px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -32px;
+}
+.fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -32px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -32px -32px;
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+.fancytree-radio span.fancytree-checkbox {
+  background-position: 0px -48px;
+}
+.fancytree-radio span.fancytree-checkbox:hover {
+  background-position: -16px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -48px;
+}
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -48px;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 3px;
+  background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+  background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+  background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+  background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+  background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+  background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+  background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+  background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url('data:image/gif;base64,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');
+  background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+  background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 0px;
+  min-height: 20px;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 20px;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 3px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+  background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+  background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 32px;
+  position: absolute;
+  background-position: 0px -128px;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 64px;
+  background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+  background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+  background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+  background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+  background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-title {
+  border: 1px solid transparent;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+  border-color: #3399ff;
+}
+.fancytree-plain span.fancytree-active span.fancytree-title,
+.fancytree-plain span.fancytree-selected span.fancytree-title {
+  background-color: #f7f7f7;
+  border-color: #dedede;
+}
+.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title {
+  font-style: italic;
+}
+.fancytree-plain span.fancytree-node:hover span.fancytree-title {
+  background-color: #eff9fe;
+  border-color: #70c0e7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title {
+  background-color: #cbe8f6;
+  border-color: #26a0da;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+  border: 1px solid #EDEDED;
+}
+table.fancytree-ext-table tbody span.fancytree-node,
+table.fancytree-ext-table tbody span.fancytree-node:hover {
+  border: none;
+  background: none;
+}
+table.fancytree-ext-table tbody tr:hover {
+  background-color: #E5F3FB;
+  outline: 1px solid #70C0E7;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {
+  outline: 1px dotted black;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+  background-color: #CBE8F6;
+  outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+  background-color: #F7F7F7;
+  outline: 1px solid #DEDEDE;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  background-color: #F7F7F7;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+  background-color: #CBE8F6;
+  outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+  background-color: #CBE8F6;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.less
new file mode 100644
index 00000000000..acdf2ee3263
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.less
@@ -0,0 +1,153 @@
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Borders have NO radius and NO gradients are used!
+
+// both:
+//    unselected background: white
+//    hover bar (unselected, inactive): #E5F3FB (border: #70C0E7) 'very light blue'
+//    active node: #CBE8F6 (border: #26A0DA)  'light blue'
+//    active node with hover: wie active node
+
+// Tree view:
+//    active node, tree inactive: #F7F7F7 (border: #DEDEDE) 'light gray, selected, but tree not active'
+
+// List view: 
+//    selected bar: --> active bar
+//    focus  bar: transparent(white) + border 1px solid #3399FF  ()
+
+//    table left/right border: #EDEDED 'light gray'
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: true;      // false: suppress all background images (i.e. icons)
+
+@fancy-hide-connectors: true;
+
+@fancy-line-height: 20px;      // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 0px;    // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px;      // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 2px;      // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px;     // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+
+// @fancy-icon-width: 16px;
+// @fancy-icon-height: 16px;
+// @fancy-line-height: 16px;
+// @fancy-icon-spacing: 3px;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+@fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS 
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain  {
+	span.fancytree-title {
+		border: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover
+	}
+	&.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+		border-color: #3399ff;
+	}
+	span.fancytree-active span.fancytree-title,
+	span.fancytree-selected span.fancytree-title { // active/selcted nodes inside inactive tree
+		background-color: #f7f7f7;
+		border-color: #dedede;
+	}
+	span.fancytree-node span.fancytree-selected span.fancytree-title {
+		font-style: italic;
+	}
+	span.fancytree-node:hover span.fancytree-title {
+		background-color: #eff9fe; // hover is always colored, even if tree is unfocused
+		border-color: #70c0e7;
+	}
+	&.fancytree-container.fancytree-treefocus {
+		span.fancytree-active span.fancytree-title,
+		span.fancytree-selected span.fancytree-title {
+			background-color: #cbe8f6;
+			border-color: #26a0da;
+		}
+	}
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody {
+	tr td {
+	  border: 1px solid #EDEDED;
+	}
+	span.fancytree-node,
+	span.fancytree-node:hover { // undo standard tree css
+		border: none;
+		background: none;
+	}
+	// Title get's a white background, when hovered. Undo standard node formatting
+	// span.fancytree-title:hover {
+	//   border: none; //1px solid transparent;
+	//   background: inherit;
+	//   background: transparent;
+	//   background: none;
+	//   filter: none;
+	// }
+	tr:hover  {
+		background-color: #E5F3FB;
+	    outline: 1px solid #70C0E7;
+	}
+	// tr:hover td {
+	//   outline: 1px solid #D8F0FA;
+	// }
+	// tr.fancytree-focused {
+	// 	border-color: #3399FF;
+ //    	outline: 1px dotted black;
+	// }
+	tr.fancytree-focused span.fancytree-title {
+	  outline: 1px dotted black;
+	}
+
+	tr.fancytree-active:hover,
+	tr.fancytree-selected:hover {
+		background-color: #CBE8F6;
+	    outline: 1px solid #26A0DA;
+	}
+	tr.fancytree-active {  // dimmed, if inside inactive tree
+		background-color: #F7F7F7;
+	    outline: 1px solid #DEDEDE;
+	}
+	tr.fancytree-selected {  // dimmed, if inside inactive tree
+		background-color: #F7F7F7;
+	}
+}
+
+table.fancytree-ext-table.fancytree-treefocus tbody {
+	tr.fancytree-active {
+		background-color: #CBE8F6;
+	    outline: 1px solid #26A0DA;
+	}
+	tr.fancytree-selected {
+		background-color: #CBE8F6;
+	}
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.min.css
new file mode 100644
index 00000000000..b6b298bdd0b
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-win8/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:2px}span.fancytree-custom-icon{display:inline-block;margin-left:3px}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(data:image/gif;base64,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);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:0;min-height:20px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:20px;padding:0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-plain span.fancytree-title{border:1px solid transparent}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title{border-color:#39f}.fancytree-plain span.fancytree-active span.fancytree-title,.fancytree-plain span.fancytree-selected span.fancytree-title{background-color:#f7f7f7;border-color:#dedede}.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title{font-style:italic}.fancytree-plain span.fancytree-node:hover span.fancytree-title{background-color:#eff9fe;border-color:#70c0e7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title{background-color:#cbe8f6;border-color:#26a0da}table.fancytree-ext-table tbody tr td{border:1px solid #EDEDED}table.fancytree-ext-table tbody span.fancytree-node,table.fancytree-ext-table tbody span.fancytree-node:hover{border:0;background:0 0}table.fancytree-ext-table tbody tr:hover{background-color:#E5F3FB;outline:1px solid #70C0E7}table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted #000}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{background-color:#CBE8F6;outline:1px solid #26A0DA}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#F7F7F7;outline:1px solid #DEDEDE}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#F7F7F7}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#CBE8F6;outline:1px solid #26A0DA}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#CBE8F6}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/icons-rtl.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/icons-rtl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a29b5fbc967378b8665df3513f4d8cf648f73809
GIT binary patch
literal 4046
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/icons.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/icons.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a58eb93f12a2c63382d6b47f070fa03ffec7fd5f
GIT binary patch
literal 4041
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

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/loading.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..251df0544cd63db56160b5a53c9e203999a561e6
GIT binary patch
literal 570
zcmZ?wbhEHb6krfwSj5Tz21}is{<pOJKX&XGgbySY|8x7fh6Fo12DlpO889<~gnqKH
zaxt(n=ztV~v@<YkMeMq>PSHlpTQ%ic>s*20?KO#JbB`J<SafRE3uUX~K;!MauT|%p
z?~hPsL}+JZU}E5AU<Ya!iO>oX<Xg8aNpf*k>-PVwjtvhv)DQ}p7#JCNfEF?^3rDO{
z`kg!_%&DO$()C1j*!N6FCWJZ`pgL{_4xl=*2&=_$Eh1qp1s`u759OHqxi!UnQaqAU
zcA!#rpkkoi9wBF<l1;?Yg%2g2j(iYr&YI|qWH%Skk*q-5!3x*>Np|>|CHN@uv{OZ#
zV43`6q`+WjU;$bUHZfwA%kH-)E!nmfb1nSIbx^$N(G(<wEMSWv-rnVX<ibJE(-K!7
z3Cs}S4)3@>2}vOn0~gfWLK1;@d|WKqXXYeZXu6yfzU<41@HNCEU|$23t=045OkcT;
z;~__8v>{Kcdao~%ubF^ug!o!mBJj*D13gJ?VWlK%w>PYgE=fr0KrsXHv~Yyf!lUbT
TUrrHtcg?o#wX~xJP@OdZ_UVjb

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.css
new file mode 100644
index 00000000000..e582778282c
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.css
@@ -0,0 +1,562 @@
+/*!
+ * Fancytree "XP" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ ******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.ui-helper-hidden {
+  display: none;
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+  font-family: tahoma, arial, helvetica;
+  font-size: 10pt;
+  white-space: nowrap;
+  padding: 3px;
+  margin: 0;
+  background-color: white;
+  border: 1px dotted gray;
+  overflow: auto;
+  min-height: 0%;
+  position: relative;
+}
+ul.fancytree-container ul {
+  padding: 0 0 0 16px;
+  margin: 0;
+}
+ul.fancytree-container li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+  opacity: 0.5;
+  background-color: silver;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: top;
+  background-repeat: no-repeat;
+  background-position: left;
+  background-image: url("icons.gif");
+  background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-radio,
+span.fancytree-custom-icon {
+  margin-top: 0px;
+}
+/* Used by iconclass option and iconClass callback: */
+span.fancytree-custom-icon {
+  display: inline-block;
+  margin-left: 3px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+  width: 16px;
+  height: 16px;
+  margin-left: 3px;
+  margin-top: 0px;
+  vertical-align: top;
+  border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+  cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+  cursor: default;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+  background-position: 0px -64px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+  background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+  background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+  background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+  background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+  background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+  background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+  background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+  background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+  background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+  background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+  background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+  background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+  background-position: -48px -96px;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+  margin-left: 3px;
+  background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+  background-position: -16px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -32px;
+}
+.fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -32px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -32px -32px;
+}
+/*------------------------------------------------------------------------------
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'fancytree-radio' in the tree options.
+ *----------------------------------------------------------------------------*/
+.fancytree-radio span.fancytree-checkbox {
+  background-position: 0px -48px;
+}
+.fancytree-radio span.fancytree-checkbox:hover {
+  background-position: -16px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
+  background-position: -64px -48px;
+}
+.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
+  background-position: -80px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox {
+  background-position: -32px -48px;
+}
+.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
+  background-position: -48px -48px;
+}
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
+.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
+  background-position: 0px -48px;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ *		 so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+  margin-left: 3px;
+  background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+  background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+  background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+  background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+  background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+  background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+  background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+  background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+  background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+  background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-wait span.fancytree-icon,
+.fancytree-statusnode-wait span.fancytree-icon:hover {
+  background-image: url('data:image/gif;base64,R0lGODlhEAAQAKIFAAAAAAAApUJC/4SE/8bGxgAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAFACwAAAAAEAAQAAADKli63K4hPBZLJWTWhZ0QU7d8YTadxTCgosqa6CM6c1Eztw3rJZ83v1gjAQAh+QQFCgAFACwBAAIACwAHAAADFFgqUhEOrqZiGaNqhbf/BUGA4QgmACH5BAUKAAUALAIAAQAMAAUAAAMTWKoi+2OUVkKAcllFyHtW92lBAgAh+QQFCgAFACwEAAEACwAIAAADFlg6o16EFFaEcPHZx1UInfOFZDeSXwIAIfkEBQoABQAsBwABAAcACwAAAxRIVMxaYzQWZxPCYstZ4F83BWFDJgAh+QQFCgAFACwKAAIABQAMAAADFEhUrPxjQPlqEeJhy0J4XhF2H5MAACH5BAUKAAUALAcABAAIAAsAAAMUWKpEu+3JOQa1cwqh+QrBF4LilAAAIfkEBQoABQAsBAAHAAsABwAAAxRYukvE0MFJyxjV4hCYEAtXiN+SAAAh+QQFCgAFACwCAAoADAAFAAADEhhR3ExEOQeZbGM4KUTJE9NNCQAh+QQFCgAFACwBAAcACwAIAAADFhhR3K0uSglnqbYI4QhpWzEMhSeNTQIAIfkEBQoABQAsAgAEAAcACwAAAxMYUczaMC4ZKxMiYjtG7AVBRGICACH5BAUKAAUALAEAAgAFAAwAAAMTWBqhxa8t6ZQQ7tY9husbQThiAgA7');
+  background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+  background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+  /* See #117 */
+  display: inherit;
+  width: 100%;
+  margin-top: 1px;
+  min-height: 16px;
+}
+span.fancytree-title {
+  color: #000000;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  min-height: 16px;
+  padding: 0 3px 0 3px;
+  margin: 0px 0 0 3px;
+  border: 0 solid transparent;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -ms-border-radius: 0px;
+  -o-border-radius: 0px;
+  border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+  color: #ff0000;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  display: inline-block;
+  color: #fff;
+  background: #337ab7;
+  border: 1px solid gray;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+  position: absolute;
+  top: -6px;
+  right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+  background: #5cb85c;
+  border: none;
+  font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+  background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+  background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+  width: 32px;
+  position: absolute;
+  background-position: 0px -128px;
+  margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+  width: 64px;
+  background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+  background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+  background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+  opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table span.fancytree-node {
+  display: inline-block;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+  position: relative;
+  border: 1px solid gray;
+  vertical-align: top;
+  overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+  padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+  list-style-image: none;
+  list-style-position: outside;
+  list-style-type: none;
+  -moz-background-clip: border;
+  -moz-background-inline-policy: continuous;
+  -moz-background-origin: padding;
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: 0px 0px;
+  background-repeat: repeat-y;
+  background-image: none;
+  /* no v-lines */
+  margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+  position: relative;
+  /* allow positioning of embedded spans */
+  display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+  background-color: #CBE8F6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+  position: absolute;
+  right: 3px;
+  background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+  background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+  display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+  color: #c0c0c0;
+  font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+  color: black;
+  font-weight: normal;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon {
+  position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+  color: #fff;
+  background: #777;
+  border: 1px solid gray;
+  position: absolute;
+  top: -6px;
+  right: -6px;
+  min-width: 10px;
+  height: 10px;
+  line-height: 1;
+  vertical-align: baseline;
+  border-radius: 10px;
+  padding: 2px;
+  text-align: center;
+  font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+  position: relative;
+  min-width: 100%;
+  z-index: 2;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+  position: relative;
+  z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+  position: absolute;
+  z-index: 1;
+  left: 0px;
+  width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Tree container
+ */
+ul.fancytree-container li {
+  background-image: url("vline.gif");
+  background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+  background-image: none;
+}
+ul.fancytree-no-connector > li {
+  background-image: none;
+}
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+  border: 0 solid transparent;
+}
+span.fancytree-title:hover {
+  background-color: #F2F7FD;
+  border-color: #B8D6FB;
+}
+span.fancytree-focused span.fancytree-title {
+  outline: 1px dotted black;
+  background-color: #EFEBDE;
+}
+.fancytree-folder span.fancytree-title {
+  font-weight: bold;
+}
+.fancytree-selected span.fancytree-title {
+  color: green;
+  font-style: italic;
+}
+.fancytree-active span.fancytree-title {
+  background-color: #3169C6 !important;
+  color: white !important;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+  border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+  background-color: #99DEFD;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+  background-color: royalblue;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+  background-color: #99FDDE;
+}
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.less b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.less
new file mode 100644
index 00000000000..71aab080514
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.less
@@ -0,0 +1,96 @@
+/*!
+ * Fancytree "XP" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Override the variable after the import. 
+// NOTE: Variables are always resolved as the last definition, even if it is 
+// after where it is used.
+@fancy-use-sprites: true;      // false: suppress all background images (i.e. icons)
+@fancy-hide-connectors: false; // true: show vertical connector lines
+
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px;
+@fancy-node-border-width: 0;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+@fancy-loading-url: data-uri("@{fancy-image-dir}/loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS 
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+
+/*******************************************************************************
+ * Tree container
+ */
+ul.fancytree-container {
+	li {
+		background-image: url("vline.gif");
+		background-position: 0 0;
+	}
+	// Suppress lines for last child node
+	li.fancytree-lastsib {
+		background-image: none;
+	}
+}
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+	background-image: none;
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+
+span.fancytree-title {
+  border: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover
+}
+span.fancytree-title:hover {
+	background-color: #F2F7FD; // light blue
+	border-color: #B8D6FB; // darker light blue
+}
+span.fancytree-focused span.fancytree-title {
+	outline: 1px dotted black;
+	background-color: #EFEBDE; // gray
+}
+.fancytree-folder span.fancytree-title {
+	font-weight: bold;
+}
+.fancytree-selected span.fancytree-title {
+	color: green;
+	font-style: italic;
+}
+.fancytree-active span.fancytree-title {
+	background-color: #3169C6 !important;
+	color: white !important; // @ IE6 
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+	border-collapse: collapse;
+	tbody tr.fancytree-focused {
+		background-color: #99DEFD;
+	}
+	tbody tr.fancytree-active {
+		background-color: royalblue;
+	}
+	tbody tr.fancytree-selected {
+		background-color: #99FDDE;
+	}
+}
+
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.min.css b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.min.css
new file mode 100644
index 00000000000..3b24c0a784f
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "XP" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-repeat:repeat-y;margin:0}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:0}span.fancytree-custom-icon{display:inline-block;margin-left:3px}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(data:image/gif;base64,R0lGODlhEAAQAKIFAAAAAAAApUJC/4SE/8bGxgAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAFACwAAAAAEAAQAAADKli63K4hPBZLJWTWhZ0QU7d8YTadxTCgosqa6CM6c1Eztw3rJZ83v1gjAQAh+QQFCgAFACwBAAIACwAHAAADFFgqUhEOrqZiGaNqhbf/BUGA4QgmACH5BAUKAAUALAIAAQAMAAUAAAMTWKoi+2OUVkKAcllFyHtW92lBAgAh+QQFCgAFACwEAAEACwAIAAADFlg6o16EFFaEcPHZx1UInfOFZDeSXwIAIfkEBQoABQAsBwABAAcACwAAAxRIVMxaYzQWZxPCYstZ4F83BWFDJgAh+QQFCgAFACwKAAIABQAMAAADFEhUrPxjQPlqEeJhy0J4XhF2H5MAACH5BAUKAAUALAcABAAIAAsAAAMUWKpEu+3JOQa1cwqh+QrBF4LilAAAIfkEBQoABQAsBAAHAAsABwAAAxRYukvE0MFJyxjV4hCYEAtXiN+SAAAh+QQFCgAFACwCAAoADAAFAAADEhhR3ExEOQeZbGM4KUTJE9NNCQAh+QQFCgAFACwBAAcACwAIAAADFhhR3K0uSglnqbYI4QhpWzEMhSeNTQIAIfkEBQoABQAsAgAEAAcACwAAAxMYUczaMC4ZKxMiYjtG7AVBRGICACH5BAUKAAUALAEAAgAFAAwAAAMTWBqhxa8t6ZQQ7tY9husbQThiAgA7);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px;margin:0 0 0 3px;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:0;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-container li{background-image:url(vline.gif);background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}span.fancytree-title{border:0 solid transparent}span.fancytree-title:hover{background-color:#F2F7FD;border-color:#B8D6FB}span.fancytree-focused span.fancytree-title{outline:1px dotted #000;background-color:#EFEBDE}.fancytree-folder span.fancytree-title{font-weight:700}.fancytree-selected span.fancytree-title{color:green;font-style:italic}.fancytree-active span.fancytree-title{background-color:#3169C6!important;color:#fff!important}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused{background-color:#99DEFD}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#4169e1}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#99FDDE}
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/vline-rtl.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/vline-rtl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0400cb3eeace6abda62ae41957f3e41907a3aa6b
GIT binary patch
literal 842
zcmZ?wbhEHb6krfw_|5<V4Pe{=rW$~}hK2(`aOc3XQy>2S|G#wUQXn}BMnhnzhQRL+
z3l=PCXlVEkOy~a@{(~tX4P*g<;!hSv28MqOIzUNaju2pA;817y%PHgWLGEBPhp^U{
h^n!(l+j-@^TqFt?xweTLhn?Y=xcF$VBr_9(H2~DE@*DsF

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/vline.gif b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/skin-xp/vline.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1b00ae50e0f1538d985811207b0af2a85d1d128b
GIT binary patch
literal 844
zcmZ?wbhEHb6krfw_|5<V4Pe{=rW$~}hK2(`aOc3XQy>2S|G#wUQXn}BMnhnzhQRL+
z3l=PCXlVEkOy~a@{(~tX4P*g<;!hSv28MqOIzUNaju2pA;Lv3F%PCTkzu;gqhp>{)
jiVX`7H}c4P#aL`ybg)BAJ?YGk0_Edva`s$291PX~%%k&-

literal 0
HcmV?d00001

diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.childcounter.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.childcounter.js
new file mode 100644
index 00000000000..2f2e0e04b9e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.childcounter.js
@@ -0,0 +1,208 @@
+// Extending Fancytree
+// ===================
+//
+// See also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code.
+//
+// Every extension should have a comment header containing some information
+// about the author, copyright and licensing. Also a pointer to the latest
+// source code.
+// Prefix with `/*!` so the comment is not removed by the minifier.
+
+/*!
+ * jquery.fancytree.childcounter.js
+ *
+ * Add a child counter bubble to tree nodes.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+// To keep the global namespace clean, we wrap everything in a closure
+
+;(function($, undefined) {
+
+// Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
+"use strict";
+
+// The [coding guidelines](http://contribute.jquery.org/style-guide/js/)
+// require jshint compliance.
+// But for this sample, we want to allow unused variables for demonstration purpose.
+
+/*jshint unused:false */
+
+
+// Adding methods
+// --------------
+
+// New member functions can be added to the `Fancytree` class.
+// This function will be available for every tree instance:
+//
+//     var tree = $("#tree").fancytree("getTree");
+//     tree.countSelected(false);
+
+$.ui.fancytree._FancytreeClass.prototype.countSelected = function(topOnly){
+	var tree = this,
+		treeOptions = tree.options;
+
+	return tree.getSelectedNodes(topOnly).length;
+};
+
+
+// The `FancytreeNode` class can also be easily extended. This would be called
+// like
+//     node.updateCounters();
+//
+// It is also good practice to add a docstring comment.
+/**
+ * [ext-childcounter] Update counter badges for `node` and its parents.
+ * May be called in the `loadChildren` event, to update parents of lazy loaded
+ * nodes.
+ * @alias FancytreeNode#updateCounters
+ * @requires jquery.fancytree.childcounters.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.updateCounters = function(){
+	var node = this,
+		$badge = $("span.fancytree-childcounter", node.span),
+		extOpts = node.tree.options.childcounter,
+		count = node.countChildren(extOpts.deep);
+
+	node.data.childCounter = count;
+	if( (count || !extOpts.hideZeros) && (!node.isExpanded() || !extOpts.hideExpanded) ) {
+		if( !$badge.length ) {
+			$badge = $("<span class='fancytree-childcounter'/>").appendTo($("span.fancytree-icon", node.span));
+		}
+		$badge.text(count);
+	} else {
+		$badge.remove();
+	}
+	if( extOpts.deep && !node.isTopLevel() && !node.isRoot() ) {
+		node.parent.updateCounters();
+	}
+};
+
+
+// Finally, we can extend the widget API and create functions that are called
+// like so:
+//
+//     $("#tree").fancytree("widgetMethod1", "abc");
+
+$.ui.fancytree.prototype.widgetMethod1 = function(arg1){
+	var tree = this.tree;
+	return arg1;
+};
+
+
+// Register a Fancytree extension
+// ------------------------------
+// A full blown extension, extension is available for all trees and can be
+// enabled like so (see also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html)):
+//
+//    <script src="../src/jquery.fancytree.js" type="text/javascript"></script>
+//    <script src="../src/jquery.fancytree.childcounter.js" type="text/javascript"></script>
+//    ...
+//
+//     $("#tree").fancytree({
+//         extensions: ["childcounter"],
+//         childcounter: {
+//             hideExpanded: true
+//         },
+//         ...
+//     });
+//
+
+
+/* 'childcounter' extension */
+$.ui.fancytree.registerExtension({
+// Every extension must be registered by a unique name.
+	name: "childcounter",
+// Version information should be compliant with [semver](http://semver.org)
+	version: "1.0.0",
+
+// Extension specific options and their defaults.
+// This options will be available as `tree.options.childcounter.hideExpanded`
+
+	options: {
+		deep: true,
+		hideZeros: true,
+		hideExpanded: false
+	},
+
+// Attributes other than `options` (or functions) can be defined here, and
+// will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`.
+// They can also be accessed as `this._local.foo` from within the extension
+// methods.
+	foo: 42,
+
+// Local functions are prefixed with an underscore '_'.
+// Callable as `this._local._appendCounter()`.
+
+	_appendCounter: function(bar){
+		var tree = this;
+	},
+
+// **Override virtual methods for this extension.**
+//
+// Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'.
+// with a `ctx` argument (see [EventData](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/global.html#EventData)
+// for details) and an extended calling context:<br>
+// `this`       : the Fancytree instance<br>
+// `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br>
+// `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
+//
+// See also the [complete list of available hook functions](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html).
+
+	/* Init */
+// `treeInit` is triggered when a tree is initalized. We can set up classes or
+// bind event handlers here...
+	treeInit: function(ctx){
+		var tree = this, // same as ctx.tree,
+			opts = ctx.options,
+			extOpts = ctx.options.childcounter;
+// Optionally check for dependencies with other extensions
+		/* this._requireExtension("glyph", false, false); */
+// Call the base implementation
+		this._superApply(arguments);
+// Add a class to the tree container
+		this.$container.addClass("fancytree-ext-childcounter");
+	},
+
+// Destroy this tree instance (we only call the default implementation, so
+// this method could as well be omitted).
+
+	treeDestroy: function(ctx){
+		this._superApply(arguments);
+	},
+
+// Overload the `renderTitle` hook, to append a counter badge
+	nodeRenderTitle: function(ctx, title) {
+		var node = ctx.node,
+			extOpts = ctx.options.childcounter,
+			count = (node.data.childCounter == null) ? node.countChildren(extOpts.deep) : +node.data.childCounter;
+// Let the base implementation render the title
+		this._superApply(arguments);
+// Append a counter badge
+		if( (count || ! extOpts.hideZeros) && (!node.isExpanded() || !extOpts.hideExpanded) ){
+			$("span.fancytree-icon", node.span).append($("<span class='fancytree-childcounter'/>").text(count));
+		}
+	},
+// Overload the `setExpanded` hook, so the counters are updated
+	nodeSetExpanded: function(ctx, flag, opts) {
+		var tree = ctx.tree,
+			node = ctx.node;
+// Let the base implementation expand/collapse the node, then redraw the title
+// after the animation has finished
+		return this._superApply(arguments).always(function(){
+			tree.nodeRenderTitle(ctx);
+		});
+	}
+
+// End of extension definition
+});
+// End of namespace closure
+}(jQuery));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.clones.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.clones.js
new file mode 100644
index 00000000000..fcf31916dcf
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.clones.js
@@ -0,0 +1,451 @@
+/*!
+ *
+ * jquery.fancytree.clones.js
+ * Support faster lookup of nodes by key and shared ref-ids.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+function _assert(cond, msg){
+	// TODO: see qunit.js extractStacktrace()
+	if(!cond){
+		msg = msg ? ": " + msg : "";
+		$.error("Assertion failed" + msg);
+	}
+}
+
+
+/* Return first occurrence of member from array. */
+function _removeArrayMember(arr, elem) {
+	// TODO: use Array.indexOf for IE >= 9
+	var i;
+	for (i = arr.length - 1; i >= 0; i--) {
+		if (arr[i] === elem) {
+			arr.splice(i, 1);
+			return true;
+		}
+	}
+	return false;
+}
+
+
+// /**
+//  * Calculate a 32 bit FNV-1a hash
+//  * Found here: https://gist.github.com/vaiorabbit/5657561
+//  * Ref.: http://isthe.com/chongo/tech/comp/fnv/
+//  *
+//  * @param {string} str the input value
+//  * @param {boolean} [asString=false] set to true to return the hash value as
+//  *     8-digit hex string instead of an integer
+//  * @param {integer} [seed] optionally pass the hash of the previous chunk
+//  * @returns {integer | string}
+//  */
+// function hashFnv32a(str, asString, seed) {
+// 	/*jshint bitwise:false */
+// 	var i, l,
+// 		hval = (seed === undefined) ? 0x811c9dc5 : seed;
+
+// 	for (i = 0, l = str.length; i < l; i++) {
+// 		hval ^= str.charCodeAt(i);
+// 		hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
+// 	}
+// 	if( asString ){
+// 		// Convert to 8 digit hex string
+// 		return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
+// 	}
+// 	return hval >>> 0;
+// }
+
+
+/**
+ * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
+ *
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+ * @see http://github.com/garycourt/murmurhash-js
+ * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
+ * @see http://sites.google.com/site/murmurhash/
+ *
+ * @param {string} key ASCII only
+ * @param {boolean} [asString=false]
+ * @param {number} seed Positive integer only
+ * @return {number} 32-bit positive integer hash
+ */
+function hashMurmur3(key, asString, seed) {
+	/*jshint bitwise:false */
+	var h1b, k1,
+		remainder = key.length & 3,
+		bytes = key.length - remainder,
+		h1 = seed,
+		c1 = 0xcc9e2d51,
+		c2 = 0x1b873593,
+		i = 0;
+
+	while (i < bytes) {
+		k1 =
+			((key.charCodeAt(i) & 0xff)) |
+			((key.charCodeAt(++i) & 0xff) << 8) |
+			((key.charCodeAt(++i) & 0xff) << 16) |
+			((key.charCodeAt(++i) & 0xff) << 24);
+		++i;
+
+		k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
+		k1 = (k1 << 15) | (k1 >>> 17);
+		k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
+
+		h1 ^= k1;
+		h1 = (h1 << 13) | (h1 >>> 19);
+		h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
+		h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
+	}
+
+	k1 = 0;
+
+	switch (remainder) {
+		/*jshint -W086:true */
+		case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
+		case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
+		case 1: k1 ^= (key.charCodeAt(i) & 0xff);
+
+		k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
+		k1 = (k1 << 15) | (k1 >>> 17);
+		k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
+		h1 ^= k1;
+	}
+
+	h1 ^= key.length;
+
+	h1 ^= h1 >>> 16;
+	h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
+	h1 ^= h1 >>> 13;
+	h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
+	h1 ^= h1 >>> 16;
+
+	if( asString ){
+		// Convert to 8 digit hex string
+		return ("0000000" + (h1 >>> 0).toString(16)).substr(-8);
+	}
+	return h1 >>> 0;
+}
+
+// console.info(hashMurmur3("costarring"));
+// console.info(hashMurmur3("costarring", true));
+// console.info(hashMurmur3("liquid"));
+// console.info(hashMurmur3("liquid", true));
+
+
+/*
+ * Return a unique key for node by calculationg the hash of the parents refKey-list
+ */
+function calcUniqueKey(node) {
+	var key,
+		path = $.map(node.getParentList(false, true), function(e){ return e.refKey || e.key; });
+	path = path.join("/");
+	key = "id_" + hashMurmur3(path, true);
+	// node.debug(path + " -> " + key);
+	return key;
+}
+
+
+/**
+ * [ext-clones] Return a list of clone-nodes or null.
+ * @param {boolean} [includeSelf=false]
+ * @returns {FancytreeNode[] | null}
+ *
+ * @alias FancytreeNode#getCloneList
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function(includeSelf){
+	var key,
+		tree = this.tree,
+		refList = tree.refMap[this.refKey] || null,
+		keyMap = tree.keyMap;
+
+	if( refList ) {
+		key = this.key;
+		// Convert key list to node list
+		if( includeSelf ) {
+			refList = $.map(refList, function(val){ return keyMap[val]; });
+		} else {
+			refList = $.map(refList, function(val){ return val === key ? null : keyMap[val]; });
+			if( refList.length < 1 ) {
+				refList = null;
+			}
+		}
+	}
+	return refList;
+};
+
+
+/**
+ * [ext-clones] Return true if this node has at least another clone with same refKey.
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#isClone
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.isClone = function(){
+	var refKey = this.refKey || null,
+		refList = refKey && this.tree.refMap[refKey] || null;
+	return !!(refList && refList.length > 1);
+};
+
+
+/**
+ * [ext-clones] Update key and/or refKey for an existing node.
+ * @param {string} key
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#reRegister
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function(key, refKey){
+	key = (key == null) ? null :  "" + key;
+	refKey = (refKey == null) ? null :  "" + refKey;
+	// this.debug("reRegister", key, refKey);
+
+	var tree = this.tree,
+		prevKey = this.key,
+		prevRefKey = this.refKey,
+		keyMap = tree.keyMap,
+		refMap = tree.refMap,
+		refList = refMap[prevRefKey] || null,
+//		curCloneKeys = refList ? node.getCloneList(true),
+		modified = false;
+
+	// Key has changed: update all references
+	if( key != null && key !== this.key ) {
+		if( keyMap[key] ) {
+			$.error("[ext-clones] reRegister(" + key + "): already exists: " + this);
+		}
+		// Update keyMap
+		delete keyMap[prevKey];
+		keyMap[key] = this;
+		// Update refMap
+		if( refList ) {
+			refMap[prevRefKey] = $.map(refList, function(e){
+				return e === prevKey ? key : e;
+			});
+		}
+		this.key = key;
+		modified = true;
+	}
+
+	// refKey has changed
+	if( refKey != null && refKey !== this.refKey ) {
+		// Remove previous refKeys
+		if( refList ){
+			if( refList.length === 1 ){
+				delete refMap[prevRefKey];
+			}else{
+				refMap[prevRefKey] = $.map(refList, function(e){
+					return e === prevKey ? null : e;
+				});
+			}
+		}
+		// Add refKey
+		if( refMap[refKey] ) {
+			refMap[refKey].append(key);
+		}else{
+			refMap[refKey] = [ this.key ];
+		}
+		this.refKey = refKey;
+		modified = true;
+	}
+	return modified;
+};
+
+
+/**
+ * [ext-clones] Return all nodes with a given refKey (null if not found).
+ * @param {string} refKey
+ * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node
+ * @returns {FancytreeNode[] | null}
+ * @alias Fancytree#getNodesByRef
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function(refKey, rootNode){
+	var keyMap = this.keyMap,
+		refList = this.refMap[refKey] || null;
+
+	if( refList ) {
+		// Convert key list to node list
+		if( rootNode ) {
+			refList = $.map(refList, function(val){
+				var node = keyMap[val];
+				return node.isDescendantOf(rootNode) ? node : null;
+			});
+		}else{
+			refList = $.map(refList, function(val){ return keyMap[val]; });
+		}
+		if( refList.length < 1 ) {
+			refList = null;
+		}
+	}
+	return refList;
+};
+
+
+/**
+ * [ext-clones] Replace a refKey with a new one.
+ * @param {string} oldRefKey
+ * @param {string} newRefKey
+ * @alias Fancytree#changeRefKey
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.changeRefKey = function(oldRefKey, newRefKey) {
+	var i, node,
+		keyMap = this.keyMap,
+		refList = this.refMap[oldRefKey] || null;
+
+	if (refList) {
+		for (i = 0; i < refList.length; i++) {
+			node = keyMap[refList[i]];
+			node.refKey = newRefKey;
+		}
+		delete this.refMap[oldRefKey];
+		this.refMap[newRefKey] = refList;
+	}
+};
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "clones",
+	version: "0.0.3",
+	// Default options for this extension.
+	options: {
+		highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
+		highlightClones: false       // set 'fancytree-clone' class on any node that has at least one clone
+	},
+
+	treeCreate: function(ctx){
+		this._superApply(arguments);
+		ctx.tree.refMap = {};
+		ctx.tree.keyMap = {};
+	},
+	treeInit: function(ctx){
+		this.$container.addClass("fancytree-ext-clones");
+		_assert(ctx.options.defaultKey == null);
+		// Generate unique / reproducible default keys
+		ctx.options.defaultKey = function(node){
+			return calcUniqueKey(node);
+		};
+		// The default implementation loads initial data
+		this._superApply(arguments);
+	},
+	treeClear: function(ctx){
+		ctx.tree.refMap = {};
+		ctx.tree.keyMap = {};
+		return this._superApply(arguments);
+	},
+	treeRegisterNode: function(ctx, add, node) {
+		var refList, len,
+			tree = ctx.tree,
+			keyMap = tree.keyMap,
+			refMap = tree.refMap,
+			key = node.key,
+			refKey = (node && node.refKey != null) ? "" + node.refKey : null;
+
+//		ctx.tree.debug("clones.treeRegisterNode", add, node);
+
+		if( key === "_statusNode" ){
+			return this._superApply(arguments);
+		}
+
+		if( add ) {
+			if( keyMap[node.key] != null ) {
+				$.error("clones.treeRegisterNode: node.key already exists: " + node);
+			}
+			keyMap[key] = node;
+			if( refKey ) {
+				refList = refMap[refKey];
+				if( refList ) {
+					refList.push(key);
+					if( refList.length === 2 && ctx.options.clones.highlightClones ) {
+						// Mark peer node, if it just became a clone (no need to
+						// mark current node, since it will be rendered later anyway)
+						keyMap[refList[0]].renderStatus();
+					}
+				} else {
+					refMap[refKey] = [key];
+				}
+				// node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]);
+			}
+		}else {
+			if( keyMap[key] == null ) {
+				$.error("clones.treeRegisterNode: node.key not registered: " + node.key);
+			}
+			delete keyMap[key];
+			if( refKey ) {
+				refList = refMap[refKey];
+				// node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]);
+				if( refList ) {
+					len = refList.length;
+					if( len <= 1 ){
+						_assert(len === 1);
+						_assert(refList[0] === key);
+						delete refMap[refKey];
+					}else{
+						_removeArrayMember(refList, key);
+						// Unmark peer node, if this was the only clone
+						if( len === 2 && ctx.options.clones.highlightClones ) {
+//							node.debug("clones.treeRegisterNode: last =>", node.getCloneList());
+							keyMap[refList[0]].renderStatus();
+						}
+					}
+					// node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]);
+				}
+			}
+		}
+		return this._superApply(arguments);
+	},
+	nodeRenderStatus: function(ctx) {
+		var $span, res,
+			node = ctx.node;
+
+		res = this._superApply(arguments);
+
+		if( ctx.options.clones.highlightClones ) {
+			$span = $(node[ctx.tree.statusClassPropName]);
+			// Only if span already exists
+			if( $span.length && node.isClone() ){
+//				node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones);
+				$span.addClass("fancytree-clone");
+			}
+		}
+		return res;
+	},
+	nodeSetActive: function(ctx, flag) {
+		var res,
+			scpn = ctx.tree.statusClassPropName,
+			node = ctx.node;
+
+		res = this._superApply(arguments);
+
+		if( ctx.options.clones.highlightActiveClones && node.isClone() ) {
+			$.each(node.getCloneList(true), function(idx, n){
+				// n.debug("clones.nodeSetActive: ", flag !== false);
+				$(n[scpn]).toggleClass("fancytree-active-clone", flag !== false);
+			});
+		}
+		return res;
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.columnview.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.columnview.js
new file mode 100644
index 00000000000..c64b59d59b0
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.columnview.js
@@ -0,0 +1,150 @@
+/*!
+ * jquery.fancytree.columnview.js
+ *
+ * Render tree like a Mac Finder's column view.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+// prevent duplicate loading
+// if ( $.ui.fancytree && $.ui.fancytree.version ) {
+//     $.ui.fancytree.warn("Fancytree: duplicate include");
+//     return;
+// }
+
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+/*
+function _assert(cond, msg){
+	msg = msg || "";
+	if(!cond){
+		$.error("Assertion failed " + msg);
+	}
+}
+*/
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+$.ui.fancytree.registerExtension({
+	name: "columnview",
+	version: "0.0.1",
+	// Default options for this extension.
+	options: {
+	},
+	// Overide virtual methods for this extension.
+	// `this`       : is this extension object
+	// `this._base` : the Fancytree instance
+	// `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+	treeInit: function(ctx){
+		var $tdFirst, $ul,
+			tree = ctx.tree,
+			$table = tree.widget.element;
+
+		tree.tr = $("tbody tr", $table)[0];
+		tree.columnCount = $(">td", tree.tr).length;
+		// Perform default behavior
+		this._superApply(arguments);
+		// Standard Fancytree created a root <ul>. Now move this into first table cell
+		$ul = $(tree.rootNode.ul);
+		$tdFirst = $(">td", tree.tr).eq(0);
+
+		$ul.removeClass("fancytree-container");
+		$ul.removeAttr("tabindex");
+		tree.$container = $table;
+		$table.addClass("fancytree-container fancytree-ext-columnview");
+		$table.attr("tabindex", "0");
+
+		$tdFirst.empty();
+		$ul.detach().appendTo($tdFirst);
+
+		// Force some required options
+		tree.widget.options.autoCollapse = true;
+//      tree.widget.options.autoActivate = true;
+		tree.widget.options.toggleEffect = false;
+		tree.widget.options.clickFolderMode = 1;
+
+		// Make sure that only active path is expanded when a node is activated:
+		$table.bind("fancytreeactivate", function(event, data){
+			var i, tdList,
+				node = data.node,
+				tree = data.tree,
+				level = node.getLevel();
+
+			tree._callHook("nodeCollapseSiblings", node);
+			// Clear right neighbours
+			if(level <= tree.columnCount){
+				tdList = $(">td", tree.tr);
+				for(i=level; i<tree.columnCount; i++){
+					tdList.eq(i).empty();
+				}
+			}
+			// Expand nodes on activate, so we populate the right neighbor cell
+			if(!node.expanded && (node.children || node.lazy)) {
+				node.setExpanded();
+			}
+		// Adjust keyboard behaviour:
+		}).bind("fancytreekeydown", function(event, data){
+			var next = null,
+				node = data.node || data.tree.getFirstChild();
+			switch(event.which){
+			case $.ui.keyCode.DOWN:
+				next = node.getNextSibling();
+				if( next ){
+					next.setFocus();
+				}
+				return false;
+			case $.ui.keyCode.LEFT:
+				next = node.getParent();
+				if( next ){
+					next.setFocus();
+				}
+				return false;
+			case $.ui.keyCode.UP:
+				next = node.getPrevSibling();
+				if( next ){
+					next.setFocus();
+				}
+				return false;
+			}
+		});
+	},
+	nodeRender: function(ctx, force, deep, collapsed, _recursive) {
+		// Render standard nested <ul> - <li> hierarchy
+		this._superApply(arguments);
+		// Remove expander and add a trailing triangle instead
+		var level, $tdChild, $ul,
+			tree = ctx.tree,
+			node = ctx.node,
+			$span = $(node.span);
+
+		$span.find("span.fancytree-expander").remove();
+		if(node.hasChildren() !== false && !$span.find("span.fancytree-cv-right").length){
+			$span.append($("<span class='fancytree-icon fancytree-cv-right'>"));
+		}
+		// Move <ul> with children into the appropriate <td>
+		if(node.ul){
+			node.ul.style.display = ""; // might be hidden if RIGHT was pressed
+			level = node.getLevel();
+			if(level < tree.columnCount){
+				$tdChild = $(">td", tree.tr).eq(level);
+				$ul = $(node.ul).detach();
+				$tdChild.empty().append($ul);
+			}
+		}
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.debug.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.debug.js
new file mode 100644
index 00000000000..778fe0eef05
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.debug.js
@@ -0,0 +1,142 @@
+/*!
+ * jquery.fancytree.debug.js
+ *
+ * Miscellaneous debug extensions.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+// prevent duplicate loading
+// if ( $.ui.fancytree && $.ui.fancytree.version ) {
+//     $.ui.fancytree.warn("Fancytree: duplicate include");
+//     return;
+// }
+
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+var i,
+	HOOK_NAMES = "nodeClick nodeCollapseSiblings".split(" "),
+	EVENT_NAMES = "activate beforeActivate".split(" "),
+	HOOK_NAME_MAP = {},
+	EVENT_NAME_MAP = {};
+
+for(i=0; i<HOOK_NAMES.length; i++){ HOOK_NAME_MAP[HOOK_NAMES[i]] = true; }
+for(i=0; i<EVENT_NAMES.length; i++){ EVENT_NAME_MAP[EVENT_NAMES[i]] = true; }
+
+/* *****************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "tracecalls",
+	version: "0.0.1",
+	// Default options for this extension.
+	options: {
+		logTarget: null,   // optional redirect logging to this <div> tag
+		traceEvents: false, // `true`or list of hook names
+		traceHooks: false  // `true`or list of event names
+	},
+	// Overide virtual methods for this extension.
+	// `this`       : is this Fancytree object
+	// `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
+	treeInit: function(ctx){
+		var tree = ctx.tree;
+
+		// Bind init-handler to apply cookie state
+		tree.$div.bind("fancytreeinit", function(event){
+			tree.debug("COOKIE " + document.cookie);
+		});
+		// Init the tree
+		this._superApply(arguments);
+	},
+	nodeClick: function(ctx) {
+		if(this.options.tracecalls.traceHooks){
+			this.debug();
+		}
+	},
+	nodeCollapseSiblings: function(ctx) {
+	},
+	nodeDblclick: function(ctx) {
+	},
+	nodeKeydown: function(ctx) {
+	},
+	nodeLoadChildren: function(ctx, source) {
+	},
+	nodeOnFocusInOut: function(ctx) {
+	},
+	nodeRemoveChildMarkup: function(ctx) {
+	},
+	nodeRemoveMarkup: function(ctx) {
+	},
+	nodeRender: function(ctx, force, deep, collapsed, _recursive) {
+	},
+	nodeRenderStatus: function(ctx) {
+	},
+	nodeRenderTitle: function(ctx, title) {
+	},
+	nodeSetActive: function(ctx, flag, opts) {
+	},
+	nodeSetExpanded: function(ctx, flag, opts) {
+	},
+	nodeSetFocus: function(ctx) {
+	},
+	nodeSetSelected: function(ctx, flag) {
+	},
+	nodeSetStatus: function(ctx, status, message, details) {
+	},
+	nodeToggleExpanded: function(ctx) {
+	},
+	nodeToggleSelected: function(ctx) {
+	},
+	treeClear: function(ctx) {
+	},
+	treeCreate: function(ctx) {
+	},
+	treeDestroy: function(ctx) {
+	},
+//	treeInit: function(ctx) {
+//	},
+	treeLoad: function(ctx, source) {
+	},
+	treeSetFocus: function(ctx, flag) {
+	}
+});
+
+}(jQuery, window, document));
+
+
+
+/* *****************************************************************************
+ * Fancytree extension: profiler
+ */
+;(function($, window, document, undefined) {
+	$.ui.fancytree.registerExtension({
+		name: "profiler",
+		version: "0.0.1",
+		// Default options for this extension
+		options: {
+			prefix: ""
+		},
+		// Overide virtual methods for this extension
+		nodeRender: function(ctx, force, deep, collapsed){
+			// ctx.tree.debug("**** PROFILER nodeRender");
+			var s = this.options.prefix + "render '" + ctx.node + "'";
+			/*jshint expr:true */
+			window.console && window.console.time && window.console.time(s);
+			this._superApply(arguments);
+			window.console && window.console.timeEnd && window.console.timeEnd(s);
+		}
+	 });
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.dnd.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.dnd.js
new file mode 100644
index 00000000000..41a9e7f6725
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.dnd.js
@@ -0,0 +1,553 @@
+/*!
+ * jquery.fancytree.dnd.js
+ *
+ * Drag-and-drop support.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+var didRegisterDnd = false,
+	classDropAccept = "fancytree-drop-accept",
+	classDropAfter = "fancytree-drop-after",
+	classDropBefore = "fancytree-drop-before",
+	classDropOver = "fancytree-drop-over",
+	classDropReject = "fancytree-drop-reject",
+	classDropTarget = "fancytree-drop-target";
+
+/* Convert number to string and prepend +/-; return empty string for 0.*/
+function offsetString(n){
+	return n === 0 ? "" : (( n > 0 ) ? ("+" + n) : ("" + n));
+}
+
+/* *****************************************************************************
+ * Drag and drop support
+ */
+function _initDragAndDrop(tree) {
+	var dnd = tree.options.dnd || null,
+		glyph = tree.options.glyph || null;
+
+	// Register 'connectToFancytree' option with ui.draggable
+	if( dnd ) {
+		_registerDnd();
+	}
+	// Attach ui.draggable to this Fancytree instance
+	if(dnd && dnd.dragStart ) {
+		tree.widget.element.draggable($.extend({
+			addClasses: false,
+			// DT issue 244: helper should be child of scrollParent:
+			appendTo: tree.$container,
+//			appendTo: "body",
+			containment: false,
+//			containment: "parent",
+			delay: 0,
+			distance: 4,
+			revert: false,
+			scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container
+			scrollSpeed: 7,
+			scrollSensitivity: 10,
+			// Delegate draggable.start, drag, and stop events to our handler
+			connectToFancytree: true,
+			// Let source tree create the helper element
+			helper: function(event) {
+				var $helper, $nodeTag, opts,
+					sourceNode = $.ui.fancytree.getNode(event.target);
+
+				if(!sourceNode){
+					// #405, DT issue 211: might happen, if dragging a table *header*
+					return "<div>ERROR?: helper requested but sourceNode not found</div>";
+				}
+				opts = sourceNode.tree.options.dnd;
+				$nodeTag = $(sourceNode.span);
+				// Only event and node argument is available
+				$helper = $("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>")
+					.css({zIndex: 3, position: "relative"}) // so it appears above ext-wide selection bar
+					.append($nodeTag.find("span.fancytree-title").clone());
+
+				// Attach node reference to helper object
+				$helper.data("ftSourceNode", sourceNode);
+
+				// Support glyph symbols instead of icons
+				if( glyph ) {
+					$helper.find(".fancytree-drag-helper-img")
+						.addClass(glyph.map.dragHelper);
+				}
+				// Allow to modify the helper, e.g. to add multi-node-drag feedback
+				if( opts.initHelper ) {
+					opts.initHelper.call(sourceNode.tree, sourceNode, {
+						node: sourceNode,
+						tree: sourceNode.tree,
+						originalEvent: event,
+						ui: { helper: $helper }
+					});
+				}
+				// We return an unconnected element, so `draggable` will add this
+				// to the parent specified as `appendTo` option
+				return $helper;
+			},
+			start: function(event, ui) {
+				var sourceNode = ui.helper.data("ftSourceNode");
+				return !!sourceNode; // Abort dragging if no node could be found
+			}
+		}, tree.options.dnd.draggable));
+	}
+	// Attach ui.droppable to this Fancytree instance
+	if(dnd && dnd.dragDrop) {
+		tree.widget.element.droppable($.extend({
+			addClasses: false,
+			tolerance: "intersect",
+			greedy: false
+/*
+			activate: function(event, ui) {
+				tree.debug("droppable - activate", event, ui, this);
+			},
+			create: function(event, ui) {
+				tree.debug("droppable - create", event, ui);
+			},
+			deactivate: function(event, ui) {
+				tree.debug("droppable - deactivate", event, ui);
+			},
+			drop: function(event, ui) {
+				tree.debug("droppable - drop", event, ui);
+			},
+			out: function(event, ui) {
+				tree.debug("droppable - out", event, ui);
+			},
+			over: function(event, ui) {
+				tree.debug("droppable - over", event, ui);
+			}
+*/
+		}, tree.options.dnd.droppable));
+	}
+}
+
+//--- Extend ui.draggable event handling --------------------------------------
+
+function _registerDnd() {
+	if(didRegisterDnd){
+		return;
+	}
+
+	// Register proxy-functions for draggable.start/drag/stop
+
+	$.ui.plugin.add("draggable", "connectToFancytree", {
+		start: function(event, ui) {
+			// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+			var draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
+				sourceNode = ui.helper.data("ftSourceNode") || null;
+
+			if(sourceNode) {
+				// Adjust helper offset, so cursor is slightly outside top/left corner
+				draggable.offset.click.top = -2;
+				draggable.offset.click.left = + 16;
+				// Trigger dragStart event
+				// TODO: when called as connectTo..., the return value is ignored(?)
+				return sourceNode.tree.ext.dnd._onDragEvent("start", sourceNode, null, event, ui, draggable);
+			}
+		},
+		drag: function(event, ui) {
+			var ctx, isHelper, logObject,
+				// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+				draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
+				sourceNode = ui.helper.data("ftSourceNode") || null,
+				prevTargetNode = ui.helper.data("ftTargetNode") || null,
+				targetNode = $.ui.fancytree.getNode(event.target),
+				dndOpts = sourceNode && sourceNode.tree.options.dnd;
+
+			// logObject = sourceNode || prevTargetNode || $.ui.fancytree;
+			// logObject.debug("Drag event:", event, event.shiftKey);
+			if(event.target && !targetNode){
+				// We got a drag event, but the targetNode could not be found
+				// at the event location. This may happen,
+				// 1. if the mouse jumped over the drag helper,
+				// 2. or if a non-fancytree element is dragged
+				// We ignore it:
+				isHelper = $(event.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length > 0;
+				if(isHelper){
+					logObject = sourceNode || prevTargetNode || $.ui.fancytree;
+					logObject.debug("Drag event over helper: ignored.");
+					return;
+				}
+			}
+			ui.helper.data("ftTargetNode", targetNode);
+
+			if( dndOpts && dndOpts.updateHelper ) {
+				ctx = sourceNode.tree._makeHookContext(sourceNode, event, {
+					otherNode: targetNode,
+					ui: ui,
+					draggable: draggable,
+					dropMarker: $("#fancytree-drop-marker")
+				});
+				dndOpts.updateHelper.call(sourceNode.tree, sourceNode, ctx);
+			}
+
+			// Leaving a tree node
+			if(prevTargetNode && prevTargetNode !== targetNode ) {
+				prevTargetNode.tree.ext.dnd._onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
+			}
+			if(targetNode){
+				if(!targetNode.tree.options.dnd.dragDrop) {
+					// not enabled as drop target
+				} else if(targetNode === prevTargetNode) {
+					// Moving over same node
+					targetNode.tree.ext.dnd._onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
+				}else{
+					// Entering this node first time
+					targetNode.tree.ext.dnd._onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
+				}
+			}
+			// else go ahead with standard event handling
+		},
+		stop: function(event, ui) {
+			var logObject,
+				// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10:
+				draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
+				sourceNode = ui.helper.data("ftSourceNode") || null,
+				targetNode = ui.helper.data("ftTargetNode") || null,
+				dropped = (event.type === "mouseup" && event.which === 1);
+
+			if(!dropped){
+				logObject = sourceNode || targetNode || $.ui.fancytree;
+				logObject.debug("Drag was cancelled");
+			}
+			if(targetNode) {
+				if(dropped){
+					targetNode.tree.ext.dnd._onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
+				}
+				targetNode.tree.ext.dnd._onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
+			}
+			if(sourceNode){
+				sourceNode.tree.ext.dnd._onDragEvent("stop", sourceNode, null, event, ui, draggable);
+			}
+		}
+	});
+
+	didRegisterDnd = true;
+}
+
+
+/* *****************************************************************************
+ *
+ */
+
+$.ui.fancytree.registerExtension({
+	name: "dnd",
+	version: "0.2.0",
+	// Default options for this extension.
+	options: {
+		// Make tree nodes accept draggables
+		autoExpandMS: 1000,  // Expand nodes after n milliseconds of hovering.
+		draggable: null,     // Additional options passed to jQuery draggable
+		droppable: null,     // Additional options passed to jQuery droppable
+		focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
+		preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+		preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
+		smartRevert: true,   // set draggable.revert = true if drop was rejected
+		// Events (drag support)
+		dragStart: null,     // Callback(sourceNode, data), return true, to enable dnd
+		dragStop: null,      // Callback(sourceNode, data)
+		initHelper: null,    // Callback(sourceNode, data)
+		updateHelper: null,  // Callback(sourceNode, data)
+		// Events (drop support)
+		dragEnter: null,  // Callback(targetNode, data)
+		dragOver: null,   // Callback(targetNode, data)
+		dragDrop: null,   // Callback(targetNode, data)
+		dragLeave: null   // Callback(targetNode, data)
+	},
+
+	treeInit: function(ctx){
+		var tree = ctx.tree;
+		this._superApply(arguments);
+		// issue #270: draggable eats mousedown events
+		if( tree.options.dnd.dragStart ){
+			tree.$container.on("mousedown", function(event){
+//				if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) {
+				if( ctx.options.dnd.focusOnClick ) {  // #270
+					var node = $.ui.fancytree.getNode(event);
+					if (node){
+						node.debug("Re-enable focus that was prevented by jQuery UI draggable.");
+						// node.setFocus();
+						// $(node.span).closest(":tabbable").focus();
+						// $(event.target).trigger("focus");
+						// $(event.target).closest(":tabbable").trigger("focus");
+					}
+					setTimeout(function() { // #300
+						$(event.target).closest(":tabbable").focus();
+					}, 10);
+				}
+			});
+		}
+		_initDragAndDrop(tree);
+	},
+	/* Display drop marker according to hitMode ('after', 'before', 'over'). */
+	_setDndStatus: function(sourceNode, targetNode, helper, hitMode, accept) {
+		var markerOffsetX = 0,
+			markerAt = "center",
+			instData = this._local,
+			glyph = this.options.glyph || null,
+			$source = sourceNode ? $(sourceNode.span) : null,
+			$target = $(targetNode.span);
+
+		if( !instData.$dropMarker ) {
+			instData.$dropMarker = $("<div id='fancytree-drop-marker'></div>")
+				.hide()
+				.css({"z-index": 1000})
+				.prependTo($(this.$div).parent());
+//                .prependTo("body");
+
+			if( glyph ) {
+				// instData.$dropMarker.addClass(glyph.map.dragHelper);
+				instData.$dropMarker
+					.addClass(glyph.map.dropMarker);
+			}
+		}
+		if( hitMode === "after" || hitMode === "before" || hitMode === "over" ){
+			switch(hitMode){
+			case "before":
+				markerAt = "top";
+				break;
+			case "after":
+				markerAt = "bottom";
+				break;
+			default:
+				markerOffsetX = 8;
+			}
+
+			instData.$dropMarker
+				.toggleClass(classDropAfter, hitMode === "after")
+				.toggleClass(classDropOver, hitMode === "over")
+				.toggleClass(classDropBefore, hitMode === "before")
+				.show()
+				.position($.ui.fancytree.fixPositionOptions({
+					my: "left" + offsetString(markerOffsetX) + " center",
+					at: "left " + markerAt,
+					of: $target
+					}));
+		} else {
+			instData.$dropMarker.hide();
+		}
+		if( $source ){
+			$source
+				.toggleClass(classDropAccept, accept === true)
+				.toggleClass(classDropReject, accept === false);
+		}
+		$target
+			.toggleClass(classDropTarget, hitMode === "after" || hitMode === "before" || hitMode === "over")
+			.toggleClass(classDropAfter, hitMode === "after")
+			.toggleClass(classDropBefore, hitMode === "before")
+			.toggleClass(classDropAccept, accept === true)
+			.toggleClass(classDropReject, accept === false);
+
+		helper
+			.toggleClass(classDropAccept, accept === true)
+			.toggleClass(classDropReject, accept === false);
+	},
+
+	/*
+	 * Handles drag'n'drop functionality.
+	 *
+	 * A standard jQuery drag-and-drop process may generate these calls:
+	 *
+	 * start:
+	 *     _onDragEvent("start", sourceNode, null, event, ui, draggable);
+	 * drag:
+	 *     _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
+	 * stop:
+	 *     _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
+	 *     _onDragEvent("stop", sourceNode, null, event, ui, draggable);
+	 */
+	_onDragEvent: function(eventName, node, otherNode, event, ui, draggable) {
+		if(eventName !== "over"){
+			this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
+		}
+		var accept, nodeOfs, relPos, relPos2,
+			enterResponse, hitMode, r,
+			opts = this.options,
+			dnd = opts.dnd,
+			ctx = this._makeHookContext(node, event, {otherNode: otherNode, ui: ui, draggable: draggable}),
+			res = null,
+			that = this,
+			$nodeTag = $(node.span);
+
+		if( dnd.smartRevert ) {
+			draggable.options.revert = "invalid";
+		}
+
+		switch (eventName) {
+
+		case "start":
+			if( node.isStatusNode() ) {
+				res = false;
+			} else if(dnd.dragStart) {
+				res = dnd.dragStart(node, ctx);
+			}
+			if(res === false) {
+				this.debug("tree.dragStart() cancelled");
+				//draggable._clear();
+				// NOTE: the return value seems to be ignored (drag is not canceled, when false is returned)
+				// TODO: call this._cancelDrag()?
+				ui.helper.trigger("mouseup")
+					.hide();
+			} else {
+				$nodeTag.addClass("fancytree-drag-source");
+				// Register global handlers to allow cancel
+				$(document)
+					.on("keydown.fancytree-dnd,mousedown.fancytree-dnd", function(event){
+						// node.tree.debug("dnd global event", event.type, event.which);
+						if( event.type === "keydown" && event.which === $.ui.keyCode.ESCAPE ) {
+							that.ext.dnd._cancelDrag();
+						} else if( event.type === "mousedown" ) {
+							that.ext.dnd._cancelDrag();
+						}
+					});
+			}
+			break;
+
+		case "enter":
+			if(dnd.preventRecursiveMoves && node.isDescendantOf(otherNode)){
+				r = false;
+			}else{
+				r = dnd.dragEnter ? dnd.dragEnter(node, ctx) : null;
+			}
+			if(!r){
+				// convert null, undefined, false to false
+				res = false;
+			}else if ( $.isArray(r) ) {
+				// TODO: also accept passing an object of this format directly
+				res = {
+					over: ($.inArray("over", r) >= 0),
+					before: ($.inArray("before", r) >= 0),
+					after: ($.inArray("after", r) >= 0)
+				};
+			}else{
+				res = {
+					over: ((r === true) || (r === "over")),
+					before: ((r === true) || (r === "before")),
+					after: ((r === true) || (r === "after"))
+				};
+			}
+			ui.helper.data("enterResponse", res);
+			this.debug("helper.enterResponse: %o", res);
+			break;
+
+		case "over":
+			enterResponse = ui.helper.data("enterResponse");
+			hitMode = null;
+			if(enterResponse === false){
+				// Don't call dragOver if onEnter returned false.
+//                break;
+			} else if(typeof enterResponse === "string") {
+				// Use hitMode from onEnter if provided.
+				hitMode = enterResponse;
+			} else {
+				// Calculate hitMode from relative cursor position.
+				nodeOfs = $nodeTag.offset();
+				relPos = { x: event.pageX - nodeOfs.left,
+						   y: event.pageY - nodeOfs.top };
+				relPos2 = { x: relPos.x / $nodeTag.width(),
+							y: relPos.y / $nodeTag.height() };
+
+				if( enterResponse.after && relPos2.y > 0.75 ){
+					hitMode = "after";
+				} else if(!enterResponse.over && enterResponse.after && relPos2.y > 0.5 ){
+					hitMode = "after";
+				} else if(enterResponse.before && relPos2.y <= 0.25) {
+					hitMode = "before";
+				} else if(!enterResponse.over && enterResponse.before && relPos2.y <= 0.5) {
+					hitMode = "before";
+				} else if(enterResponse.over) {
+					hitMode = "over";
+				}
+				// Prevent no-ops like 'before source node'
+				// TODO: these are no-ops when moving nodes, but not in copy mode
+				if( dnd.preventVoidMoves ){
+					if(node === otherNode){
+						this.debug("    drop over source node prevented");
+						hitMode = null;
+					}else if(hitMode === "before" && otherNode && node === otherNode.getNextSibling()){
+						this.debug("    drop after source node prevented");
+						hitMode = null;
+					}else if(hitMode === "after" && otherNode && node === otherNode.getPrevSibling()){
+						this.debug("    drop before source node prevented");
+						hitMode = null;
+					}else if(hitMode === "over" && otherNode && otherNode.parent === node && otherNode.isLastSibling() ){
+						this.debug("    drop last child over own parent prevented");
+						hitMode = null;
+					}
+				}
+//                this.debug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
+				ui.helper.data("hitMode", hitMode);
+			}
+			// Auto-expand node (only when 'over' the node, not 'before', or 'after')
+			if(hitMode === "over" && dnd.autoExpandMS && node.hasChildren() !== false && !node.expanded) {
+				node.scheduleAction("expand", dnd.autoExpandMS);
+			}
+			if(hitMode && dnd.dragOver){
+				// TODO: http://code.google.com/p/dynatree/source/detail?r=625
+				ctx.hitMode = hitMode;
+				res = dnd.dragOver(node, ctx);
+			}
+			accept = (res !== false && hitMode !== null);
+			if( dnd.smartRevert ) {
+				draggable.options.revert = !accept;
+			}
+			this._local._setDndStatus(otherNode, node, ui.helper, hitMode, accept);
+			break;
+
+		case "drop":
+			hitMode = ui.helper.data("hitMode");
+			if(hitMode && dnd.dragDrop){
+				ctx.hitMode = hitMode;
+				dnd.dragDrop(node, ctx);
+			}
+			break;
+
+		case "leave":
+			// Cancel pending expand request
+			node.scheduleAction("cancel");
+			ui.helper.data("enterResponse", null);
+			ui.helper.data("hitMode", null);
+			this._local._setDndStatus(otherNode, node, ui.helper, "out", undefined);
+			if(dnd.dragLeave){
+				dnd.dragLeave(node, ctx);
+			}
+			break;
+
+		case "stop":
+			$nodeTag.removeClass("fancytree-drag-source");
+			$(document).off(".fancytree-dnd");
+			if(dnd.dragStop){
+				dnd.dragStop(node, ctx);
+			}
+			break;
+
+		default:
+			$.error("Unsupported drag event: " + eventName);
+		}
+		return res;
+	},
+
+	_cancelDrag: function() {
+		 var dd = $.ui.ddmanager.current;
+		 if(dd){
+			 dd.cancel();
+		 }
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.edit.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.edit.js
new file mode 100644
index 00000000000..dd498b6a5c3
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.edit.js
@@ -0,0 +1,309 @@
+/*!
+ * jquery.fancytree.edit.js
+ *
+ * Make node titles editable.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+
+var isMac = /Mac/.test(navigator.platform),
+	escapeHtml = $.ui.fancytree.escapeHtml,
+	unescapeHtml = $.ui.fancytree.unescapeHtml;
+
+/**
+ * [ext-edit] Start inline editing of current node title.
+ *
+ * @alias FancytreeNode#editStart
+ * @requires Fancytree
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.editStart = function(){
+	var $input,
+		node = this,
+		tree = this.tree,
+		local = tree.ext.edit,
+		instOpts = tree.options.edit,
+		$title = $(".fancytree-title", node.span),
+		eventData = {
+			node: node,
+			tree: tree,
+			options: tree.options,
+			isNew: $(node[tree.statusClassPropName]).hasClass("fancytree-edit-new"),
+			orgTitle: node.title,
+			input: null,
+			dirty: false
+			};
+
+	// beforeEdit may want to modify the title before editing
+	if( instOpts.beforeEdit.call(node, {type: "beforeEdit"}, eventData) === false ) {
+		return false;
+	}
+	$.ui.fancytree.assert(!local.currentNode, "recursive edit");
+	local.currentNode = this;
+	local.eventData = eventData;
+
+	// Disable standard Fancytree mouse- and key handling
+	tree.widget._unbind();
+	// #116: ext-dnd prevents the blur event, so we have to catch outer clicks
+	$(document).on("mousedown.fancytree-edit", function(event){
+		if( ! $(event.target).hasClass("fancytree-edit-input") ){
+			node.editEnd(true, event);
+		}
+	});
+
+	// Replace node with <input>
+	$input = $("<input />", {
+		"class": "fancytree-edit-input",
+		type: "text",
+		value: unescapeHtml(eventData.orgTitle)
+	});
+	local.eventData.input = $input;
+	if ( instOpts.adjustWidthOfs != null ) {
+		$input.width($title.width() + instOpts.adjustWidthOfs);
+	}
+	if ( instOpts.inputCss != null ) {
+		$input.css(instOpts.inputCss);
+	}
+
+	$title.html($input);
+
+	// Focus <input> and bind keyboard handler
+	$input
+		.focus()
+		.change(function(event){
+			$input.addClass("fancytree-edit-dirty");
+		}).keydown(function(event){
+			switch( event.which ) {
+			case $.ui.keyCode.ESCAPE:
+				node.editEnd(false, event);
+				break;
+			case $.ui.keyCode.ENTER:
+				node.editEnd(true, event);
+				return false; // so we don't start editmode on Mac
+			}
+			event.stopPropagation();
+		}).blur(function(event){
+			return node.editEnd(true, event);
+		});
+
+	instOpts.edit.call(node, {type: "edit"}, eventData);
+};
+
+
+/**
+ * [ext-edit] Stop inline editing.
+ * @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified)
+ * @alias FancytreeNode#editEnd
+ * @requires jquery.fancytree.edit.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function(applyChanges, _event){
+	var newVal,
+		node = this,
+		tree = this.tree,
+		local = tree.ext.edit,
+		eventData = local.eventData,
+		instOpts = tree.options.edit,
+		$title = $(".fancytree-title", node.span),
+		$input = $title.find("input.fancytree-edit-input");
+
+	// eventData.isNew = $(node[tree.statusClassPropName]).hasClass("fancytree-edit-new");
+
+	if( instOpts.trim ) {
+		$input.val($.trim($input.val()));
+	}
+	newVal = $input.val();
+	// eventData.dirty = $input.hasClass("fancytree-edit-dirty") || ;
+	eventData.dirty = ( newVal !== node.title );
+
+	// Find out, if saving is required
+	if( applyChanges === false ) {
+		// If true/false was passed, honor this (except in rename mode, if unchanged)
+		eventData.save = false;
+	} else if( eventData.isNew ) {
+		// In create mode, we save everyting, except for empty text
+		eventData.save = (newVal !== "");
+	} else {
+		// In rename mode, we save everyting, except for empty or unchanged text
+		eventData.save = eventData.dirty && (newVal !== "");
+	}
+	// Allow to break (keep editor open), modify input, or re-define data.save
+	if( instOpts.beforeClose.call(node, {type: "beforeClose"}, eventData) === false){
+		return false;
+	}
+	if( eventData.save && instOpts.save.call(node, {type: "save"}, eventData) === false){
+		return false;
+	}
+	$input
+		.removeClass("fancytree-edit-dirty")
+		.unbind();
+	// Unbind outer-click handler
+	$(document).off(".fancytree-edit");
+
+	if( eventData.save ) {
+		node.setTitle( escapeHtml(newVal) );
+		// $(node[tree.statusClassPropName]).removeClass("fancytree-edit-new");
+		node.setFocus();
+	}else{
+		if( eventData.isNew ) {
+			node.remove();
+			node = eventData.node = null;
+			local.relatedNode.setFocus();
+		} else {
+			node.renderTitle();
+			node.setFocus();
+		}
+	}
+	local.eventData = null;
+	local.currentNode = null;
+	local.relatedNode = null;
+	// Re-enable mouse and keyboard handling
+	tree.widget._bind();
+	// Set keyboard focus, even if setFocus() claims 'nothing to do'
+	$(tree.$container).focus();
+	eventData.input = null;
+	instOpts.close.call(node, {type: "close"}, eventData);
+	return true;
+};
+
+
+/**
+* [ext-edit] Create a new child or sibling node and start edit mode.
+*
+* @param {String} [mode='child'] 'before', 'after', or 'child'
+* @param {Object} [init] NodeData (or simple title string)
+* @alias FancytreeNode#editCreateNode
+* @requires jquery.fancytree.edit.js
+* @since 2.4
+*/
+$.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function(mode, init){
+	var newNode,
+		tree = this.tree,
+		self = this;
+
+	mode = mode || "child";
+	if( init == null ) {
+		init = { title: "" };
+	} else if( typeof init === "string" ) {
+		init = { title: init };
+	} else {
+		$.ui.fancytree.assert($.isPlainObject(init));
+	}
+	// Make sure node is expanded (and loaded) in 'child' mode
+	if( mode === "child" && !this.isExpanded() && this.hasChildren() !== false ) {
+		this.setExpanded().done(function(){
+			self.editCreateNode(mode, init);
+		});
+		return;
+	}
+	newNode = this.addNode(init, mode);
+	newNode.makeVisible(/*{noAnimation: true}*/).done(function(){
+		$(newNode[tree.statusClassPropName]).addClass("fancytree-edit-new");
+		self.tree.ext.edit.relatedNode = self;
+		newNode.editStart();
+	});
+};
+
+
+/**
+ * [ext-edit] Check if any node in this tree  in edit mode.
+ *
+ * @returns {FancytreeNode | null}
+ * @alias Fancytree#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.isEditing = function(){
+	return this.ext.edit.currentNode;
+};
+
+
+/**
+ * [ext-edit] Check if this node is in edit mode.
+ * @returns {Boolean} true if node is currently beeing edited
+ * @alias FancytreeNode#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function(){
+	return this.tree.ext.edit.currentNode === this;
+};
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "edit",
+	version: "0.2.0",
+	// Default options for this extension.
+	options: {
+		adjustWidthOfs: 4,   // null: don't adjust input size to content
+		allowEmpty: false,   // Prevent empty input
+		inputCss: {minWidth: "3em"},
+		triggerCancel: ["esc", "tab", "click"],
+		// triggerStart: ["f2", "dblclick", "shift+click", "mac+enter"],
+		triggerStart: ["f2", "shift+click", "mac+enter"],
+		trim: true,          // Trim whitespace before save
+		// Events:
+		beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available)
+		beforeEdit: $.noop,  // Return false to prevent edit mode
+		close: $.noop,       // Editor was removed
+		edit: $.noop,        // Editor was opened (available as data.input)
+//		keypress: $.noop,    // Not yet implemented
+		save: $.noop         // Save data.input.val() or return false to keep editor open
+	},
+	// Local attributes
+	currentNode: null,
+
+	treeInit: function(ctx){
+		this._superApply(arguments);
+		this.$container.addClass("fancytree-ext-edit");
+	},
+	nodeClick: function(ctx) {
+		if( $.inArray("shift+click", ctx.options.edit.triggerStart) >= 0 ){
+			if( ctx.originalEvent.shiftKey ){
+				ctx.node.editStart();
+				return false;
+			}
+		}
+		return this._superApply(arguments);
+	},
+	nodeDblclick: function(ctx) {
+		if( $.inArray("dblclick", ctx.options.edit.triggerStart) >= 0 ){
+			ctx.node.editStart();
+			return false;
+		}
+		return this._superApply(arguments);
+	},
+	nodeKeydown: function(ctx) {
+		switch( ctx.originalEvent.which ) {
+		case 113: // [F2]
+			if( $.inArray("f2", ctx.options.edit.triggerStart) >= 0 ){
+				ctx.node.editStart();
+				return false;
+			}
+			break;
+		case $.ui.keyCode.ENTER:
+			if( $.inArray("mac+enter", ctx.options.edit.triggerStart) >= 0 && isMac ){
+				ctx.node.editStart();
+				return false;
+			}
+			break;
+		}
+		return this._superApply(arguments);
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.filter.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.filter.js
new file mode 100644
index 00000000000..a1a88f00d18
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.filter.js
@@ -0,0 +1,283 @@
+/*!
+ * jquery.fancytree.filter.js
+ *
+ * Remove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+
+function _escapeRegex(str){
+	/*jshint regexdash:true */
+	return (str + "").replace(/([.?*+\^\$\[\]\\(){}|-])/g, "\\$1");
+}
+
+$.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function(filter, branchMode, opts){
+	var leavesOnly, match, re, re2,
+		count = 0,
+		filterOpts = this.options.filter,
+		hideMode = filterOpts.mode === "hide";
+
+	opts = opts || {};
+	leavesOnly = !!opts.leavesOnly && !branchMode;
+
+	// Default to 'match title substring (not case sensitive)'
+	if(typeof filter === "string"){
+		// console.log("rex", filter.split('').join('\\w*').replace(/\W/, ""))
+		if( filterOpts.fuzzy ) {
+			// See https://codereview.stackexchange.com/questions/23899/faster-javascript-fuzzy-string-matching-function/23905#23905
+			// and http://www.quora.com/How-is-the-fuzzy-search-algorithm-in-Sublime-Text-designed
+			// and http://www.dustindiaz.com/autocomplete-fuzzy-matching
+			match = filter.split("").reduce(function(a, b) {
+				return a + "[^" + b + "]*" + b;
+			});
+		} else {
+			match = _escapeRegex(filter); // make sure a '.' is treated literally
+		}
+		re = new RegExp(".*" + match + ".*", "i");
+		re2 = new RegExp(filter, "gi");
+		filter = function(node){
+			var res = !!re.test(node.title);
+			// node.debug("filter res", res, filterOpts.highlight)
+			if( res && filterOpts.highlight ) {
+				node.titleWithHighlight = node.title.replace(re2, function(s){
+					return "<mark>" + s + "</mark>";
+				});
+			// } else {
+			// 	delete node.titleWithHighlight;
+			}
+			return res;
+		};
+	}
+
+	this.enableFilter = true;
+	this.lastFilterArgs = arguments;
+
+	this.$div.addClass("fancytree-ext-filter");
+	if( hideMode ){
+		this.$div.addClass("fancytree-ext-filter-hide");
+	} else {
+		this.$div.addClass("fancytree-ext-filter-dimm");
+	}
+	// Reset current filter
+	this.visit(function(node){
+		delete node.match;
+		delete node.titleWithHighlight;
+		node.subMatchCount = 0;
+	});
+	// Adjust node.hide, .match, and .subMatchCount properties
+	this.visit(function(node){
+		if ((!leavesOnly || node.children == null) && filter(node)) {
+			count++;
+			node.match = true;
+			node.visitParents(function(p){
+				p.subMatchCount += 1;
+				if( opts.autoExpand && !p.expanded ) {
+					p.setExpanded(true, {noAnimation: true, noEvents: true, scrollIntoView: false});
+					p._filterAutoExpanded = true;
+				}
+			});
+			if( branchMode ) {
+				node.visit(function(p){
+					p.match = true;
+				});
+				return "skip";
+			}
+		}
+	});
+	// Redraw whole tree
+	this.render();
+	return count;
+};
+
+/**
+ * [ext-filter] Dimm or hide nodes.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false, leavesOnly: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterNodes
+ * @requires jquery.fancytree.filter.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.filterNodes = function(filter, opts) {
+	if( typeof opts === "boolean" ) {
+		opts = { leavesOnly: opts };
+		this.warn("Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19.");
+	}
+	return this._applyFilterImpl(filter, false, opts);
+};
+
+/**
+ * @deprecated
+ */
+$.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
+	this.warn("Fancytree.applyFilter() is deprecated since 2.1.0 / 2014-05-29. Use .filterNodes() instead.");
+	return this.filterNodes.apply(this, arguments);
+};
+
+/**
+ * [ext-filter] Dimm or hide whole branches.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterBranches
+ * @requires jquery.fancytree.filter.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.filterBranches = function(filter, opts){
+	return this._applyFilterImpl(filter, true, opts);
+};
+
+
+/**
+ * [ext-filter] Reset the filter.
+ *
+ * @alias Fancytree#clearFilter
+ * @requires jquery.fancytree.filter.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.clearFilter = function(){
+	this.visit(function(node){
+		if( node.match ) {  // #491
+			$(">span.fancytree-title", node.span).html(node.title);
+		}
+		delete node.match;
+		delete node.subMatchCount;
+		delete node.titleWithHighlight;
+		if ( node.$subMatchBadge ) {
+			node.$subMatchBadge.remove();
+			delete node.$subMatchBadge;
+		}
+		if( node._filterAutoExpanded && node.expanded ) {
+			node.setExpanded(false, {noAnimation: true, noEvents: true, scrollIntoView: false});
+		}
+		delete node._filterAutoExpanded;
+	});
+	this.enableFilter = false;
+	this.lastFilterArgs = null;
+	this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide");
+	this.render();
+};
+
+
+/**
+ * [ext-filter] Return true if a filter is currently applied.
+ *
+ * @returns {Boolean}
+ * @alias Fancytree#isFilterActive
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+$.ui.fancytree._FancytreeClass.prototype.isFilterActive = function(){
+	return !!this.enableFilter;
+};
+
+
+/**
+ * [ext-filter] Return true if this node is matched by current filter (or no filter is active).
+ *
+ * @returns {Boolean}
+ * @alias FancytreeNode#isMatched
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.isMatched = function(){
+	return !(this.tree.enableFilter && !this.match);
+};
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "filter",
+	version: "0.7.0",
+	// Default options for this extension.
+	options: {
+		autoApply: true,  // Re-apply last filter if lazy data is loaded
+		counter: true,  // Show a badge with number of matching child nodes near parent icons
+		fuzzy: false,  // Match single characters in order, e.g. 'fb' will match 'FooBar'
+		hideExpandedCounter: true,  // Hide counter badge, when parent is expanded
+		highlight: true,  // Highlight matches by wrapping inside <mark> tags
+		mode: "dimm"  // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
+	},
+	// treeCreate: function(ctx){
+	// 	this._superApply(arguments);
+	// 	console.log("create")
+	// 	ctx.tree.options.renderTitle = function(event, data) {
+	// 		var node = data.node;
+	// 		console.log("create n", node.titleWithHighlight, data.tree.enableFilter)
+	// 		if( node.titleWithHighlight && node.tree.enableFilter ) {
+	// 			return node.titleWithHighlight;
+	// 		}
+	// 	}
+	// },
+	// treeInit: function(ctx){
+	// 	this._superApply(arguments);
+	// },
+	nodeLoadChildren: function(ctx, source) {
+		return this._superApply(arguments).done(function() {
+			if( ctx.tree.enableFilter && ctx.tree.lastFilterArgs && ctx.options.filter.autoApply ) {
+				ctx.tree._applyFilterImpl.apply(ctx.tree, ctx.tree.lastFilterArgs);
+			}
+		});
+	},
+	nodeSetExpanded: function(ctx, flag, callOpts) {
+		delete ctx.node._filterAutoExpanded;
+		// Make sure counter badge is displayed again, when node is beeing collapsed
+		if( !flag && ctx.options.filter.hideExpandedCounter && ctx.node.$subMatchBadge ) {
+			ctx.node.$subMatchBadge.show();
+		}
+		return this._superApply(arguments);
+	},
+	nodeRenderStatus: function(ctx) {
+		// Set classes for current status
+		var res,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options.filter,
+			$span = $(node[tree.statusClassPropName]);
+
+		res = this._superApply(arguments);
+		// nothing to do, if node was not yet rendered
+		if( !$span.length || !tree.enableFilter ) {
+			return res;
+		}
+		$span
+			.toggleClass("fancytree-match", !!node.match)
+			.toggleClass("fancytree-submatch", !!node.subMatchCount)
+			.toggleClass("fancytree-hide", !(node.match || node.subMatchCount));
+		// Add/update counter badge
+		if( opts.counter && node.subMatchCount && (!node.isExpanded() || !opts.hideExpandedCounter) ) {
+			if( !node.$subMatchBadge ) {
+				node.$subMatchBadge = $("<span class='fancytree-childcounter'/>");
+				$("span.fancytree-icon", node.span).append(node.$subMatchBadge);
+			}
+			node.$subMatchBadge.show().text(node.subMatchCount);
+		} else if ( node.$subMatchBadge ) {
+			node.$subMatchBadge.hide();
+		}
+		// node.debug("nodeRenderStatus", node.titleWithHighlight, node.title)
+		if( node.titleWithHighlight ) {
+			$("span.fancytree-title", node.span).html(node.titleWithHighlight);
+		} else {
+			$("span.fancytree-title", node.span).html(node.title);
+		}
+		return res;
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.glyph.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.glyph.js
new file mode 100644
index 00000000000..e8aa3aaa84e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.glyph.js
@@ -0,0 +1,139 @@
+/*!
+ * jquery.fancytree.glyph.js
+ *
+ * Use glyph fonts as instead of icon sprites.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+
+function _getIcon(opts, type){
+	return opts.map[type];
+}
+
+$.ui.fancytree.registerExtension({
+	name: "glyph",
+	version: "0.3.0",
+	// Default options for this extension.
+	options: {
+		map: {
+			// Samples from Font Awesome 3.2
+			//   http://fortawesome.github.io/Font-Awesome/3.2.1/icons/
+			// See here for alternatives:
+			//   http://fortawesome.github.io/Font-Awesome/icons/
+			//   http://getbootstrap.com/components/
+			checkbox: "icon-check-empty",
+			checkboxSelected: "icon-check",
+			checkboxUnknown: "icon-check icon-muted",
+			error: "icon-exclamation-sign",
+			expanderClosed: "icon-caret-right",
+			expanderLazy: "icon-angle-right",
+			expanderOpen: "icon-caret-down",
+			noExpander: "",
+			dragHelper: "icon-caret-right",
+			dropMarker: "icon-caret-right",
+			// Default node icons.
+			// (Use tree.options.iconClass callback to define custom icons
+			// based on node data)
+			doc: "icon-file-alt",
+			docOpen: "icon-file-alt",
+			loading: "icon-refresh icon-spin",
+			folder: "icon-folder-close-alt",
+			folderOpen: "icon-folder-open-alt"
+		}
+	},
+
+	treeInit: function(ctx){
+		var tree = ctx.tree;
+		this._superApply(arguments);
+		tree.$container.addClass("fancytree-ext-glyph");
+	},
+	nodeRenderStatus: function(ctx) {
+		var icon, span,
+			node = ctx.node,
+			$span = $(node.span),
+			opts = ctx.options.glyph,
+			// callback = opts.icon,
+			map = opts.map
+			// $span = $(node.span)
+			;
+
+		this._superApply(arguments);
+
+		if( node.isRoot() ){
+			return;
+		}
+		span = $span.children("span.fancytree-expander").get(0);
+		if( span ){
+			if( node.isLoading() ){
+				icon = "loading";
+			}else if( node.expanded ){
+				icon = "expanderOpen";
+			}else if( node.isUndefined() ){
+				icon = "expanderLazy";
+			}else if( node.hasChildren() ){
+				icon = "expanderClosed";
+			}else{
+				icon = "noExpander";
+			}
+			span.className = "fancytree-expander " + map[icon];
+		}
+
+		if( node.tr ){
+			span = $("td", node.tr).find("span.fancytree-checkbox").get(0);
+		}else{
+			span = $span.children("span.fancytree-checkbox").get(0);
+		}
+		if( span ){
+			icon = node.selected ? "checkboxSelected" : (node.partsel ? "checkboxUnknown" : "checkbox");
+			span.className = "fancytree-checkbox " + map[icon];
+		}
+
+		// Icon (note that this does not match .fancytree-custom-icon, that might
+		// be set by opts.iconClass)
+		span = $span.children("span.fancytree-icon").get(0);
+		if( span ){
+			if( node.folder ){
+				icon = node.expanded ? _getIcon(opts, "folderOpen") : _getIcon(opts, "folder");
+			}else{
+				icon = node.expanded ? _getIcon(opts, "docOpen") : _getIcon(opts, "doc");
+			}
+			span.className = "fancytree-icon " + icon;
+		}
+	},
+	nodeSetStatus: function(ctx, status, message, details) {
+		var span,
+			opts = ctx.options.glyph,
+			node = ctx.node;
+
+		this._superApply(arguments);
+
+		if(node.parent){
+			span = $("span.fancytree-expander", node.span).get(0);
+		}else{
+			span = $(".fancytree-statusnode-wait, .fancytree-statusnode-error", node[this.nodeContainerAttrName])
+				.find("span.fancytree-expander").get(0);
+		}
+		if( status === "loading"){
+			// $("span.fancytree-expander", ctx.node.span).addClass(_getIcon(opts, "loading"));
+			span.className = "fancytree-expander " + _getIcon(opts, "loading");
+		}else if( status === "error"){
+			span.className = "fancytree-expander " + _getIcon(opts, "error");
+		}
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.gridnav.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.gridnav.js
new file mode 100644
index 00000000000..d700c2a54d2
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.gridnav.js
@@ -0,0 +1,199 @@
+/*!
+ * jquery.fancytree.gridnav.js
+ *
+ * Support keyboard navigation for trees with embedded input controls.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+
+// Allow these navigation keys even when input controls are focused
+
+var	KC = $.ui.keyCode,
+	// which keys are *not* handled by embedded control, but passed to tree
+	// navigation handler:
+	NAV_KEYS = {
+		"text": [KC.UP, KC.DOWN],
+		"checkbox": [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+		"radiobutton": [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+		"select-one": [KC.LEFT, KC.RIGHT],
+		"select-multiple": [KC.LEFT, KC.RIGHT]
+	};
+
+
+/* Calculate TD column index (considering colspans).*/
+function getColIdx($tr, $td) {
+	var colspan,
+		td = $td.get(0),
+		idx = 0;
+
+	$tr.children().each(function () {
+		if( this === td ) {
+			return false;
+		}
+		colspan = $(this).prop("colspan");
+		idx += colspan ? colspan : 1;
+	});
+	return idx;
+}
+
+
+/* Find TD at given column index (considering colspans).*/
+function findTdAtColIdx($tr, colIdx) {
+	var colspan,
+		res = null,
+		idx = 0;
+
+	$tr.children().each(function () {
+		if( idx >= colIdx ) {
+			res = $(this);
+			return false;
+		}
+		colspan = $(this).prop("colspan");
+		idx += colspan ? colspan : 1;
+	});
+	return res;
+}
+
+
+/* Find adjacent cell for a given direction. Skip empty cells and consider merged cells */
+function findNeighbourTd($target, keyCode){
+	var $tr, colIdx,
+		$td = $target.closest("td"),
+		$tdNext = null;
+
+	switch( keyCode ){
+		case KC.LEFT:
+			$tdNext = $td.prev();
+			break;
+		case KC.RIGHT:
+			$tdNext = $td.next();
+			break;
+		case KC.UP:
+		case KC.DOWN:
+			$tr = $td.parent();
+			colIdx = getColIdx($tr, $td);
+			while( true ) {
+				$tr = (keyCode === KC.UP) ? $tr.prev() : $tr.next();
+				if( !$tr.length ) {
+					break;
+				}
+				// Skip hidden rows
+				if( $tr.is(":hidden") ) {
+					continue;
+				}
+				// Find adjacent cell in the same column
+				$tdNext = findTdAtColIdx($tr, colIdx);
+				// Skip cells that don't conatain a focusable element
+				if( $tdNext && $tdNext.find(":input").length ) {
+					break;
+				}
+			}
+			break;
+	}
+	return $tdNext;
+}
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "gridnav",
+	version: "0.0.1",
+	// Default options for this extension.
+	options: {
+		autofocusInput:   false,  // Focus first embedded input if node gets activated
+		handleCursorKeys: true   // Allow UP/DOWN in inputs to move to prev/next node
+	},
+
+	treeInit: function(ctx){
+		// gridnav requires the table extension to be loaded before itself
+		this._requireExtension("table", true, true);
+		this._superApply(arguments);
+
+		this.$container.addClass("fancytree-ext-gridnav");
+
+		// Activate node if embedded input gets focus (due to a click)
+		this.$container.on("focusin", function(event){
+			var ctx2,
+				node = $.ui.fancytree.getNode(event.target);
+
+			if( node && !node.isActive() ){
+				// Call node.setActive(), but also pass the event
+				ctx2 = ctx.tree._makeHookContext(node, event);
+				ctx.tree._callHook("nodeSetActive", ctx2, true);
+			}
+		});
+	},
+	nodeSetActive: function(ctx, flag) {
+		var $outer,
+			opts = ctx.options.gridnav,
+			node = ctx.node,
+			event = ctx.originalEvent || {},
+			triggeredByInput = $(event.target).is(":input");
+
+		flag = (flag !== false);
+
+		this._superApply(arguments);
+
+		if( flag ){
+			if( ctx.options.titlesTabbable ){
+				if( !triggeredByInput ) {
+					$(node.span).find("span.fancytree-title").focus();
+					node.setFocus();
+				}
+				// If one node is tabbable, the container no longer needs to be
+				ctx.tree.$container.attr("tabindex", "-1");
+				// ctx.tree.$container.removeAttr("tabindex");
+			} else if( opts.autofocusInput && !triggeredByInput ){
+				// Set focus to input sub input (if node was clicked, but not
+				// when TAB was pressed )
+				$outer = $(node.tr || node.span);
+				$outer.find(":input:enabled:first").focus();
+			}
+		}
+	},
+	nodeKeydown: function(ctx) {
+		var inputType, handleKeys, $td,
+			opts = ctx.options.gridnav,
+			event = ctx.originalEvent,
+			$target = $(event.target);
+
+		// jQuery
+		inputType = $target.is(":input:enabled") ? $target.prop("type") : null;
+//		ctx.tree.debug("ext-gridnav nodeKeydown", event, inputType);
+
+		if( inputType && opts.handleCursorKeys ){
+			handleKeys = NAV_KEYS[inputType];
+			if( handleKeys && $.inArray(event.which, handleKeys) >= 0 ){
+				$td = findNeighbourTd($target, event.which);
+				// ctx.node.debug("ignore keydown in input", event.which, handleKeys);
+				if( $td && $td.length ) {
+					$td.find(":input:enabled").focus();
+					// Prevent Fancytree default navigation
+					return false;
+				}
+			}
+			return true;
+		}
+		// ctx.tree.debug("ext-gridnav NOT HANDLED", event, inputType);
+		return this._superApply(arguments);
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.js
new file mode 100644
index 00000000000..95de0d3735c
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.js
@@ -0,0 +1,4515 @@
+/*!
+ * jquery.fancytree.js
+ * Tree view control with support for lazy loading and much more.
+ * https://github.com/mar10/fancytree/
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+/** Core Fancytree module.
+ */
+
+
+// Start of local namespace
+;(function($, window, document, undefined) {
+"use strict";
+
+// prevent duplicate loading
+if ( $.ui && $.ui.fancytree ) {
+	$.ui.fancytree.warn("Fancytree: ignored duplicate include");
+	return;
+}
+
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+
+function _assert(cond, msg){
+	// TODO: see qunit.js extractStacktrace()
+	if(!cond){
+		msg = msg ? ": " + msg : "";
+		// consoleApply("assert", [!!cond, msg]);
+		$.error("Fancytree assertion failed" + msg);
+	}
+}
+
+_assert($.ui, "Fancytree requires jQuery UI (http://jqueryui.com)");
+
+function consoleApply(method, args){
+	var i, s,
+		fn = window.console ? window.console[method] : null;
+
+	if(fn){
+		try{
+			fn.apply(window.console, args);
+		} catch(e) {
+			// IE 8?
+			s = "";
+			for( i=0; i<args.length; i++){
+				s += args[i];
+			}
+			fn(s);
+		}
+	}
+}
+
+/*Return true if x is a FancytreeNode.*/
+function _isNode(x){
+	return !!(x.tree && x.statusNodeType !== undefined);
+}
+
+/** Return true if dotted version string is equal or higher than requested version.
+ *
+ * See http://jsfiddle.net/mar10/FjSAN/
+ */
+function isVersionAtLeast(dottedVersion, major, minor, patch){
+	var i, v, t,
+		verParts = $.map($.trim(dottedVersion).split("."), function(e){ return parseInt(e, 10); }),
+		testParts = $.map(Array.prototype.slice.call(arguments, 1), function(e){ return parseInt(e, 10); });
+
+	for( i = 0; i < testParts.length; i++ ){
+		v = verParts[i] || 0;
+		t = testParts[i] || 0;
+		if( v !== t ){
+			return ( v > t );
+		}
+	}
+	return true;
+}
+
+/** Return a wrapper that calls sub.methodName() and exposes
+ *  this        : tree
+ *  this._local : tree.ext.EXTNAME
+ *  this._super : base.methodName()
+ */
+function _makeVirtualFunction(methodName, tree, base, extension, extName){
+	// $.ui.fancytree.debug("_makeVirtualFunction", methodName, tree, base, extension, extName);
+	// if(rexTestSuper && !rexTestSuper.test(func)){
+	//     // extension.methodName() doesn't call _super(), so no wrapper required
+	//     return func;
+	// }
+	// Use an immediate function as closure
+	var proxy = (function(){
+		var prevFunc = tree[methodName],      // org. tree method or prev. proxy
+			baseFunc = extension[methodName], //
+			_local = tree.ext[extName],
+			_super = function(){
+				return prevFunc.apply(tree, arguments);
+			},
+			_superApply = function(args){
+				return prevFunc.apply(tree, args);
+			};
+
+		// Return the wrapper function
+		return function(){
+			var prevLocal = tree._local,
+				prevSuper = tree._super,
+				prevSuperApply = tree._superApply;
+
+			try{
+				tree._local = _local;
+				tree._super = _super;
+				tree._superApply = _superApply;
+				return  baseFunc.apply(tree, arguments);
+			}finally{
+				tree._local = prevLocal;
+				tree._super = prevSuper;
+				tree._superApply = prevSuperApply;
+			}
+		};
+	})(); // end of Immediate Function
+	return proxy;
+}
+
+/**
+ * Subclass `base` by creating proxy functions
+ */
+function _subclassObject(tree, base, extension, extName){
+	// $.ui.fancytree.debug("_subclassObject", tree, base, extension, extName);
+	for(var attrName in extension){
+		if(typeof extension[attrName] === "function"){
+			if(typeof tree[attrName] === "function"){
+				// override existing method
+				tree[attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);
+			}else if(attrName.charAt(0) === "_"){
+				// Create private methods in tree.ext.EXTENSION namespace
+				tree.ext[extName][attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);
+			}else{
+				$.error("Could not override tree." + attrName + ". Use prefix '_' to create tree." + extName + "._" + attrName);
+			}
+		}else{
+			// Create member variables in tree.ext.EXTENSION namespace
+			if(attrName !== "options"){
+				tree.ext[extName][attrName] = extension[attrName];
+			}
+		}
+	}
+}
+
+
+function _getResolvedPromise(context, argArray){
+	if(context === undefined){
+		return $.Deferred(function(){this.resolve();}).promise();
+	}else{
+		return $.Deferred(function(){this.resolveWith(context, argArray);}).promise();
+	}
+}
+
+
+function _getRejectedPromise(context, argArray){
+	if(context === undefined){
+		return $.Deferred(function(){this.reject();}).promise();
+	}else{
+		return $.Deferred(function(){this.rejectWith(context, argArray);}).promise();
+	}
+}
+
+
+function _makeResolveFunc(deferred, context){
+	return function(){
+		deferred.resolveWith(context);
+	};
+}
+
+
+function _getElementDataAsDict($el){
+	// Evaluate 'data-NAME' attributes with special treatment for 'data-json'.
+	var d = $.extend({}, $el.data()),
+		json = d.json;
+
+	delete d.fancytree; // added to container by widget factory (old jQuery UI)
+	delete d.uiFancytree; // added to container by widget factory
+
+	if( json ) {
+		delete d.json;
+		// <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)
+		d = $.extend(d, json);
+	}
+	return d;
+}
+
+
+// TODO: use currying
+function _makeNodeTitleMatcher(s){
+	s = s.toLowerCase();
+	return function(node){
+		return node.title.toLowerCase().indexOf(s) >= 0;
+	};
+}
+
+
+function _makeNodeTitleStartMatcher(s){
+	var reMatch = new RegExp("^" + s, "i");
+	return function(node){
+		return reMatch.test(node.title);
+	};
+}
+
+var i, attr,
+	FT = null, // initialized below
+	ENTITY_MAP = {"&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;", "/": "&#x2F;"},
+	IGNORE_KEYCODES = { 16: true, 17: true, 18: true },
+	SPECIAL_KEYCODES = {
+		8: "backspace", 9: "tab", 10: "return", 13: "return",
+		// 16: null, 17: null, 18: null, // ignore shift, ctrl, alt
+		19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup",
+		34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up",
+		39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=",
+		96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6",
+		103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".",
+		111: "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5",
+		117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11",
+		123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=",
+		188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
+		221: "]", 222: "'"},
+	MOUSE_BUTTONS = { 0: "", 1: "left", 2: "middle", 3: "right" },
+	//boolean attributes that can be set with equivalent class names in the LI tags
+	CLASS_ATTRS = "active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),
+	CLASS_ATTR_MAP = {},
+	//	Top-level Fancytree node attributes, that can be set by dict
+	NODE_ATTRS = "expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "),
+	NODE_ATTR_MAP = {},
+	// Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)
+	NODE_ATTR_LOWERCASE_MAP = {},
+	// Attribute names that should NOT be added to node.data
+	NONE_NODE_DATA_MAP = {"active": true, "children": true, "data": true, "focus": true};
+
+for(i=0; i<CLASS_ATTRS.length; i++){ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true; }
+for(i=0; i<NODE_ATTRS.length; i++) {
+	attr = NODE_ATTRS[i];
+	NODE_ATTR_MAP[attr] = true;
+	if( attr !== attr.toLowerCase() ) {
+		NODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;
+	}
+}
+
+
+/* *****************************************************************************
+ * FancytreeNode
+ */
+
+
+/**
+ * Creates a new FancytreeNode
+ *
+ * @class FancytreeNode
+ * @classdesc A FancytreeNode represents the hierarchical data model and operations.
+ *
+ * @param {FancytreeNode} parent
+ * @param {NodeData} obj
+ *
+ * @property {Fancytree} tree The tree instance
+ * @property {FancytreeNode} parent The parent node
+ * @property {string} key Node id (must be unique inside the tree)
+ * @property {string} title Display name (may contain HTML)
+ * @property {object} data Contains all extra data that was passed on node creation
+ * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>
+ *     For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array
+ *     to define a node that has no children.
+ * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.
+ * @property {string} extraClasses Addtional CSS classes, added to the node's `&lt;span>`
+ * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>
+ *     Note: Also non-folders may have children.
+ * @property {string} statusNodeType null or type of temporarily generated system node like 'loading', or 'error'.
+ * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.
+ * @property {boolean} selected Use isSelected(), setSelected() to access this property.
+ * @property {string} tooltip Alternative description used as hover banner
+ */
+function FancytreeNode(parent, obj){
+	var i, l, name, cl;
+
+	this.parent = parent;
+	this.tree = parent.tree;
+	this.ul = null;
+	this.li = null;  // <li id='key' ftnode=this> tag
+	this.statusNodeType = null; // if this is a temp. node to display the status of its parent
+	this._isLoading = false;    // if this node itself is loading
+	this._error = null;         // {message: '...'} if a load error occurred
+	this.data = {};
+
+	// TODO: merge this code with node.toDict()
+	// copy attributes from obj object
+	for(i=0, l=NODE_ATTRS.length; i<l; i++){
+		name = NODE_ATTRS[i];
+		this[name] = obj[name];
+	}
+	// node.data += obj.data
+	if(obj.data){
+		$.extend(this.data, obj.data);
+	}
+	// copy all other attributes to this.data.NAME
+	for(name in obj){
+		if(!NODE_ATTR_MAP[name] && !$.isFunction(obj[name]) && !NONE_NODE_DATA_MAP[name]){
+			// node.data.NAME = obj.NAME
+			this.data[name] = obj[name];
+		}
+	}
+
+	// Fix missing key
+	if( this.key == null ){ // test for null OR undefined
+		if( this.tree.options.defaultKey ) {
+			this.key = this.tree.options.defaultKey(this);
+			_assert(this.key, "defaultKey() must return a unique key");
+		} else {
+			this.key = "_" + (FT._nextNodeKey++);
+		}
+	} else {
+		this.key = "" + this.key; // Convert to string (#217)
+	}
+
+	// Fix tree.activeNode
+	// TODO: not elegant: we use obj.active as marker to set tree.activeNode
+	// when loading from a dictionary.
+	if(obj.active){
+		_assert(this.tree.activeNode === null, "only one active node allowed");
+		this.tree.activeNode = this;
+	}
+	if( obj.selected ){ // #186
+		this.tree.lastSelectedNode = this;
+	}
+	// TODO: handle obj.focus = true
+	// Create child nodes
+	cl = obj.children;
+	if( cl ){
+		if( cl.length ){
+			this._setChildren(cl);
+		} else {
+			// if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'
+			this.children = this.lazy ? [] : null;
+		}
+	} else {
+		this.children = null;
+	}
+	// Add to key/ref map (except for root node)
+//	if( parent ) {
+	this.tree._callHook("treeRegisterNode", this.tree, true, this);
+//	}
+}
+
+
+FancytreeNode.prototype = /** @lends FancytreeNode# */{
+	/* Return the direct child FancytreeNode with a given key, index. */
+	_findDirectChild: function(ptr){
+		var i, l,
+			cl = this.children;
+
+		if(cl){
+			if(typeof ptr === "string"){
+				for(i=0, l=cl.length; i<l; i++){
+					if(cl[i].key === ptr){
+						return cl[i];
+					}
+				}
+			}else if(typeof ptr === "number"){
+				return this.children[ptr];
+			}else if(ptr.parent === this){
+				return ptr;
+			}
+		}
+		return null;
+	},
+	// TODO: activate()
+	// TODO: activateSilently()
+	/* Internal helper called in recursive addChildren sequence.*/
+	_setChildren: function(children){
+		_assert(children && (!this.children || this.children.length === 0), "only init supported");
+		this.children = [];
+		for(var i=0, l=children.length; i<l; i++){
+			this.children.push(new FancytreeNode(this, children[i]));
+		}
+	},
+	/**
+	 * Append (or insert) a list of child nodes.
+	 *
+	 * @param {NodeData[]} children array of child node definitions (also single child accepted)
+	 * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).
+	 *     If omitted, the new children are appended.
+	 * @returns {FancytreeNode} first child added
+	 *
+	 * @see FancytreeNode#applyPatch
+	 */
+	addChildren: function(children, insertBefore){
+		var i, l, pos,
+			firstNode = null,
+			nodeList = [];
+
+		if($.isPlainObject(children) ){
+			children = [children];
+		}
+		if(!this.children){
+			this.children = [];
+		}
+		for(i=0, l=children.length; i<l; i++){
+			nodeList.push(new FancytreeNode(this, children[i]));
+		}
+		firstNode = nodeList[0];
+		if(insertBefore == null){
+			this.children = this.children.concat(nodeList);
+		}else{
+			insertBefore = this._findDirectChild(insertBefore);
+			pos = $.inArray(insertBefore, this.children);
+			_assert(pos >= 0, "insertBefore must be an existing child");
+			// insert nodeList after children[pos]
+			this.children.splice.apply(this.children, [pos, 0].concat(nodeList));
+		}
+		if( !this.parent || this.parent.ul || this.tr ){
+			// render if the parent was rendered (or this is a root node)
+			this.render();
+		}
+		if( this.tree.options.selectMode === 3 ){
+			this.fixSelection3FromEndNodes();
+		}
+		return firstNode;
+	},
+	/**
+	 * Append or prepend a node, or append a child node.
+	 *
+	 * This a convenience function that calls addChildren()
+	 *
+	 * @param {NodeData} node node definition
+	 * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
+	 * @returns {FancytreeNode} new node
+	 */
+	addNode: function(node, mode){
+		if(mode === undefined || mode === "over"){
+			mode = "child";
+		}
+		switch(mode){
+		case "after":
+			return this.getParent().addChildren(node, this.getNextSibling());
+		case "before":
+			return this.getParent().addChildren(node, this);
+		case "firstChild":
+			// Insert before the first child if any
+			var insertBefore = (this.children ? this.children[0] : null);
+			return this.addChildren(node, insertBefore);
+		case "child":
+		case "over":
+			return this.addChildren(node);
+		}
+		_assert(false, "Invalid mode: " + mode);
+	},
+	/**
+	 * Append new node after this.
+	 *
+	 * This a convenience function that calls addNode(node, 'after')
+	 *
+	 * @param {NodeData} node node definition
+	 * @returns {FancytreeNode} new node
+	 */
+	appendSibling: function(node){
+		return this.addNode(node, "after");
+	},
+	/**
+	 * Modify existing child nodes.
+	 *
+	 * @param {NodePatch} patch
+	 * @returns {$.Promise}
+	 * @see FancytreeNode#addChildren
+	 */
+	applyPatch: function(patch) {
+		// patch [key, null] means 'remove'
+		if(patch === null){
+			this.remove();
+			return _getResolvedPromise(this);
+		}
+		// TODO: make sure that root node is not collapsed or modified
+		// copy (most) attributes to node.ATTR or node.data.ATTR
+		var name, promise, v,
+			IGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global
+
+		for(name in patch){
+			v = patch[name];
+			if( !IGNORE_MAP[name] && !$.isFunction(v)){
+				if(NODE_ATTR_MAP[name]){
+					this[name] = v;
+				}else{
+					this.data[name] = v;
+				}
+			}
+		}
+		// Remove and/or create children
+		if(patch.hasOwnProperty("children")){
+			this.removeChildren();
+			if(patch.children){ // only if not null and not empty list
+				// TODO: addChildren instead?
+				this._setChildren(patch.children);
+			}
+			// TODO: how can we APPEND or INSERT child nodes?
+		}
+		if(this.isVisible()){
+			this.renderTitle();
+			this.renderStatus();
+		}
+		// Expand collapse (final step, since this may be async)
+		if(patch.hasOwnProperty("expanded")){
+			promise = this.setExpanded(patch.expanded);
+		}else{
+			promise = _getResolvedPromise(this);
+		}
+		return promise;
+	},
+	/** Collapse all sibling nodes.
+	 * @returns {$.Promise}
+	 */
+	collapseSiblings: function() {
+		return this.tree._callHook("nodeCollapseSiblings", this);
+	},
+	/** Copy this node as sibling or child of `node`.
+	 *
+	 * @param {FancytreeNode} node source node
+	 * @param {string} [mode=child] 'before' | 'after' | 'child'
+	 * @param {Function} [map] callback function(NodeData) that could modify the new node
+	 * @returns {FancytreeNode} new
+	 */
+	copyTo: function(node, mode, map) {
+		return node.addNode(this.toDict(true, map), mode);
+	},
+	/** Count direct and indirect children.
+	 *
+	 * @param {boolean} [deep=true] pass 'false' to only count direct children
+	 * @returns {int} number of child nodes
+	 */
+	countChildren: function(deep) {
+		var cl = this.children, i, l, n;
+		if( !cl ){
+			return 0;
+		}
+		n = cl.length;
+		if(deep !== false){
+			for(i=0, l=n; i<l; i++){
+				n += cl[i].countChildren();
+			}
+		}
+		return n;
+	},
+	// TODO: deactivate()
+	/** Write to browser console if debugLevel >= 2 (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	debug: function(msg){
+		if( this.tree.options.debugLevel >= 2 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("log", arguments);
+		}
+	},
+	/** Deprecated.
+	 * @deprecated since 2014-02-16. Use resetLazy() instead.
+	 */
+	discard: function(){
+		this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead.");
+		return this.resetLazy();
+	},
+
+	// TODO: expand(flag)
+
+	/**Find all nodes that match condition (excluding self).
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode[]} array of nodes (may be empty)
+	 */
+	findAll: function(match) {
+		match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);
+		var res = [];
+		this.visit(function(n){
+			if(match(n)){
+				res.push(n);
+			}
+		});
+		return res;
+	},
+	/**Find first node that matches condition (excluding self).
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode} matching node or null
+	 * @see FancytreeNode#findAll
+	 */
+	findFirst: function(match) {
+		match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);
+		var res = null;
+		this.visit(function(n){
+			if(match(n)){
+				res = n;
+				return false;
+			}
+		});
+		return res;
+	},
+	/* Apply selection state (internal use only) */
+	_changeSelectStatusAttrs: function (state) {
+		var changed = false;
+
+		switch(state){
+		case false:
+			changed = ( this.selected || this.partsel );
+			this.selected = false;
+			this.partsel = false;
+			break;
+		case true:
+			changed = ( !this.selected || !this.partsel );
+			this.selected = true;
+			this.partsel = true;
+			break;
+		case undefined:
+			changed = ( this.selected || !this.partsel );
+			this.selected = false;
+			this.partsel = true;
+			break;
+		default:
+			_assert(false, "invalid state: " + state);
+		}
+		// this.debug("fixSelection3AfterLoad() _changeSelectStatusAttrs()", state, changed);
+		if( changed ){
+			this.renderStatus();
+		}
+		return changed;
+	},
+	/**
+	 * Fix selection status, after this node was (de)selected in multi-hier mode.
+	 * This includes (de)selecting all children.
+	 */
+	fixSelection3AfterClick: function() {
+		var flag = this.isSelected();
+
+//		this.debug("fixSelection3AfterClick()");
+
+		this.visit(function(node){
+			node._changeSelectStatusAttrs(flag);
+		});
+		this.fixSelection3FromEndNodes();
+	},
+	/**
+	 * Fix selection status for multi-hier mode.
+	 * Only end-nodes are considered to update the descendants branch and parents.
+	 * Should be called after this node has loaded new children or after
+	 * children have been modified using the API.
+	 */
+	fixSelection3FromEndNodes: function() {
+//		this.debug("fixSelection3FromEndNodes()");
+		_assert(this.tree.options.selectMode === 3, "expected selectMode 3");
+
+		// Visit all end nodes and adjust their parent's `selected` and `partsel`
+		// attributes. Return selection state true, false, or undefined.
+		function _walk(node){
+			var i, l, child, s, state, allSelected,someSelected,
+				children = node.children;
+
+			if( children && children.length ){
+				// check all children recursively
+				allSelected = true;
+				someSelected = false;
+
+				for( i=0, l=children.length; i<l; i++ ){
+					child = children[i];
+					// the selection state of a node is not relevant; we need the end-nodes
+					s = _walk(child);
+					if( s !== false ) {
+						someSelected = true;
+					}
+					if( s !== true ) {
+						allSelected = false;
+					}
+				}
+				state = allSelected ? true : (someSelected ? undefined : false);
+			}else{
+				// This is an end-node: simply report the status
+//				state = ( node.unselectable ) ? undefined : !!node.selected;
+				state = !!node.selected;
+			}
+			node._changeSelectStatusAttrs(state);
+			return state;
+		}
+		_walk(this);
+
+		// Update parent's state
+		this.visitParents(function(node){
+			var i, l, child, state,
+				children = node.children,
+				allSelected = true,
+				someSelected = false;
+
+			for( i=0, l=children.length; i<l; i++ ){
+				child = children[i];
+				// When fixing the parents, we trust the sibling status (i.e.
+				// we don't recurse)
+				if( child.selected || child.partsel ) {
+					someSelected = true;
+				}
+				if( !child.unselectable && !child.selected ) {
+					allSelected = false;
+				}
+			}
+			state = allSelected ? true : (someSelected ? undefined : false);
+			node._changeSelectStatusAttrs(state);
+		});
+	},
+	// TODO: focus()
+	/**
+	 * Update node data. If dict contains 'children', then also replace
+	 * the hole sub tree.
+	 * @param {NodeData} dict
+	 *
+	 * @see FancytreeNode#addChildren
+	 * @see FancytreeNode#applyPatch
+	 */
+	fromDict: function(dict) {
+		// copy all other attributes to this.data.xxx
+		for(var name in dict){
+			if(NODE_ATTR_MAP[name]){
+				// node.NAME = dict.NAME
+				this[name] = dict[name];
+			}else if(name === "data"){
+				// node.data += dict.data
+				$.extend(this.data, dict.data);
+			}else if(!$.isFunction(dict[name]) && !NONE_NODE_DATA_MAP[name]){
+				// node.data.NAME = dict.NAME
+				this.data[name] = dict[name];
+			}
+		}
+		if(dict.children){
+			// recursively set children and render
+			this.removeChildren();
+			this.addChildren(dict.children);
+		}
+		this.renderTitle();
+/*
+		var children = dict.children;
+		if(children === undefined){
+			this.data = $.extend(this.data, dict);
+			this.render();
+			return;
+		}
+		dict = $.extend({}, dict);
+		dict.children = undefined;
+		this.data = $.extend(this.data, dict);
+		this.removeChildren();
+		this.addChild(children);
+*/
+	},
+	/** Return the list of child nodes (undefined for unexpanded lazy nodes).
+	 * @returns {FancytreeNode[] | undefined}
+	 */
+	getChildren: function() {
+		if(this.hasChildren() === undefined){ // TODO: only required for lazy nodes?
+			return undefined; // Lazy node: unloaded, currently loading, or load error
+		}
+		return this.children;
+	},
+	/** Return the first child node or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getFirstChild: function() {
+		return this.children ? this.children[0] : null;
+	},
+	/** Return the 0-based child index.
+	 * @returns {int}
+	 */
+	getIndex: function() {
+//		return this.parent.children.indexOf(this);
+		return $.inArray(this, this.parent.children); // indexOf doesn't work in IE7
+	},
+	/** Return the hierarchical child index (1-based, e.g. '3.2.4').
+	 * @returns {string}
+	 */
+	getIndexHier: function(separator) {
+		separator = separator || ".";
+		var res = [];
+		$.each(this.getParentList(false, true), function(i, o){
+			res.push(o.getIndex() + 1);
+		});
+		return res.join(separator);
+	},
+	/** Return the parent keys separated by options.keyPathSeparator, e.g. "id_1/id_17/id_32".
+	 * @param {boolean} [excludeSelf=false]
+	 * @returns {string}
+	 */
+	getKeyPath: function(excludeSelf) {
+		var path = [],
+			sep = this.tree.options.keyPathSeparator;
+		this.visitParents(function(n){
+			if(n.parent){
+				path.unshift(n.key);
+			}
+		}, !excludeSelf);
+		return sep + path.join(sep);
+	},
+	/** Return the last child of this node or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getLastChild: function() {
+		return this.children ? this.children[this.children.length - 1] : null;
+	},
+	/** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .
+	 * @returns {int}
+	 */
+	getLevel: function() {
+		var level = 0,
+			dtn = this.parent;
+		while( dtn ) {
+			level++;
+			dtn = dtn.parent;
+		}
+		return level;
+	},
+	/** Return the successor node (under the same parent) or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getNextSibling: function() {
+		// TODO: use indexOf, if available: (not in IE6)
+		if( this.parent ){
+			var i, l,
+				ac = this.parent.children;
+
+			for(i=0, l=ac.length-1; i<l; i++){ // up to length-2, so next(last) = null
+				if( ac[i] === this ){
+					return ac[i+1];
+				}
+			}
+		}
+		return null;
+	},
+	/** Return the parent node (null for the system root node).
+	 * @returns {FancytreeNode | null}
+	 */
+	getParent: function() {
+		// TODO: return null for top-level nodes?
+		return this.parent;
+	},
+	/** Return an array of all parent nodes (top-down).
+	 * @param {boolean} [includeRoot=false] Include the invisible system root node.
+	 * @param {boolean} [includeSelf=false] Include the node itself.
+	 * @returns {FancytreeNode[]}
+	 */
+	getParentList: function(includeRoot, includeSelf) {
+		var l = [],
+			dtn = includeSelf ? this : this.parent;
+		while( dtn ) {
+			if( includeRoot || dtn.parent ){
+				l.unshift(dtn);
+			}
+			dtn = dtn.parent;
+		}
+		return l;
+	},
+	/** Return the predecessor node (under the same parent) or null.
+	 * @returns {FancytreeNode | null}
+	 */
+	getPrevSibling: function() {
+		if( this.parent ){
+			var i, l,
+				ac = this.parent.children;
+
+			for(i=1, l=ac.length; i<l; i++){ // start with 1, so prev(first) = null
+				if( ac[i] === this ){
+					return ac[i-1];
+				}
+			}
+		}
+		return null;
+	},
+	/** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).
+	 * @returns {boolean | undefined}
+	 */
+	hasChildren: function() {
+		if(this.lazy){
+			if(this.children == null ){
+				// null or undefined: Not yet loaded
+				return undefined;
+			}else if(this.children.length === 0){
+				// Loaded, but response was empty
+				return false;
+			}else if(this.children.length === 1 && this.children[0].isStatusNode() ){
+				// Currently loading or load error
+				return undefined;
+			}
+			return true;
+		}
+		return !!( this.children && this.children.length );
+	},
+	/** Return true if node has keyboard focus.
+	 * @returns {boolean}
+	 */
+	hasFocus: function() {
+		return (this.tree.hasFocus() && this.tree.focusNode === this);
+	},
+	/** Write to browser console if debugLevel >= 1 (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	info: function(msg){
+		if( this.tree.options.debugLevel >= 1 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("info", arguments);
+		}
+	},
+	/** Return true if node is active (see also FancytreeNode#isSelected).
+	 * @returns {boolean}
+	 */
+	isActive: function() {
+		return (this.tree.activeNode === this);
+	},
+	/** Return true if node is a direct child of otherNode.
+	 * @param {FancytreeNode} otherNode
+	 * @returns {boolean}
+	 */
+	isChildOf: function(otherNode) {
+		return (this.parent && this.parent === otherNode);
+	},
+	/** Return true, if node is a direct or indirect sub node of otherNode.
+	 * @param {FancytreeNode} otherNode
+	 * @returns {boolean}
+	 */
+	isDescendantOf: function(otherNode) {
+		if(!otherNode || otherNode.tree !== this.tree){
+			return false;
+		}
+		var p = this.parent;
+		while( p ) {
+			if( p === otherNode ){
+				return true;
+			}
+			p = p.parent;
+		}
+		return false;
+	},
+	/** Return true if node is expanded.
+	 * @returns {boolean}
+	 */
+	isExpanded: function() {
+		return !!this.expanded;
+	},
+	/** Return true if node is the first node of its parent's children.
+	 * @returns {boolean}
+	 */
+	isFirstSibling: function() {
+		var p = this.parent;
+		return !p || p.children[0] === this;
+	},
+	/** Return true if node is a folder, i.e. has the node.folder attribute set.
+	 * @returns {boolean}
+	 */
+	isFolder: function() {
+		return !!this.folder;
+	},
+	/** Return true if node is the last node of its parent's children.
+	 * @returns {boolean}
+	 */
+	isLastSibling: function() {
+		var p = this.parent;
+		return !p || p.children[p.children.length-1] === this;
+	},
+	/** Return true if node is lazy (even if data was already loaded)
+	 * @returns {boolean}
+	 */
+	isLazy: function() {
+		return !!this.lazy;
+	},
+	/** Return true if node is lazy and loaded. For non-lazy nodes always return true.
+	 * @returns {boolean}
+	 */
+	isLoaded: function() {
+		return !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node
+	},
+	/** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.
+	 * @returns {boolean}
+	 */
+	isLoading: function() {
+		return !!this._isLoading;
+	},
+	/*
+	 * @deprecated since v2.4.0:  Use isRootNode() instead
+	 */
+	isRoot: function() {
+		return this.isRootNode();
+	},
+	/** Return true if this is the (invisible) system root node.
+	 * @returns {boolean}
+	 * @since 2.4
+	 */
+	isRootNode: function() {
+		return (this.tree.rootNode === this);
+	},
+	/** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).
+	 * @returns {boolean}
+	 */
+	isSelected: function() {
+		return !!this.selected;
+	},
+	/** Return true if this node is a temporarily generated system node like
+	 * 'loading', or 'error' (node.statusNodeType contains the type).
+	 * @returns {boolean}
+	 */
+	isStatusNode: function() {
+		return !!this.statusNodeType;
+	},
+	/** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.
+	 * @returns {boolean}
+	 * @since 2.4
+	 */
+	isTopLevel: function() {
+		return (this.tree.rootNode === this.parent);
+	},
+	/** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.
+	 * @returns {boolean}
+	 */
+	isUndefined: function() {
+		return this.hasChildren() === undefined; // also checks if the only child is a status node
+	},
+	/** Return true if all parent nodes are expanded. Note: this does not check
+	 * whether the node is scrolled into the visible part of the screen.
+	 * @returns {boolean}
+	 */
+	isVisible: function() {
+		var i, l,
+			parents = this.getParentList(false, false);
+
+		for(i=0, l=parents.length; i<l; i++){
+			if( ! parents[i].expanded ){ return false; }
+		}
+		return true;
+	},
+	/** Deprecated.
+	 * @deprecated since 2014-02-16: use load() instead.
+	 */
+	lazyLoad: function(discard) {
+		this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.");
+		return this.load(discard);
+	},
+	/**
+	 * Load all children of a lazy node if neccessary. The *expanded* state is maintained.
+	 * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before.
+	 * @returns {$.Promise}
+	 */
+	load: function(forceReload) {
+		var res, source,
+			that = this;
+
+		_assert( this.isLazy(), "load() requires a lazy node" );
+		// _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" );
+		if( !forceReload && !this.isUndefined() ) {
+			return _getResolvedPromise(this);
+		}
+		if( this.isLoaded() ){
+			this.resetLazy(); // also collapses
+		}
+		// This method is also called by setExpanded() and loadKeyPath(), so we
+		// have to avoid recursion.
+		source = this.tree._triggerNodeEvent("lazyLoad", this);
+		if( source === false ) { // #69
+			return _getResolvedPromise(this);
+		}
+		_assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+		res = this.tree._callHook("nodeLoadChildren", this, source);
+		if( this.expanded ) {
+			res.always(function(){
+				that.render();
+			});
+		}
+		return res;
+	},
+	/** Expand all parents and optionally scroll into visible area as neccessary.
+	 * Promise is resolved, when lazy loading and animations are done.
+	 * @param {object} [opts] passed to `setExpanded()`.
+	 *     Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
+	 * @returns {$.Promise}
+	 */
+	makeVisible: function(opts) {
+		var i,
+			that = this,
+			deferreds = [],
+			dfd = new $.Deferred(),
+			parents = this.getParentList(false, false),
+			len = parents.length,
+			effects = !(opts && opts.noAnimation === true),
+			scroll = !(opts && opts.scrollIntoView === false);
+
+		// Expand bottom-up, so only the top node is animated
+		for(i = len - 1; i >= 0; i--){
+			// that.debug("pushexpand" + parents[i]);
+			deferreds.push(parents[i].setExpanded(true, opts));
+		}
+		$.when.apply($, deferreds).done(function(){
+			// All expands have finished
+			// that.debug("expand DONE", scroll);
+			if( scroll ){
+				that.scrollIntoView(effects).done(function(){
+					// that.debug("scroll DONE");
+					dfd.resolve();
+				});
+			} else {
+				dfd.resolve();
+			}
+		});
+		return dfd.promise();
+	},
+	/** Move this node to targetNode.
+	 *  @param {FancytreeNode} targetNode
+	 *  @param {string} mode <pre>
+	 *      'child': append this node as last child of targetNode.
+	 *               This is the default. To be compatble with the D'n'd
+	 *               hitMode, we also accept 'over'.
+	 *      'before': add this node as sibling before targetNode.
+	 *      'after': add this node as sibling after targetNode.</pre>
+	 *  @param {function} [map] optional callback(FancytreeNode) to allow modifcations
+	 */
+	moveTo: function(targetNode, mode, map) {
+		if(mode === undefined || mode === "over"){
+			mode = "child";
+		}
+		var pos,
+			prevParent = this.parent,
+			targetParent = (mode === "child") ? targetNode : targetNode.parent;
+
+		if(this === targetNode){
+			return;
+		}else if( !this.parent  ){
+			throw "Cannot move system root";
+		}else if( targetParent.isDescendantOf(this) ){
+			throw "Cannot move a node to its own descendant";
+		}
+		// Unlink this node from current parent
+		if( this.parent.children.length === 1 ) {
+			if( this.parent === targetParent ){
+				return; // #258
+			}
+			this.parent.children = this.parent.lazy ? [] : null;
+			this.parent.expanded = false;
+		} else {
+			pos = $.inArray(this, this.parent.children);
+			_assert(pos >= 0, "invalid source parent");
+			this.parent.children.splice(pos, 1);
+		}
+		// Remove from source DOM parent
+//		if(this.parent.ul){
+//			this.parent.ul.removeChild(this.li);
+//		}
+
+		// Insert this node to target parent's child list
+		this.parent = targetParent;
+		if( targetParent.hasChildren() ) {
+			switch(mode) {
+			case "child":
+				// Append to existing target children
+				targetParent.children.push(this);
+				break;
+			case "before":
+				// Insert this node before target node
+				pos = $.inArray(targetNode, targetParent.children);
+				_assert(pos >= 0, "invalid target parent");
+				targetParent.children.splice(pos, 0, this);
+				break;
+			case "after":
+				// Insert this node after target node
+				pos = $.inArray(targetNode, targetParent.children);
+				_assert(pos >= 0, "invalid target parent");
+				targetParent.children.splice(pos+1, 0, this);
+				break;
+			default:
+				throw "Invalid mode " + mode;
+			}
+		} else {
+			targetParent.children = [ this ];
+		}
+		// Parent has no <ul> tag yet:
+//		if( !targetParent.ul ) {
+//			// This is the parent's first child: create UL tag
+//			// (Hidden, because it will be
+//			targetParent.ul = document.createElement("ul");
+//			targetParent.ul.style.display = "none";
+//			targetParent.li.appendChild(targetParent.ul);
+//		}
+//		// Issue 319: Add to target DOM parent (only if node was already rendered(expanded))
+//		if(this.li){
+//			targetParent.ul.appendChild(this.li);
+//		}^
+
+		// Let caller modify the nodes
+		if( map ){
+			targetNode.visit(map, true);
+		}
+		// Handle cross-tree moves
+		if( this.tree !== targetNode.tree ) {
+			// Fix node.tree for all source nodes
+//			_assert(false, "Cross-tree move is not yet implemented.");
+			this.warn("Cross-tree moveTo is experimantal!");
+			this.visit(function(n){
+				// TODO: fix selection state and activation, ...
+				n.tree = targetNode.tree;
+			}, true);
+		}
+
+		// A collaposed node won't re-render children, so we have to remove it manually
+		// if( !targetParent.expanded ){
+		//   prevParent.ul.removeChild(this.li);
+		// }
+
+		// Update HTML markup
+		if( !prevParent.isDescendantOf(targetParent)) {
+			prevParent.render();
+		}
+		if( !targetParent.isDescendantOf(prevParent) && targetParent !== prevParent) {
+			targetParent.render();
+		}
+		// TODO: fix selection state
+		// TODO: fix active state
+
+/*
+		var tree = this.tree;
+		var opts = tree.options;
+		var pers = tree.persistence;
+
+
+		// Always expand, if it's below minExpandLevel
+//		tree.logDebug ("%s._addChildNode(%o), l=%o", this, ftnode, ftnode.getLevel());
+		if ( opts.minExpandLevel >= ftnode.getLevel() ) {
+//			tree.logDebug ("Force expand for %o", ftnode);
+			this.bExpanded = true;
+		}
+
+		// In multi-hier mode, update the parents selection state
+		// DT issue #82: only if not initializing, because the children may not exist yet
+//		if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )
+//			ftnode._fixSelectionState();
+
+		// In multi-hier mode, update the parents selection state
+		if( ftnode.bSelected && opts.selectMode==3 ) {
+			var p = this;
+			while( p ) {
+				if( !p.hasSubSel )
+					p._setSubSel(true);
+				p = p.parent;
+			}
+		}
+		// render this node and the new child
+		if ( tree.bEnableUpdate )
+			this.render();
+
+		return ftnode;
+
+*/
+	},
+	/** Set focus relative to this node and optionally activate.
+	 *
+	 * @param {number} where The keyCode that would normally trigger this move,
+	 *		e.g. `$.ui.keyCode.LEFT` would collapse the node if it
+	 *      is expanded or move to the parent oterwise.
+	 * @param {boolean} [activate=true]
+	 * @returns {$.Promise}
+	 */
+	// navigate: function(where, activate) {
+	// 	console.time("navigate")
+	// 	this._navigate(where, activate)
+	// 	console.timeEnd("navigate")
+	// },
+	navigate: function(where, activate) {
+		var i, parents,
+			handled = true,
+			KC = $.ui.keyCode,
+			sib = null;
+
+		// Navigate to node
+		function _goto(n){
+			if( n ){
+				try { n.makeVisible(); } catch(e) {} // #272
+				// Node may still be hidden by a filter
+				if( ! $(n.span).is(":visible") ) {
+					n.debug("Navigate: skipping hidden node");
+					n.navigate(where, activate);
+					return;
+				}
+				return activate === false ? n.setFocus() : n.setActive();
+			}
+		}
+
+		switch( where ) {
+			case KC.BACKSPACE:
+				if( this.parent && this.parent.parent ) {
+					_goto(this.parent);
+				}
+				break;
+			case KC.LEFT:
+				if( this.expanded ) {
+					this.setExpanded(false);
+					_goto(this);
+				} else if( this.parent && this.parent.parent ) {
+					_goto(this.parent);
+				}
+				break;
+			case KC.RIGHT:
+				if( !this.expanded && (this.children || this.lazy) ) {
+					this.setExpanded();
+					_goto(this);
+				} else if( this.children && this.children.length ) {
+					_goto(this.children[0]);
+				}
+				break;
+			case KC.UP:
+				sib = this.getPrevSibling();
+				// #359: skip hidden sibling nodes, preventing a _goto() recursion
+				while( sib && !$(sib.span).is(":visible") ) {
+					sib = sib.getPrevSibling();
+				}
+				while( sib && sib.expanded && sib.children && sib.children.length ) {
+					sib = sib.children[sib.children.length - 1];
+				}
+				if( !sib && this.parent && this.parent.parent ){
+					sib = this.parent;
+				}
+				_goto(sib);
+				break;
+			case KC.DOWN:
+				if( this.expanded && this.children && this.children.length ) {
+					sib = this.children[0];
+				} else {
+					parents = this.getParentList(false, true);
+					for(i=parents.length-1; i>=0; i--) {
+						sib = parents[i].getNextSibling();
+						// #359: skip hidden sibling nodes, preventing a _goto() recursion
+						while( sib && !$(sib.span).is(":visible") ) {
+							sib = sib.getNextSibling();
+						}
+						if( sib ){ break; }
+					}
+				}
+				_goto(sib);
+				break;
+			default:
+				handled = false;
+		}
+	},
+	/**
+	 * Remove this node (not allowed for system root).
+	 */
+	remove: function() {
+		return this.parent.removeChild(this);
+	},
+	/**
+	 * Remove childNode from list of direct children.
+	 * @param {FancytreeNode} childNode
+	 */
+	removeChild: function(childNode) {
+		return this.tree._callHook("nodeRemoveChild", this, childNode);
+	},
+	/**
+	 * Remove all child nodes and descendents. This converts the node into a leaf.<br>
+	 * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()
+	 * in order to trigger lazyLoad on next expand.
+	 */
+	removeChildren: function() {
+		return this.tree._callHook("nodeRemoveChildren", this);
+	},
+	/**
+	 * This method renders and updates all HTML markup that is required
+	 * to display this node in its current state.<br>
+	 * Note:
+	 * <ul>
+	 * <li>It should only be neccessary to call this method after the node object
+	 *     was modified by direct access to its properties, because the common
+	 *     API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)
+	 *     already handle this.
+	 * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}
+	 *     are implied. If changes are more local, calling only renderTitle() or
+	 *     renderStatus() may be sufficient and faster.
+	 * <li>If a node was created/removed, node.render() must be called <i>on the parent</i>.
+	 * </ul>
+	 *
+	 * @param {boolean} [force=false] re-render, even if html markup was already created
+	 * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+	 */
+	render: function(force, deep) {
+		return this.tree._callHook("nodeRender", this, force, deep);
+	},
+	/** Create HTML markup for the node's outer &lt;span> (expander, checkbox, icon, and title).
+	 * Implies {@link FancytreeNode#renderStatus}.
+	 * @see Fancytree_Hooks#nodeRenderTitle
+	 */
+	renderTitle: function() {
+		return this.tree._callHook("nodeRenderTitle", this);
+	},
+	/** Update element's CSS classes according to node state.
+	 * @see Fancytree_Hooks#nodeRenderStatus
+	 */
+	renderStatus: function() {
+		return this.tree._callHook("nodeRenderStatus", this);
+	},
+	/**
+	 * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
+	 * event is triggered on next expand.
+	 */
+	resetLazy: function() {
+		this.removeChildren();
+		this.expanded = false;
+		this.lazy = true;
+		this.children = undefined;
+		this.renderStatus();
+	},
+	/** Schedule activity for delayed execution (cancel any pending request).
+	 *  scheduleAction('cancel') will only cancel a pending request (if any).
+	 * @param {string} mode
+	 * @param {number} ms
+	 */
+	scheduleAction: function(mode, ms) {
+		if( this.tree.timer ) {
+			clearTimeout(this.tree.timer);
+//            this.tree.debug("clearTimeout(%o)", this.tree.timer);
+		}
+		this.tree.timer = null;
+		var self = this; // required for closures
+		switch (mode) {
+		case "cancel":
+			// Simply made sure that timer was cleared
+			break;
+		case "expand":
+			this.tree.timer = setTimeout(function(){
+				self.tree.debug("setTimeout: trigger expand");
+				self.setExpanded(true);
+			}, ms);
+			break;
+		case "activate":
+			this.tree.timer = setTimeout(function(){
+				self.tree.debug("setTimeout: trigger activate");
+				self.setActive(true);
+			}, ms);
+			break;
+		default:
+			throw "Invalid mode " + mode;
+		}
+//        this.tree.debug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer);
+	},
+	/**
+	 *
+	 * @param {boolean | PlainObject} [effects=false] animation options.
+	 * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in
+	 *     any case, even if `this` is outside the scroll pane.
+	 * @returns {$.Promise}
+	 */
+	scrollIntoView: function(effects, options) {
+		if( options !== undefined && _isNode(options) ) {
+			this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.");
+			options = {topNode: options};
+		}
+		// this.$scrollParent = (this.options.scrollParent === "auto") ? $ul.scrollParent() : $(this.options.scrollParent);
+		// this.$scrollParent = this.$scrollParent.length ? this.$scrollParent || this.$container;
+
+		var topNodeY, nodeY, horzScrollbarHeight, containerOffsetTop,
+			opts = $.extend({
+				effects: (effects === true) ? {duration: 200, queue: false} : effects,
+				scrollOfs: this.tree.options.scrollOfs,
+				scrollParent: this.tree.options.scrollParent || this.tree.$container,
+				topNode: null
+			}, options),
+			dfd = new $.Deferred(),
+			that = this,
+			nodeHeight = $(this.span).height(),
+			$container = $(opts.scrollParent),
+			topOfs = opts.scrollOfs.top || 0,
+			bottomOfs = opts.scrollOfs.bottom || 0,
+			containerHeight = $container.height(),// - topOfs - bottomOfs,
+			scrollTop = $container.scrollTop(),
+			$animateTarget = $container,
+			isParentWindow = $container[0] === window,
+			topNode = opts.topNode || null,
+			newScrollTop = null;
+
+		// this.debug("scrollIntoView(), scrollTop=", scrollTop, opts.scrollOfs);
+//		_assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets
+		if( !$(this.span).is(":visible") ) {
+			// We cannot calc offsets for hidden elements
+			this.warn("scrollIntoView(): node is invisible.");
+			return _getResolvedPromise();
+		}
+		if( isParentWindow ) {
+			nodeY = $(this.span).offset().top;
+			topNodeY = (topNode && topNode.span) ? $(topNode.span).offset().top : 0;
+			$animateTarget = $("html,body");
+
+		} else {
+			_assert($container[0] !== document && $container[0] !== document.body, "scrollParent should be an simple element or `window`, not document or body.");
+
+			containerOffsetTop = $container.offset().top,
+			nodeY = $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent
+			topNodeY = topNode ? $(topNode.span).offset().top - containerOffsetTop  + scrollTop : 0;
+			horzScrollbarHeight = Math.max(0, ($container.innerHeight() - $container[0].clientHeight));
+			containerHeight -= horzScrollbarHeight;
+		}
+
+		// this.debug("    scrollIntoView(), nodeY=", nodeY, "containerHeight=", containerHeight);
+		if( nodeY < (scrollTop + topOfs) ){
+			// Node is above visible container area
+			newScrollTop = nodeY - topOfs;
+			// this.debug("    scrollIntoView(), UPPER newScrollTop=", newScrollTop);
+
+		}else if((nodeY + nodeHeight) > (scrollTop + containerHeight - bottomOfs)){
+			newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;
+			// this.debug("    scrollIntoView(), LOWER newScrollTop=", newScrollTop);
+			// If a topNode was passed, make sure that it is never scrolled
+			// outside the upper border
+			if(topNode){
+				_assert(topNode.isRootNode() || $(topNode.span).is(":visible"), "topNode must be visible");
+				if( topNodeY < newScrollTop ){
+					newScrollTop = topNodeY - topOfs;
+					// this.debug("    scrollIntoView(), TOP newScrollTop=", newScrollTop);
+				}
+			}
+		}
+
+		if(newScrollTop !== null){
+			// this.debug("    scrollIntoView(), SET newScrollTop=", newScrollTop);
+			if(opts.effects){
+				opts.effects.complete = function(){
+					dfd.resolveWith(that);
+				};
+				$animateTarget.stop(true).animate({
+					scrollTop: newScrollTop
+				}, opts.effects);
+			}else{
+				$animateTarget[0].scrollTop = newScrollTop;
+				dfd.resolveWith(this);
+			}
+		}else{
+			dfd.resolveWith(this);
+		}
+		return dfd.promise();
+	},
+
+	/**Activate this node.
+	 * @param {boolean} [flag=true] pass false to deactivate
+	 * @param {object} [opts] additional options. Defaults to {noEvents: false}
+	 * @returns {$.Promise}
+	 */
+	setActive: function(flag, opts){
+		return this.tree._callHook("nodeSetActive", this, flag, opts);
+	},
+	/**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.
+	 * @param {boolean} [flag=true] pass false to collapse
+	 * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+	 * @returns {$.Promise}
+	 */
+	setExpanded: function(flag, opts){
+		return this.tree._callHook("nodeSetExpanded", this, flag, opts);
+	},
+	/**Set keyboard focus to this node.
+	 * @param {boolean} [flag=true] pass false to blur
+	 * @see Fancytree#setFocus
+	 */
+	setFocus: function(flag){
+		return this.tree._callHook("nodeSetFocus", this, flag);
+	},
+	/**Select this node, i.e. check the checkbox.
+	 * @param {boolean} [flag=true] pass false to deselect
+	 */
+	setSelected: function(flag){
+		return this.tree._callHook("nodeSetSelected", this, flag);
+	},
+	/**Mark a lazy node as 'error', 'loading', or 'ok'.
+	 * @param {string} status 'error', 'ok'
+	 * @param {string} [message]
+	 * @param {string} [details]
+	 */
+	setStatus: function(status, message, details){
+		return this.tree._callHook("nodeSetStatus", this, status, message, details);
+	},
+	/**Rename this node.
+	 * @param {string} title
+	 */
+	setTitle: function(title){
+		this.title = title;
+		this.renderTitle();
+	},
+	/**Sort child list by title.
+	 * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).
+	 * @param {boolean} [deep=false] pass true to sort all descendant nodes
+	 */
+	sortChildren: function(cmp, deep) {
+		var i,l,
+			cl = this.children;
+
+		if( !cl ){
+			return;
+		}
+		cmp = cmp || function(a, b) {
+			var x = a.title.toLowerCase(),
+				y = b.title.toLowerCase();
+			return x === y ? 0 : x > y ? 1 : -1;
+			};
+		cl.sort(cmp);
+		if( deep ){
+			for(i=0, l=cl.length; i<l; i++){
+				if( cl[i].children ){
+					cl[i].sortChildren(cmp, "$norender$");
+				}
+			}
+		}
+		if( deep !== "$norender$" ){
+			this.render();
+		}
+	},
+	/** Convert node (or whole branch) into a plain object.
+	 *
+	 * The result is compatible with node.addChildren().
+	 *
+	 * @param {boolean} [recursive=false] include child nodes
+	 * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications
+	 * @returns {NodeData}
+	 */
+	toDict: function(recursive, callback) {
+		var i, l, node,
+			dict = {},
+			self = this;
+
+		$.each(NODE_ATTRS, function(i, a){
+			if(self[a] || self[a] === false){
+				dict[a] = self[a];
+			}
+		});
+		if(!$.isEmptyObject(this.data)){
+			dict.data = $.extend({}, this.data);
+			if($.isEmptyObject(dict.data)){
+				delete dict.data;
+			}
+		}
+		if( callback ){
+			callback(dict, self);
+		}
+		if( recursive ) {
+			if(this.hasChildren()){
+				dict.children = [];
+				for(i=0, l=this.children.length; i<l; i++ ){
+					node = this.children[i];
+					if( !node.isStatusNode() ){
+						dict.children.push(node.toDict(true, callback));
+					}
+				}
+			}else{
+//                dict.children = null;
+			}
+		}
+		return dict;
+	},
+	/** Flip expanded status.  */
+	toggleExpanded: function(){
+		return this.tree._callHook("nodeToggleExpanded", this);
+	},
+	/** Flip selection status.  */
+	toggleSelected: function(){
+		return this.tree._callHook("nodeToggleSelected", this);
+	},
+	toString: function() {
+		return "<FancytreeNode(#" + this.key + ", '" + this.title + "')>";
+	},
+	/** Call fn(node) for all child nodes.<br>
+	 * Stop iteration, if fn() returns false. Skip current branch, if fn() returns "skip".<br>
+	 * Return false if iteration was stopped.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and
+	 *     its children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {boolean}
+	 */
+	visit: function(fn, includeSelf) {
+		var i, l,
+			res = true,
+			children = this.children;
+
+		if( includeSelf === true ) {
+			res = fn(this);
+			if( res === false || res === "skip" ){
+				return res;
+			}
+		}
+		if(children){
+			for(i=0, l=children.length; i<l; i++){
+				res = children[i].visit(fn, true);
+				if( res === false ){
+					break;
+				}
+			}
+		}
+		return res;
+	},
+	/** Call fn(node) for all child nodes and recursively load lazy children.<br>
+	 * <b>Note:</b> If you need this method, you probably should consider to review
+	 * your architecture! Recursivley loading nodes is a perfect way for lazy
+	 * programmers to flood the server with requests ;-)
+	 *
+	 * @param {function} [fn] optional callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and
+	 *     its children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {$.Promise}
+	 * @since 2.4
+	 */
+	visitAndLoad: function(fn, includeSelf, _recursion) {
+		var dfd, res, loaders,
+			node = this;
+
+		// node.debug("visitAndLoad");
+		if( fn && includeSelf === true ) {
+			res = fn(node);
+			if( res === false || res === "skip" ) {
+				return _recursion ? res : _getResolvedPromise();
+			}
+		}
+		if( !node.children && !node.lazy ) {
+			return _getResolvedPromise();
+		}
+		dfd = new $.Deferred();
+		loaders = [];
+		// node.debug("load()...");
+		node.load().done(function(){
+			// node.debug("load()... done.");
+			for(var i=0, l=node.children.length; i<l; i++){
+				res = node.children[i].visitAndLoad(fn, true, true);
+				if( res === false ) {
+					dfd.reject();
+					break;
+				} else if ( res !== "skip" ) {
+					loaders.push(res); // Add promise to the list
+				}
+			}
+			$.when.apply(this, loaders).then(function(){
+				dfd.resolve();
+			});
+		});
+		return dfd.promise();
+	},
+	/** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
+	 * Stop iteration, if fn() returns false.<br>
+	 * Return false if iteration was stopped.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and children only.
+	 * @param {boolean} [includeSelf=false]
+	 * @returns {boolean}
+	 */
+	visitParents: function(fn, includeSelf) {
+		// Visit parent nodes (bottom up)
+		if(includeSelf && fn(this) === false){
+			return false;
+		}
+		var p = this.parent;
+		while( p ) {
+			if(fn(p) === false){
+				return false;
+			}
+			p = p.parent;
+		}
+		return true;
+	},
+	/** Write warning to browser console (prepending node info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	warn: function(msg){
+		Array.prototype.unshift.call(arguments, this.toString());
+		consoleApply("warn", arguments);
+	}
+};
+
+
+/* *****************************************************************************
+ * Fancytree
+ */
+/**
+ * Construct a new tree object.
+ *
+ * @class Fancytree
+ * @classdesc The controller behind a fancytree.
+ * This class also contains 'hook methods': see {@link Fancytree_Hooks}.
+ *
+ * @param {Widget} widget
+ *
+ * @property {string} _id Automatically generated unique tree instance ID, e.g. "1".
+ * @property {string} _ns Automatically generated unique tree namespace, e.g. ".fancytree-1".
+ * @property {FancytreeNode} activeNode Currently active node or null.
+ * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.
+ *     Typically "li", but "tr" for table extension.
+ * @property {jQueryObject} $container Outer &lt;ul> element (or &lt;table> element for ext-table).
+ * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)
+ * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.
+ * @property {object} ext Hash of all active plugin instances.
+ * @property {FancytreeNode} focusNode Currently focused node or null.
+ * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)
+ * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.
+ *     Typically "li", but "tr" for table extension.
+ * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.
+ * @property {FancytreeNode} rootNode Invisible system root node.
+ * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.
+ *     Typically "span", but "tr" for table extension.
+ * @property {object} widget Base widget instance.
+ */
+function Fancytree(widget) {
+	this.widget = widget;
+	this.$div = widget.element;
+	this.options = widget.options;
+	if( this.options ) {
+		if(  $.isFunction(this.options.lazyload ) && !$.isFunction(this.options.lazyLoad) ) {
+			this.options.lazyLoad = function() {
+				FT.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead.");
+				return widget.options.lazyload.apply(this, arguments);
+			};
+		}
+		if( $.isFunction(this.options.loaderror) ) {
+			$.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead.");
+		}
+		if( this.options.fx !== undefined ) {
+			FT.warn("The 'fx' options was replaced by 'toggleEffect' since 2014-11-30.");
+		}
+	}
+	this.ext = {}; // Active extension instances
+	// allow to init tree.data.foo from <div data-foo=''>
+	this.data = _getElementDataAsDict(this.$div);
+	// TODO: use widget.uuid instead?
+	this._id = $.ui.fancytree._nextId++;
+	// TODO: use widget.eventNamespace instead?
+	this._ns = ".fancytree-" + this._id; // append for namespaced events
+	this.activeNode = null;
+	this.focusNode = null;
+	this._hasFocus = null;
+	this.lastSelectedNode = null;
+	this.systemFocusElement = null;
+	this.lastQuicksearchTerm = "";
+	this.lastQuicksearchTime = 0;
+
+	this.statusClassPropName = "span";
+	this.ariaPropName = "li";
+	this.nodeContainerAttrName = "li";
+
+	// Remove previous markup if any
+	this.$div.find(">ul.fancytree-container").remove();
+
+	// Create a node without parent.
+	var fakeParent = { tree: this },
+		$ul;
+	this.rootNode = new FancytreeNode(fakeParent, {
+		title: "root",
+		key: "root_" + this._id,
+		children: null,
+		expanded: true
+	});
+	this.rootNode.parent = null;
+
+	// Create root markup
+	$ul = $("<ul>", {
+		"class": "ui-fancytree fancytree-container fancytree-plain"
+	}).appendTo(this.$div);
+	this.$container = $ul;
+	this.rootNode.ul = $ul[0];
+
+	if(this.options.debugLevel == null){
+		this.options.debugLevel = FT.debugLevel;
+	}
+	// Add container to the TAB chain
+	// See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+	this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1");
+	if(this.options.aria){
+		this.$container
+			.attr("role", "tree")
+			.attr("aria-multiselectable", true);
+	}
+}
+
+
+Fancytree.prototype = /** @lends Fancytree# */{
+	/* Return a context object that can be re-used for _callHook().
+	 * @param {Fancytree | FancytreeNode | EventData} obj
+	 * @param {Event} originalEvent
+	 * @param {Object} extra
+	 * @returns {EventData}
+	 */
+	_makeHookContext: function(obj, originalEvent, extra) {
+		var ctx, tree;
+		if(obj.node !== undefined){
+			// obj is already a context object
+			if(originalEvent && obj.originalEvent !== originalEvent){
+				$.error("invalid args");
+			}
+			ctx = obj;
+		}else if(obj.tree){
+			// obj is a FancytreeNode
+			tree = obj.tree;
+			ctx = { node: obj, tree: tree, widget: tree.widget, options: tree.widget.options, originalEvent: originalEvent };
+		}else if(obj.widget){
+			// obj is a Fancytree
+			ctx = { node: null, tree: obj, widget: obj.widget, options: obj.widget.options, originalEvent: originalEvent };
+		}else{
+			$.error("invalid args");
+		}
+		if(extra){
+			$.extend(ctx, extra);
+		}
+		return ctx;
+	},
+	/* Trigger a hook function: funcName(ctx, [...]).
+	 *
+	 * @param {string} funcName
+	 * @param {Fancytree|FancytreeNode|EventData} contextObject
+	 * @param {any}  [_extraArgs] optional additional arguments
+	 * @returns {any}
+	 */
+	_callHook: function(funcName, contextObject, _extraArgs) {
+		var ctx = this._makeHookContext(contextObject),
+			fn = this[funcName],
+			args = Array.prototype.slice.call(arguments, 2);
+		if(!$.isFunction(fn)){
+			$.error("_callHook('" + funcName + "') is not a function");
+		}
+		args.unshift(ctx);
+//		this.debug("_hook", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);
+		return fn.apply(this, args);
+	},
+	/* Check if current extensions dependencies are met and throw an error if not.
+	 *
+	 * This method may be called inside the `treeInit` hook for custom extensions.
+	 *
+	 * @param {string} extension name of the required extension
+	 * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present
+	 * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)
+	 * @param {string} [message] optional error message (defaults to a descriptve error message)
+	 */
+	_requireExtension: function(name, required, before, message) {
+		before = !!before;
+		var thisName = this._local.name,
+			extList = this.options.extensions,
+			isBefore = $.inArray(name, extList) < $.inArray(thisName, extList),
+			isMissing = required && this.ext[name] == null,
+			badOrder = !isMissing && before != null && (before !== isBefore);
+
+		_assert(thisName && thisName !== name, "invalid or same name");
+
+		if( isMissing || badOrder ){
+			if( !message ){
+				if( isMissing || required ){
+					message = "'" + thisName + "' extension requires '" + name + "'";
+					if( badOrder ){
+						message += " to be registered " + (before ? "before" : "after") + " itself";
+					}
+				}else{
+					message = "If used together, `" + name + "` must be registered " + (before ? "before" : "after") + " `" + thisName + "`";
+				}
+			}
+			$.error(message);
+			return false;
+		}
+		return true;
+	},
+	/** Activate node with a given key and fire focus and activate events.
+	 *
+	 * A prevously activated node will be deactivated.
+	 * If activeVisible option is set, all parents will be expanded as necessary.
+	 * Pass key = false, to deactivate the current node only.
+	 * @param {string} key
+	 * @returns {FancytreeNode} activated node (null, if not found)
+	 */
+	activateKey: function(key) {
+		var node = this.getNodeByKey(key);
+		if(node){
+			node.setActive();
+		}else if(this.activeNode){
+			this.activeNode.setActive(false);
+		}
+		return node;
+	},
+	/** (experimental)
+	 *
+	 * @param {Array} patchList array of [key, NodePatch] arrays
+	 * @returns {$.Promise} resolved, when all patches have been applied
+	 * @see TreePatch
+	 */
+	applyPatch: function(patchList) {
+		var dfd, i, p2, key, patch, node,
+			patchCount = patchList.length,
+			deferredList = [];
+
+		for(i=0; i<patchCount; i++){
+			p2 = patchList[i];
+			_assert(p2.length === 2, "patchList must be an array of length-2-arrays");
+			key = p2[0];
+			patch = p2[1];
+			node = (key === null) ? this.rootNode : this.getNodeByKey(key);
+			if(node){
+				dfd = new $.Deferred();
+				deferredList.push(dfd);
+				node.applyPatch(patch).always(_makeResolveFunc(dfd, node));
+			}else{
+				this.warn("could not find node with key '" + key + "'");
+			}
+		}
+		// Return a promise that is resolved, when ALL patches were applied
+		return $.when.apply($, deferredList).promise();
+	},
+	/* TODO: implement in dnd extension
+	cancelDrag: function() {
+		var dd = $.ui.ddmanager.current;
+		if(dd){
+			dd.cancel();
+		}
+	},
+   */
+   /** Return the number of nodes.
+	* @returns {integer}
+	*/
+	count: function() {
+		return this.rootNode.countChildren();
+	},
+	/** Write to browser console if debugLevel >= 2 (prepending tree name)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	debug: function(msg){
+		if( this.options.debugLevel >= 2 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("log", arguments);
+		}
+	},
+	// TODO: disable()
+	// TODO: enable()
+	// TODO: enableUpdate()
+
+	/**Find all nodes that matches condition.
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode[]} array of nodes (may be empty)
+	 * @see FancytreeNode#findAll
+	 * @since 2.12
+	 */
+	findAll: function(match) {
+		return this.rootNode.findAll(match);
+	},
+	/**Find first node that matches condition.
+	 *
+	 * @param {string | function(node)} match title string to search for, or a
+	 *     callback function that returns `true` if a node is matched.
+	 * @returns {FancytreeNode} matching node or null
+	 * @see FancytreeNode#findFirst
+	 * @since 2.12
+	 */
+	findFirst: function(match) {
+		return this.rootNode.findFirst(match);
+	},
+	/** Find the next visible node that starts with `match`, starting at `startNode`
+	 * and wrap-around at the end.
+	 *
+	 * @param {string|function} match
+	 * @param {FancytreeNode} [startNode] defaults to first node
+	 * @returns {FancytreeNode} matching node or null
+	 */
+	findNextNode: function(match, startNode, visibleOnly) {
+		var stopNode = null,
+			parentChildren = startNode.parent.children,
+			matchingNode = null,
+			walkVisible = function(parent, idx, fn) {
+				var i, grandParent,
+					parentChildren = parent.children,
+					siblingCount = parentChildren.length,
+					node = parentChildren[idx];
+				// visit node itself
+				if( node && fn(node) === false ) {
+					return false;
+				}
+				// visit descendants
+				if( node && node.children && node.expanded ) {
+					if( walkVisible(node, 0, fn) === false ) {
+						return false;
+					}
+				}
+				// visit subsequent siblings
+				for( i = idx + 1; i < siblingCount; i++ ) {
+					if( walkVisible(parent, i, fn) === false ) {
+						return false;
+					}
+				}
+				// visit parent's subsequent siblings
+				grandParent = parent.parent;
+				if( grandParent ) {
+					return walkVisible(grandParent, grandParent.children.indexOf(parent) + 1, fn);
+				} else {
+					// wrap-around: restart with first node
+					return walkVisible(parent, 0, fn);
+				}
+			};
+
+		match = (typeof match === "string") ? _makeNodeTitleStartMatcher(match) : match;
+		startNode = startNode || this.getFirstChild();
+
+		walkVisible(startNode.parent, parentChildren.indexOf(startNode), function(node){
+			// Stop iteration if we see the start node a second time
+			if( node === stopNode ) {
+				return false;
+			}
+			stopNode = stopNode || node;
+			// Ignore nodes hidden by a filter
+			if( ! $(node.span).is(":visible") ) {
+				node.debug("quicksearch: skipping hidden node");
+				return;
+			}
+			// Test if we found a match, but search for a second match if this
+			// was the currently active node
+			if( match(node) ) {
+				// node.debug("quicksearch match " + node.title, startNode);
+				matchingNode = node;
+				if( matchingNode !== startNode ) {
+					return false;
+				}
+			}
+		});
+		return matchingNode;
+	},
+	// TODO: fromDict
+	/**
+	 * Generate INPUT elements that can be submitted with html forms.
+	 *
+	 * In selectMode 3 only the topmost selected nodes are considered, unless
+	 * `opts.stopOnParents: false` is passed.
+	 *
+	 * @param {boolean | string} [selected=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID[]')
+	 * @param {boolean | string} [active=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID_active')
+	 * @param {object} [opts] default { stopOnParents: true }
+	 */
+	generateFormElements: function(selected, active, opts) {
+		// TODO: test case
+		opts = opts || {};
+
+		var nodeList,
+			selectedName = (typeof selected === "string") ? selected : "ft_" + this._id + "[]",
+			activeName = (typeof active === "string") ? active : "ft_" + this._id + "_active",
+			id = "fancytree_result_" + this._id,
+			$result = $("#" + id),
+			stopOnParents = this.options.selectMode === 3 && opts.stopOnParents !== false;
+
+		if($result.length){
+			$result.empty();
+		}else{
+			$result = $("<div>", {
+				id: id
+			}).hide().insertAfter(this.$container);
+		}
+		if(selected !== false){
+			nodeList = this.getSelectedNodes(stopOnParents);
+			$.each(nodeList, function(idx, node){
+				$result.append($("<input>", {
+					type: "checkbox",
+					name: selectedName,
+					value: node.key,
+					checked: true
+				}));
+			});
+		}
+		if(active !== false && this.activeNode){
+			$result.append($("<input>", {
+				type: "radio",
+				name: activeName,
+				value: this.activeNode.key,
+				checked: true
+			}));
+		}
+	},
+	/**
+	 * Return the currently active node or null.
+	 * @returns {FancytreeNode}
+	 */
+	getActiveNode: function() {
+		return this.activeNode;
+	},
+	/** Return the first top level node if any (not the invisible root node).
+	 * @returns {FancytreeNode | null}
+	 */
+	getFirstChild: function() {
+		return this.rootNode.getFirstChild();
+	},
+	/**
+	 * Return node that has keyboard focus or null.
+	 * @returns {FancytreeNode}
+	 */
+	getFocusNode: function() {
+		return this.focusNode;
+	},
+	/**
+	 * Return node with a given key or null if not found.
+	 * @param {string} key
+	 * @param {FancytreeNode} [searchRoot] only search below this node
+	 * @returns {FancytreeNode | null}
+	 */
+	getNodeByKey: function(key, searchRoot) {
+		// Search the DOM by element ID (assuming this is faster than traversing all nodes).
+		// $("#...") has problems, if the key contains '.', so we use getElementById()
+		var el, match;
+		if(!searchRoot){
+			el = document.getElementById(this.options.idPrefix + key);
+			if( el ){
+				return el.ftnode ? el.ftnode : null;
+			}
+		}
+		// Not found in the DOM, but still may be in an unrendered part of tree
+		// TODO: optimize with specialized loop
+		// TODO: consider keyMap?
+		searchRoot = searchRoot || this.rootNode;
+		match = null;
+		searchRoot.visit(function(node){
+//            window.console.log("getNodeByKey(" + key + "): ", node.key);
+			if(node.key === key) {
+				match = node;
+				return false;
+			}
+		}, true);
+		return match;
+	},
+	/** Return the invisible system root node.
+	 * @returns {FancytreeNode}
+	 */
+	getRootNode: function() {
+		return this.rootNode;
+	},
+	/**
+	 * Return an array of selected nodes.
+	 * @param {boolean} [stopOnParents=false] only return the topmost selected
+	 *     node (useful with selectMode 3)
+	 * @returns {FancytreeNode[]}
+	 */
+	getSelectedNodes: function(stopOnParents) {
+		var nodeList = [];
+		this.rootNode.visit(function(node){
+			if( node.selected ) {
+				nodeList.push(node);
+				if( stopOnParents === true ){
+					return "skip"; // stop processing this branch
+				}
+			}
+		});
+		return nodeList;
+	},
+	/** Return true if the tree control has keyboard focus
+	 * @returns {boolean}
+	 */
+	hasFocus: function(){
+		return !!this._hasFocus;
+	},
+	/** Write to browser console if debugLevel >= 1 (prepending tree name)
+	 * @param {*} msg string or object or array of such
+	 */
+	info: function(msg){
+		if( this.options.debugLevel >= 1 ) {
+			Array.prototype.unshift.call(arguments, this.toString());
+			consoleApply("info", arguments);
+		}
+	},
+/*
+	TODO: isInitializing: function() {
+		return ( this.phase=="init" || this.phase=="postInit" );
+	},
+	TODO: isReloading: function() {
+		return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
+	},
+	TODO: isUserEvent: function() {
+		return ( this.phase=="userEvent" );
+	},
+*/
+
+	/**
+	 * Make sure that a node with a given ID is loaded, by traversing - and
+	 * loading - its parents. This method is ment for lazy hierarchies.
+	 * A callback is executed for every node as we go.
+	 * @example
+	 * tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){
+	 *   if(status === "loaded") {
+	 *     console.log("loaded intermiediate node " + node);
+	 *   }else if(status === "ok") {
+	 *     node.activate();
+	 *   }
+	 * });
+	 *
+	 * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')
+	 * @param {function} callback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error')
+	 * @returns {$.Promise}
+	 */
+	loadKeyPath: function(keyPathList, callback, _rootNode) {
+		var deferredList, dfd, i, path, key, loadMap, node, root, segList,
+			sep = this.options.keyPathSeparator,
+			self = this;
+
+		if(!$.isArray(keyPathList)){
+			keyPathList = [keyPathList];
+		}
+		// Pass 1: handle all path segments for nodes that are already loaded
+		// Collect distinct top-most lazy nodes in a map
+		loadMap = {};
+
+		for(i=0; i<keyPathList.length; i++){
+			root = _rootNode || this.rootNode;
+			path = keyPathList[i];
+			// strip leading slash
+			if(path.charAt(0) === sep){
+				path = path.substr(1);
+			}
+			// traverse and strip keys, until we hit a lazy, unloaded node
+			segList = path.split(sep);
+			while(segList.length){
+				key = segList.shift();
+//                node = _findDirectChild(root, key);
+				node = root._findDirectChild(key);
+				if(!node){
+					this.warn("loadKeyPath: key not found: " + key + " (parent: " + root + ")");
+					callback.call(this, key, "error");
+					break;
+				}else if(segList.length === 0){
+					callback.call(this, node, "ok");
+					break;
+				}else if(!node.lazy || (node.hasChildren() !== undefined )){
+					callback.call(this, node, "loaded");
+					root = node;
+				}else{
+					callback.call(this, node, "loaded");
+//                    segList.unshift(key);
+					if(loadMap[key]){
+						loadMap[key].push(segList.join(sep));
+					}else{
+						loadMap[key] = [segList.join(sep)];
+					}
+					break;
+				}
+			}
+		}
+//        alert("loadKeyPath: loadMap=" + JSON.stringify(loadMap));
+		// Now load all lazy nodes and continue itearation for remaining paths
+		deferredList = [];
+		// Avoid jshint warning 'Don't make functions within a loop.':
+		function __lazyload(key, node, dfd){
+			callback.call(self, node, "loading");
+			node.load().done(function(){
+				self.loadKeyPath.call(self, loadMap[key], callback, node).always(_makeResolveFunc(dfd, self));
+			}).fail(function(errMsg){
+				self.warn("loadKeyPath: error loading: " + key + " (parent: " + root + ")");
+				callback.call(self, node, "error");
+				dfd.reject();
+			});
+		}
+		for(key in loadMap){
+			node = root._findDirectChild(key);
+//            alert("loadKeyPath: lazy node(" + key + ") = " + node);
+			dfd = new $.Deferred();
+			deferredList.push(dfd);
+			__lazyload(key, node, dfd);
+		}
+		// Return a promise that is resolved, when ALL paths were loaded
+		return $.when.apply($, deferredList).promise();
+	},
+	/** Re-fire beforeActivate and activate events. */
+	reactivate: function(setFocus) {
+		var res,
+			node = this.activeNode;
+
+		if( !node ) {
+			return _getResolvedPromise();
+		}
+		this.activeNode = null; // Force re-activating
+		res = node.setActive();
+		if( setFocus ){
+			node.setFocus();
+		}
+		return res;
+	},
+	/** Reload tree from source and return a promise.
+	 * @param [source] optional new source (defaults to initial source data)
+	 * @returns {$.Promise}
+	 */
+	reload: function(source) {
+		this._callHook("treeClear", this);
+		return this._callHook("treeLoad", this, source);
+	},
+	/**Render tree (i.e. create DOM elements for all top-level nodes).
+	 * @param {boolean} [force=false] create DOM elemnts, even is parent is collapsed
+	 * @param {boolean} [deep=false]
+	 */
+	render: function(force, deep) {
+		return this.rootNode.render(force, deep);
+	},
+	// TODO: selectKey: function(key, select)
+	// TODO: serializeArray: function(stopOnParents)
+	/**
+	 * @param {boolean} [flag=true]
+	 */
+	setFocus: function(flag) {
+		return this._callHook("treeSetFocus", this, flag);
+	},
+	/**
+	 * Return all nodes as nested list of {@link NodeData}.
+	 *
+	 * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)
+	 * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications
+	 * @returns {Array | object}
+	 * @see FancytreeNode#toDict
+	 */
+	toDict: function(includeRoot, callback){
+		var res = this.rootNode.toDict(true, callback);
+		return includeRoot ? res : res.children;
+	},
+	/* Implicitly called for string conversions.
+	 * @returns {string}
+	 */
+	toString: function(){
+		return "<Fancytree(#" + this._id + ")>";
+	},
+	/* _trigger a widget event with additional node ctx.
+	 * @see EventData
+	 */
+	_triggerNodeEvent: function(type, node, originalEvent, extra) {
+//		this.debug("_trigger(" + type + "): '" + ctx.node.title + "'", ctx);
+		var ctx = this._makeHookContext(node, originalEvent, extra),
+			res = this.widget._trigger(type, originalEvent, ctx);
+		if(res !== false && ctx.result !== undefined){
+			return ctx.result;
+		}
+		return res;
+	},
+	/* _trigger a widget event with additional tree data. */
+	_triggerTreeEvent: function(type, originalEvent, extra) {
+//		this.debug("_trigger(" + type + ")", ctx);
+		var ctx = this._makeHookContext(this, originalEvent, extra),
+			res = this.widget._trigger(type, originalEvent, ctx);
+
+		if(res !== false && ctx.result !== undefined){
+			return ctx.result;
+		}
+		return res;
+	},
+	/** Call fn(node) for all nodes.
+	 *
+	 * @param {function} fn the callback function.
+	 *     Return false to stop iteration, return "skip" to skip this node and children only.
+	 * @returns {boolean} false, if the iterator was stopped.
+	 */
+	visit: function(fn) {
+		return this.rootNode.visit(fn, false);
+	},
+	/** Write warning to browser console (prepending tree info)
+	 *
+	 * @param {*} msg string or object or array of such
+	 */
+	warn: function(msg){
+		Array.prototype.unshift.call(arguments, this.toString());
+		consoleApply("warn", arguments);
+	}
+};
+
+/**
+ * These additional methods of the {@link Fancytree} class are 'hook functions'
+ * that can be used and overloaded by extensions.
+ * (See <a href="https://github.com/mar10/fancytree/wiki/TutorialExtensions">writing extensions</a>.)
+ * @mixin Fancytree_Hooks
+ */
+$.extend(Fancytree.prototype,
+	/** @lends Fancytree_Hooks# */
+	{
+	/** Default handling for mouse click events.
+	 *
+	 * @param {EventData} ctx
+	 */
+	nodeClick: function(ctx) {
+		var activate, expand,
+			// event = ctx.originalEvent,
+			targetType = ctx.targetType,
+			node = ctx.node;
+
+//	    this.debug("ftnode.onClick(" + event.type + "): ftnode:" + this + ", button:" + event.button + ", which: " + event.which, ctx);
+		// TODO: use switch
+		// TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)
+		if( targetType === "expander" ) {
+			if( node.isLoading() ) {
+				// #495: we probably got a click event while a lazy load is pending.
+				// The 'expanded' state is not yet set, so 'toggle' would expand
+				// and trigger lazyLoad again.
+				// It would be better to allow to collapse/expand the status node
+				// while loading (instead of ignoring), but that would require some
+				// more work.
+				node.debug("Got 2nd click while loading: ignored");
+				return;
+			}
+			// Clicking the expander icon always expands/collapses
+			this._callHook("nodeToggleExpanded", ctx);
+
+		} else if( targetType === "checkbox" ) {
+			// Clicking the checkbox always (de)selects
+			this._callHook("nodeToggleSelected", ctx);
+			if( ctx.options.focusOnSelect ) { // #358
+				this._callHook("nodeSetFocus", ctx, true);
+			}
+
+		} else {
+			// Honor `clickFolderMode` for
+			expand = false;
+			activate = true;
+			if( node.folder ) {
+				switch( ctx.options.clickFolderMode ) {
+				case 2: // expand only
+					expand = true;
+					activate = false;
+					break;
+				case 3: // expand and activate
+					activate = true;
+					expand = true; //!node.isExpanded();
+					break;
+				// else 1 or 4: just activate
+				}
+			}
+			if( activate ) {
+				this.nodeSetFocus(ctx);
+				this._callHook("nodeSetActive", ctx, true);
+			}
+			if( expand ) {
+				if(!activate){
+//                    this._callHook("nodeSetFocus", ctx);
+				}
+//				this._callHook("nodeSetExpanded", ctx, true);
+				this._callHook("nodeToggleExpanded", ctx);
+			}
+		}
+		// Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+		// if(event.target.localName === "a" && event.target.className === "fancytree-title"){
+		// 	event.preventDefault();
+		// }
+		// TODO: return promise?
+	},
+	/** Collapse all other  children of same parent.
+	 *
+	 * @param {EventData} ctx
+	 * @param {object} callOpts
+	 */
+	nodeCollapseSiblings: function(ctx, callOpts) {
+		// TODO: return promise?
+		var ac, i, l,
+			node = ctx.node;
+
+		if( node.parent ){
+			ac = node.parent.children;
+			for (i=0, l=ac.length; i<l; i++) {
+				if ( ac[i] !== node && ac[i].expanded ){
+					this._callHook("nodeSetExpanded", ac[i], false, callOpts);
+				}
+			}
+		}
+	},
+	/** Default handling for mouse douleclick events.
+	 * @param {EventData} ctx
+	 */
+	nodeDblclick: function(ctx) {
+		// TODO: return promise?
+		if( ctx.targetType === "title" && ctx.options.clickFolderMode === 4) {
+//			this.nodeSetFocus(ctx);
+//			this._callHook("nodeSetActive", ctx, true);
+			this._callHook("nodeToggleExpanded", ctx);
+		}
+		// TODO: prevent text selection on dblclicks
+		if( ctx.targetType === "title" ) {
+			ctx.originalEvent.preventDefault();
+		}
+	},
+	/** Default handling for mouse keydown events.
+	 *
+	 * NOTE: this may be called with node == null if tree (but no node) has focus.
+	 * @param {EventData} ctx
+	 */
+	nodeKeydown: function(ctx) {
+		// TODO: return promise?
+		var matchNode, stamp, res, focusNode,
+			event = ctx.originalEvent,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			which = event.which,
+			whichChar = String.fromCharCode(which),
+			clean = !(event.altKey || event.ctrlKey || event.metaKey || event.shiftKey),
+			$target = $(event.target),
+			handled = true,
+			activate = !(event.ctrlKey || !opts.autoActivate );
+
+//		(node || FT).debug("ftnode.nodeKeydown(" + event.type + "): ftnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+//		FT.debug("eventToString", which, '"' + String.fromCharCode(which) + '"', '"' + FT.eventToString(event) + '"');
+
+		// Set focus to active (or first node) if no other node has the focus yet
+		if( !node ){
+			focusNode = (this.getActiveNode() || this.getFirstChild());
+			if (focusNode){
+				focusNode.setFocus();
+				node = ctx.node = this.focusNode;
+				node.debug("Keydown force focus on active node");
+			}
+		}
+
+		if( opts.quicksearch && clean && /\w/.test(whichChar) && !$target.is(":input:enabled") ) {
+			// Allow to search for longer streaks if typed in quickly
+			stamp = new Date().getTime();
+			if( stamp - tree.lastQuicksearchTime > 500 ) {
+				tree.lastQuicksearchTerm = "";
+			}
+			tree.lastQuicksearchTime = stamp;
+			tree.lastQuicksearchTerm += whichChar;
+			// tree.debug("quicksearch find", tree.lastQuicksearchTerm);
+			matchNode = tree.findNextNode(tree.lastQuicksearchTerm, tree.getActiveNode());
+			if( matchNode ) {
+				matchNode.setActive();
+			}
+			event.preventDefault();
+			return;
+		}
+		switch( FT.eventToString(event) ) {
+			case "+":
+			case "=": // 187: '+' @ Chrome, Safari
+				tree.nodeSetExpanded(ctx, true);
+				break;
+			case "-":
+				tree.nodeSetExpanded(ctx, false);
+				break;
+			case "space":
+				if(opts.checkbox){
+					tree.nodeToggleSelected(ctx);
+				}else{
+					tree.nodeSetActive(ctx, true);
+				}
+				break;
+			case "return":
+				tree.nodeSetActive(ctx, true);
+				break;
+			case "backspace":
+			case "left":
+			case "right":
+			case "up":
+			case "down":
+				res = node.navigate(event.which, activate);
+				break;
+			default:
+				handled = false;
+		}
+		if(handled){
+			event.preventDefault();
+		}
+	},
+
+
+	// /** Default handling for mouse keypress events. */
+	// nodeKeypress: function(ctx) {
+	//     var event = ctx.originalEvent;
+	// },
+
+	// /** Trigger lazyLoad event (async). */
+	// nodeLazyLoad: function(ctx) {
+	//     var node = ctx.node;
+	//     if(this._triggerNodeEvent())
+	// },
+	/** Load child nodes (async).
+	 *
+	 * @param {EventData} ctx
+	 * @param {object[]|object|string|$.Promise|function} source
+	 * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)
+	 *     data was rendered.
+	 */
+	nodeLoadChildren: function(ctx, source) {
+		var ajax, delay, dfd,
+			tree = ctx.tree,
+			node = ctx.node;
+
+		if($.isFunction(source)){
+			source = source();
+		}
+		// TOTHINK: move to 'ajax' extension?
+		if(source.url){
+			// `source` is an Ajax options object
+			ajax = $.extend({}, ctx.options.ajax, source);
+			if(ajax.debugDelay){
+				// simulate a slow server
+				delay = ajax.debugDelay;
+				if($.isArray(delay)){ // random delay range [min..max]
+					delay = delay[0] + Math.random() * (delay[1] - delay[0]);
+				}
+
+				node.debug("nodeLoadChildren waiting debug delay " + Math.round(delay) + "ms");
+				ajax.debugDelay = false;
+				dfd = $.Deferred(function (dfd) {
+					setTimeout(function () {
+						$.ajax(ajax)
+							.done(function () {	dfd.resolveWith(this, arguments); })
+							.fail(function () {	dfd.rejectWith(this, arguments); });
+					}, delay);
+				});
+			}else{
+				dfd = $.ajax(ajax);
+			}
+
+			// Defer the deferred: we want to be able to reject, even if ajax
+			// resolved ok.
+			source = new $.Deferred();
+			dfd.done(function (data, textStatus, jqXHR) {
+				var errorObj, res;
+				if(this.dataType === "json" && typeof data === "string"){
+					$.error("Ajax request returned a string (did you get the JSON dataType wrong?).");
+				}
+				// postProcess is similar to the standard ajax dataFilter hook,
+				// but it is also called for JSONP
+				if( ctx.options.postProcess ){
+					res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, error: null, dataType: this.dataType});
+					if( res.error ) {
+						errorObj = $.isPlainObject(res.error) ? res.error : {message: res.error};
+						errorObj = tree._makeHookContext(node, null, errorObj);
+						source.rejectWith(this, [errorObj]);
+						return;
+					}
+					data = $.isArray(res) ? res : data;
+
+				} else if (data && data.hasOwnProperty("d") && ctx.options.enableAspx ) {
+					// Process ASPX WebMethod JSON object inside "d" property
+					data = (typeof data.d === "string") ? $.parseJSON(data.d) : data.d;
+				}
+				source.resolveWith(this, [data]);
+			}).fail(function (jqXHR, textStatus, errorThrown) {
+				var errorObj = tree._makeHookContext(node, null, {
+					error: jqXHR,
+					args: Array.prototype.slice.call(arguments),
+					message: errorThrown,
+					details: jqXHR.status + ": " + errorThrown
+				});
+				source.rejectWith(this, [errorObj]);
+			});
+		}
+		// #383: accept and convert ECMAScript 6 Promise
+		if( $.isFunction(source.then) && $.isFunction(source["catch"]) ) {
+			dfd = source;
+			source = new $.Deferred();
+			dfd.then(function(value){
+				source.resolve(value);
+			}, function(reason){
+				source.reject(reason);
+			});
+		}
+		if($.isFunction(source.promise)){
+			// `source` is a deferred, i.e. ajax request
+			_assert(!node.isLoading(), "recursive load");
+			// node._isLoading = true;
+			tree.nodeSetStatus(ctx, "loading");
+
+			source.done(function (children) {
+				tree.nodeSetStatus(ctx, "ok");
+			}).fail(function(error){
+				var ctxErr;
+				if (error.node && error.error && error.message) {
+					// error is already a context object
+					ctxErr = error;
+				} else {
+					ctxErr = tree._makeHookContext(node, null, {
+						error: error, // it can be jqXHR or any custom error
+						args: Array.prototype.slice.call(arguments),
+						message: error ? (error.message || error.toString()) : ""
+					});
+				}
+				if( tree._triggerNodeEvent("loadError", ctxErr, null) !== false ) {
+					tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details);
+				}
+			});
+		}
+		// $.when(source) resolves also for non-deferreds
+		return $.when(source).done(function(children){
+			var metaData;
+
+			if( $.isPlainObject(children) ){
+				// We got {foo: 'abc', children: [...]}
+				// Copy extra properties to tree.data.foo
+				_assert(node.isRootNode(), "source may only be an object for root nodes (expecting an array of child objects otherwise)");
+				_assert($.isArray(children.children), "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')");
+				metaData = children;
+				children = children.children;
+				delete metaData.children;
+				$.extend(tree.data, metaData);
+			}
+			_assert($.isArray(children), "expected array of children");
+			node._setChildren(children);
+			// trigger fancytreeloadchildren
+			tree._triggerNodeEvent("loadChildren", node);
+		// }).always(function(){
+		// 	node._isLoading = false;
+		});
+	},
+	/** [Not Implemented]  */
+	nodeLoadKeyPath: function(ctx, keyPathList) {
+		// TODO: implement and improve
+		// http://code.google.com/p/dynatree/issues/detail?id=222
+	},
+	/**
+	 * Remove a single direct child of ctx.node.
+	 * @param {EventData} ctx
+	 * @param {FancytreeNode} childNode dircect child of ctx.node
+	 */
+	nodeRemoveChild: function(ctx, childNode) {
+		var idx,
+			node = ctx.node,
+			opts = ctx.options,
+			subCtx = $.extend({}, ctx, {node: childNode}),
+			children = node.children;
+
+		// FT.debug("nodeRemoveChild()", node.toString(), childNode.toString());
+
+		if( children.length === 1 ) {
+			_assert(childNode === children[0], "invalid single child");
+			return this.nodeRemoveChildren(ctx);
+		}
+		if( this.activeNode && (childNode === this.activeNode || this.activeNode.isDescendantOf(childNode))){
+			this.activeNode.setActive(false); // TODO: don't fire events
+		}
+		if( this.focusNode && (childNode === this.focusNode || this.focusNode.isDescendantOf(childNode))){
+			this.focusNode = null;
+		}
+		// TODO: persist must take care to clear select and expand cookies
+		this.nodeRemoveMarkup(subCtx);
+		this.nodeRemoveChildren(subCtx);
+		idx = $.inArray(childNode, children);
+		_assert(idx >= 0, "invalid child");
+		// Unlink to support GC
+		childNode.visit(function(n){
+			n.parent = null;
+		}, true);
+		this._callHook("treeRegisterNode", this, false, childNode);
+		if ( opts.removeNode ){
+			opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx);
+		}
+		// remove from child list
+		children.splice(idx, 1);
+	},
+	/**Remove HTML markup for all descendents of ctx.node.
+	 * @param {EventData} ctx
+	 */
+	nodeRemoveChildMarkup: function(ctx) {
+		var node = ctx.node;
+
+		// FT.debug("nodeRemoveChildMarkup()", node.toString());
+		// TODO: Unlink attr.ftnode to support GC
+		if(node.ul){
+			if( node.isRootNode() ) {
+				$(node.ul).empty();
+			} else {
+				$(node.ul).remove();
+				node.ul = null;
+			}
+			node.visit(function(n){
+				n.li = n.ul = null;
+			});
+		}
+	},
+	/**Remove all descendants of ctx.node.
+	* @param {EventData} ctx
+	*/
+	nodeRemoveChildren: function(ctx) {
+		var subCtx,
+			tree = ctx.tree,
+			node = ctx.node,
+			children = node.children,
+			opts = ctx.options;
+
+		// FT.debug("nodeRemoveChildren()", node.toString());
+		if(!children){
+			return;
+		}
+		if( this.activeNode && this.activeNode.isDescendantOf(node)){
+			this.activeNode.setActive(false); // TODO: don't fire events
+		}
+		if( this.focusNode && this.focusNode.isDescendantOf(node)){
+			this.focusNode = null;
+		}
+		// TODO: persist must take care to clear select and expand cookies
+		this.nodeRemoveChildMarkup(ctx);
+		// Unlink children to support GC
+		// TODO: also delete this.children (not possible using visit())
+		subCtx = $.extend({}, ctx);
+		node.visit(function(n){
+			n.parent = null;
+			tree._callHook("treeRegisterNode", tree, false, n);
+			if ( opts.removeNode ){
+				subCtx.node = n;
+				opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx);
+			}
+		});
+		if( node.lazy ){
+			// 'undefined' would be interpreted as 'not yet loaded' for lazy nodes
+			node.children = [];
+		} else{
+			node.children = null;
+		}
+		if( !node.isRootNode() ) {
+			node.expanded = false;  // #449, #459
+		}
+		this.nodeRenderStatus(ctx);
+	},
+	/**Remove HTML markup for ctx.node and all its descendents.
+	 * @param {EventData} ctx
+	 */
+	nodeRemoveMarkup: function(ctx) {
+		var node = ctx.node;
+		// FT.debug("nodeRemoveMarkup()", node.toString());
+		// TODO: Unlink attr.ftnode to support GC
+		if(node.li){
+			$(node.li).remove();
+			node.li = null;
+		}
+		this.nodeRemoveChildMarkup(ctx);
+	},
+	/**
+	 * Create `&lt;li>&lt;span>..&lt;/span> .. &lt;/li>` tags for this node.
+	 *
+	 * This method takes care that all HTML markup is created that is required
+	 * to display this node in it's current state.
+	 *
+	 * Call this method to create new nodes, or after the strucuture
+	 * was changed (e.g. after moving this node or adding/removing children)
+	 * nodeRenderTitle() and nodeRenderStatus() are implied.
+	 *
+	 * Note: if a node was created/removed, nodeRender() must be called for the
+	 *       parent.
+	 * &lt;code>
+	 * &lt;li id='KEY' ftnode=NODE>
+	 *     &lt;span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>
+	 *         &lt;span class="fancytree-expander">&lt;/span>
+	 *         &lt;span class="fancytree-checkbox">&lt;/span> // only present in checkbox mode
+	 *         &lt;span class="fancytree-icon">&lt;/span>
+	 *         &lt;a href="#" class="fancytree-title"> Node 1 &lt;/a>
+	 *     &lt;/span>
+	 *     &lt;ul> // only present if node has children
+	 *         &lt;li id='KEY' ftnode=NODE> child1 ... &lt;/li>
+	 *         &lt;li id='KEY' ftnode=NODE> child2 ... &lt;/li>
+	 *     &lt;/ul>
+	 * &lt;/li>
+	 * &lt;/code>
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [force=false] re-render, even if html markup was already created
+	 * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+	 * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later
+	 */
+	nodeRender: function(ctx, force, deep, collapsed, _recursive) {
+		/* This method must take care of all cases where the current data mode
+		 * (i.e. node hierarchy) does not match the current markup.
+		 *
+		 * - node was not yet rendered:
+		 *   create markup
+		 * - node was rendered: exit fast
+		 * - children have been added
+		 * - children have been removed
+		 */
+		var childLI, childNode1, childNode2, i, l, next, subCtx,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			aria = opts.aria,
+			firstTime = false,
+			parent = node.parent,
+			isRootNode = !parent,
+			children = node.children,
+			successorLi = null;
+		// FT.debug("nodeRender(" + !!force + ", " + !!deep + ")", node.toString());
+
+		if( ! isRootNode && ! parent.ul ) {
+			// Calling node.collapse on a deep, unrendered node
+			return;
+		}
+		_assert(isRootNode || parent.ul, "parent UL must exist");
+
+		// Render the node
+		if( !isRootNode ){
+			// Discard markup on force-mode, or if it is not linked to parent <ul>
+			if(node.li && (force || (node.li.parentNode !== node.parent.ul) ) ){
+				if( node.li.parentNode === node.parent.ul ){
+					// #486: store following node, so we can insert the new markup there later
+					successorLi = node.li.nextSibling;
+				}else{
+					// May happen, when a top-level node was dropped over another
+					this.debug("Unlinking " + node + " (must be child of " + node.parent + ")");
+				}
+//	            this.debug("nodeRemoveMarkup...");
+				this.nodeRemoveMarkup(ctx);
+			}
+			// Create <li><span /> </li>
+//			node.debug("render...");
+			if( !node.li ) {
+//	            node.debug("render... really");
+				firstTime = true;
+				node.li = document.createElement("li");
+				node.li.ftnode = node;
+				if(aria){
+					// TODO: why doesn't this work:
+//					node.li.role = "treeitem";
+//                    $(node.li).attr("role", "treeitem")
+//                    .attr("aria-labelledby", "ftal_" + node.key);
+				}
+				if( node.key && opts.generateIds ){
+					node.li.id = opts.idPrefix + node.key;
+				}
+				node.span = document.createElement("span");
+				node.span.className = "fancytree-node";
+				if(aria){
+					$(node.span).attr("aria-labelledby", "ftal_" + node.key);
+				}
+				node.li.appendChild(node.span);
+
+				// Create inner HTML for the <span> (expander, checkbox, icon, and title)
+				this.nodeRenderTitle(ctx);
+
+				// Allow tweaking and binding, after node was created for the first time
+				if ( opts.createNode ){
+					opts.createNode.call(tree, {type: "createNode"}, ctx);
+				}
+			}else{
+//				this.nodeRenderTitle(ctx);
+				this.nodeRenderStatus(ctx);
+			}
+			// Allow tweaking after node state was rendered
+			if ( opts.renderNode ){
+				opts.renderNode.call(tree, {type: "renderNode"}, ctx);
+			}
+		}
+
+		// Visit child nodes
+		if( children ){
+			if( isRootNode || node.expanded || deep === true ) {
+				// Create a UL to hold the children
+				if( !node.ul ){
+					node.ul = document.createElement("ul");
+					if((collapsed === true && !_recursive) || !node.expanded){
+						// hide top UL, so we can use an animation to show it later
+						node.ul.style.display = "none";
+					}
+					if(aria){
+						$(node.ul).attr("role", "group");
+					}
+					if ( node.li ) { // issue #67
+						node.li.appendChild(node.ul);
+					} else {
+						node.tree.$div.append(node.ul);
+					}
+				}
+				// Add child markup
+				for(i=0, l=children.length; i<l; i++) {
+					subCtx = $.extend({}, ctx, {node: children[i]});
+					this.nodeRender(subCtx, force, deep, false, true);
+				}
+				// Remove <li> if nodes have moved to another parent
+				childLI = node.ul.firstChild;
+				while( childLI ){
+					childNode2 = childLI.ftnode;
+					if( childNode2 && childNode2.parent !== node ) {
+						node.debug("_fixParent: remove missing " + childNode2, childLI);
+						next = childLI.nextSibling;
+						childLI.parentNode.removeChild(childLI);
+						childLI = next;
+					}else{
+						childLI = childLI.nextSibling;
+					}
+				}
+				// Make sure, that <li> order matches node.children order.
+				childLI = node.ul.firstChild;
+				for(i=0, l=children.length-1; i<l; i++) {
+					childNode1 = children[i];
+					childNode2 = childLI.ftnode;
+					if( childNode1 !== childNode2 ) {
+						// node.debug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
+						node.ul.insertBefore(childNode1.li, childNode2.li);
+					} else {
+						childLI = childLI.nextSibling;
+					}
+				}
+			}
+		}else{
+			// No children: remove markup if any
+			if( node.ul ){
+//				alert("remove child markup for " + node);
+				this.warn("remove child markup for " + node);
+				this.nodeRemoveChildMarkup(ctx);
+			}
+		}
+		if( !isRootNode ){
+			// Update element classes according to node state
+			// this.nodeRenderStatus(ctx);
+			// Finally add the whole structure to the DOM, so the browser can render
+			if( firstTime ){
+				// #486: successorLi is set, if we re-rendered (i.e. discarded)
+				// existing markup, which  we want to insert at the same position.
+				// (null is equivalent to append)
+//				parent.ul.appendChild(node.li);
+				parent.ul.insertBefore(node.li, successorLi);
+			}
+		}
+	},
+	/** Create HTML inside the node's outer &lt;span> (i.e. expander, checkbox,
+	 * icon, and title).
+	 *
+	 * nodeRenderStatus() is implied.
+	 * @param {EventData} ctx
+	 * @param {string} [title] optinal new title
+	 */
+	nodeRenderTitle: function(ctx, title) {
+		// set node connector images, links and text
+		var id, iconSpanClass, nodeTitle, role, tabindex, tooltip,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			aria = opts.aria,
+			level = node.getLevel(),
+			ares = [],
+			iconSrc = node.data.icon;
+
+		if(title !== undefined){
+			node.title = title;
+		}
+		if(!node.span){
+			// Silently bail out if node was not rendered yet, assuming
+			// node.render() will be called as the node becomes visible
+			return;
+		}
+		// connector (expanded, expandable or simple)
+		// TODO: optimize this if clause
+		if( level < opts.minExpandLevel ) {
+			if( !node.lazy ) {
+				node.expanded = true;
+			}
+			if(level > 1){
+				if(aria){
+					ares.push("<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>");
+				}else{
+					ares.push("<span class='fancytree-expander fancytree-expander-fixed''></span>");
+				}
+			}
+			// .. else (i.e. for root level) skip expander/connector alltogether
+		} else {
+			if(aria){
+				ares.push("<span role='button' class='fancytree-expander'></span>");
+			}else{
+				ares.push("<span class='fancytree-expander'></span>");
+			}
+		}
+		// Checkbox mode
+		if( opts.checkbox && node.hideCheckbox !== true && !node.isStatusNode() ) {
+			if(aria){
+				ares.push("<span role='checkbox' class='fancytree-checkbox'></span>");
+			}else{
+				ares.push("<span class='fancytree-checkbox'></span>");
+			}
+		}
+		// folder or doctype icon
+		role = aria ? " role='img'" : "";
+		if( iconSrc === true || (iconSrc !== false && opts.icons !== false) ) {
+			// opts.icons defines the default behavior, node.icon == true/false can override this
+			if ( iconSrc && typeof iconSrc === "string" ) {
+				// node.icon is an image url
+				iconSrc = (iconSrc.charAt(0) === "/") ? iconSrc : ((opts.imagePath || "") + iconSrc);
+				ares.push("<img src='" + iconSrc + "' class='fancytree-icon' alt='' />");
+			} else {
+				// See if node.iconclass or opts.iconClass() define a class name
+				iconSpanClass = (opts.iconClass && opts.iconClass.call(tree, {type: "iconClass"}, ctx)) || node.data.iconclass || null;
+				if( iconSpanClass ) {
+					ares.push("<span " + role + " class='fancytree-custom-icon " + iconSpanClass +  "'></span>");
+				} else {
+					ares.push("<span " + role + " class='fancytree-icon'></span>");
+				}
+			}
+		}
+
+		// node title
+		nodeTitle = "";
+		if ( opts.renderTitle ){
+			nodeTitle = opts.renderTitle.call(tree, {type: "renderTitle"}, ctx) || "";
+		}
+		if(!nodeTitle){
+			tooltip = node.tooltip ? " title='" + FT.escapeHtml(node.tooltip) + "'" : "";
+			id = aria ? " id='ftal_" + node.key + "'" : "";
+			role = aria ? " role='treeitem'" : "";
+			tabindex = opts.titlesTabbable ? " tabindex='0'" : "";
+
+			nodeTitle = "<span " + role + " class='fancytree-title'" + id + tooltip + tabindex + ">" + node.title + "</span>";
+		}
+		ares.push(nodeTitle);
+		// Note: this will trigger focusout, if node had the focus
+		//$(node.span).html(ares.join("")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly
+		node.span.innerHTML = ares.join("");
+		// Update CSS classes
+		this.nodeRenderStatus(ctx);
+	},
+	/** Update element classes according to node state.
+	 * @param {EventData} ctx
+	 */
+	nodeRenderStatus: function(ctx) {
+		// Set classes for current status
+		var node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+//			nodeContainer = node[tree.nodeContainerAttrName],
+			hasChildren = node.hasChildren(),
+			isLastSib = node.isLastSibling(),
+			aria = opts.aria,
+//            $ariaElem = aria ? $(node[tree.ariaPropName]) : null,
+			$ariaElem = $(node.span).find(".fancytree-title"),
+			cn = opts._classNames,
+			cnList = [],
+			statusElem = node[tree.statusClassPropName];
+
+		if( !statusElem ){
+			// if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)
+			return;
+		}
+		// Build a list of class names that we will add to the node <span>
+		cnList.push(cn.node);
+		if( tree.activeNode === node ){
+			cnList.push(cn.active);
+//			$(">span.fancytree-title", statusElem).attr("tabindex", "0");
+//			tree.$container.removeAttr("tabindex");
+		// }else{
+//			$(">span.fancytree-title", statusElem).removeAttr("tabindex");
+//			tree.$container.attr("tabindex", "0");
+		}
+		if( tree.focusNode === node ){
+			cnList.push(cn.focused);
+			if(aria){
+//              $(">span.fancytree-title", statusElem).attr("tabindex", "0");
+//                $(">span.fancytree-title", statusElem).attr("tabindex", "-1");
+				// TODO: is this the right element for this attribute?
+				$ariaElem
+					.attr("aria-activedescendant", true);
+//					.attr("tabindex", "-1");
+			}
+		}else if(aria){
+//			$(">span.fancytree-title", statusElem).attr("tabindex", "-1");
+			$ariaElem
+				.removeAttr("aria-activedescendant");
+//				.removeAttr("tabindex");
+		}
+		if( node.expanded ){
+			cnList.push(cn.expanded);
+			if(aria){
+				$ariaElem.attr("aria-expanded", true);
+			}
+		}else if(aria){
+			$ariaElem.removeAttr("aria-expanded");
+		}
+		if( node.folder ){
+			cnList.push(cn.folder);
+		}
+		if( hasChildren !== false ){
+			cnList.push(cn.hasChildren);
+		}
+		// TODO: required?
+		if( isLastSib ){
+			cnList.push(cn.lastsib);
+		}
+		if( node.lazy && node.children == null ){
+			cnList.push(cn.lazy);
+		}
+		if( node.partsel ){
+			cnList.push(cn.partsel);
+		}
+		if( node.unselectable ){
+			cnList.push(cn.unselectable);
+		}
+		if( node._isLoading ){
+			cnList.push(cn.loading);
+		}
+		if( node._error ){
+			cnList.push(cn.error);
+		}
+		if( node.selected ){
+			cnList.push(cn.selected);
+			if(aria){
+				$ariaElem.attr("aria-selected", true);
+			}
+		}else if(aria){
+			$ariaElem.attr("aria-selected", false);
+		}
+		if( node.extraClasses ){
+			cnList.push(node.extraClasses);
+		}
+		// IE6 doesn't correctly evaluate multiple class names,
+		// so we create combined class names that can be used in the CSS
+		if( hasChildren === false ){
+			cnList.push(cn.combinedExpanderPrefix + "n" +
+					(isLastSib ? "l" : "")
+					);
+		}else{
+			cnList.push(cn.combinedExpanderPrefix +
+					(node.expanded ? "e" : "c") +
+					(node.lazy && node.children == null ? "d" : "") +
+					(isLastSib ? "l" : "")
+					);
+		}
+		cnList.push(cn.combinedIconPrefix +
+				(node.expanded ? "e" : "c") +
+				(node.folder ? "f" : "")
+				);
+//        node.span.className = cnList.join(" ");
+		statusElem.className = cnList.join(" ");
+
+		// TODO: we should not set this in the <span> tag also, if we set it here:
+		// Maybe most (all) of the classes should be set in LI instead of SPAN?
+		if(node.li){
+			node.li.className = isLastSib ? cn.lastsib : "";
+		}
+	},
+	/** Activate node.
+	 * flag defaults to true.
+	 * If flag is true, the node is activated (must be a synchronous operation)
+	 * If flag is false, the node is deactivated (must be a synchronous operation)
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+	 * @returns {$.Promise}
+	 */
+	nodeSetActive: function(ctx, flag, callOpts) {
+		// Handle user click / [space] / [enter], according to clickFolderMode.
+		callOpts = callOpts || {};
+		var subCtx,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			noEvents = (callOpts.noEvents === true),
+			noFocus = (callOpts.noFocus === true),
+			isActive = (node === tree.activeNode);
+
+		// flag defaults to true
+		flag = (flag !== false);
+		// node.debug("nodeSetActive", flag);
+
+		if(isActive === flag){
+			// Nothing to do
+			return _getResolvedPromise(node);
+		}else if(flag && !noEvents && this._triggerNodeEvent("beforeActivate", node, ctx.originalEvent) === false ){
+			// Callback returned false
+			return _getRejectedPromise(node, ["rejected"]);
+		}
+		if(flag){
+			if(tree.activeNode){
+				_assert(tree.activeNode !== node, "node was active (inconsistency)");
+				subCtx = $.extend({}, ctx, {node: tree.activeNode});
+				tree.nodeSetActive(subCtx, false);
+				_assert(tree.activeNode === null, "deactivate was out of sync?");
+			}
+			if(opts.activeVisible){
+				// tree.nodeMakeVisible(ctx);
+				node.makeVisible({scrollIntoView: false}); // nodeSetFocus will scroll
+			}
+			tree.activeNode = node;
+			tree.nodeRenderStatus(ctx);
+			if( !noFocus ) {
+				tree.nodeSetFocus(ctx);
+			}
+			if( !noEvents ) {
+				tree._triggerNodeEvent("activate", node, ctx.originalEvent);
+			}
+		}else{
+			_assert(tree.activeNode === node, "node was not active (inconsistency)");
+			tree.activeNode = null;
+			this.nodeRenderStatus(ctx);
+			if( !noEvents ) {
+				ctx.tree._triggerNodeEvent("deactivate", node, ctx.originalEvent);
+			}
+		}
+		return _getResolvedPromise(node);
+	},
+	/** Expand or collapse node, return Deferred.promise.
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+	 * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)
+	 *     data was retrieved, rendered, and the expand animation finshed.
+	 */
+	nodeSetExpanded: function(ctx, flag, callOpts) {
+		callOpts = callOpts || {};
+		var _afterLoad, dfd, i, l, parents, prevAC,
+			node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options,
+			noAnimation = (callOpts.noAnimation === true),
+			noEvents = (callOpts.noEvents === true);
+
+		// flag defaults to true
+		flag = (flag !== false);
+
+		// node.debug("nodeSetExpanded(" + flag + ")");
+
+		if((node.expanded && flag) || (!node.expanded && !flag)){
+			// Nothing to do
+			// node.debug("nodeSetExpanded(" + flag + "): nothing to do");
+			return _getResolvedPromise(node);
+		}else if(flag && !node.lazy && !node.hasChildren() ){
+			// Prevent expanding of empty nodes
+			// return _getRejectedPromise(node, ["empty"]);
+			return _getResolvedPromise(node);
+		}else if( !flag && node.getLevel() < opts.minExpandLevel ) {
+			// Prevent collapsing locked levels
+			return _getRejectedPromise(node, ["locked"]);
+		}else if ( !noEvents && this._triggerNodeEvent("beforeExpand", node, ctx.originalEvent) === false ){
+			// Callback returned false
+			return _getRejectedPromise(node, ["rejected"]);
+		}
+		// If this node inside a collpased node, no animation and scrolling is needed
+		if( !noAnimation && !node.isVisible() ) {
+			noAnimation = callOpts.noAnimation = true;
+		}
+
+		dfd = new $.Deferred();
+
+		// Auto-collapse mode: collapse all siblings
+		if( flag && !node.expanded && opts.autoCollapse ) {
+			parents = node.getParentList(false, true);
+			prevAC = opts.autoCollapse;
+			try{
+				opts.autoCollapse = false;
+				for(i=0, l=parents.length; i<l; i++){
+					// TODO: should return promise?
+					this._callHook("nodeCollapseSiblings", parents[i], callOpts);
+				}
+			}finally{
+				opts.autoCollapse = prevAC;
+			}
+		}
+		// Trigger expand/collapse after expanding
+		dfd.done(function(){
+			var	lastChild = node.getLastChild();
+			if( flag && opts.autoScroll && !noAnimation && lastChild ) {
+				// Scroll down to last child, but keep current node visible
+				lastChild.scrollIntoView(true, {topNode: node}).always(function(){
+					if( !noEvents ) {
+						ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+					}
+				});
+			} else {
+				if( !noEvents ) {
+					ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+				}
+			}
+		});
+		// vvv Code below is executed after loading finished:
+		_afterLoad = function(callback){
+			var isVisible, isExpanded,
+				effect = opts.toggleEffect;
+
+			node.expanded = flag;
+			// Create required markup, but make sure the top UL is hidden, so we
+			// can animate later
+			tree._callHook("nodeRender", ctx, false, false, true);
+
+			// If the currently active node is now hidden, deactivate it
+			// if( opts.activeVisible && this.activeNode && ! this.activeNode.isVisible() ) {
+			//     this.activeNode.deactivate();
+			// }
+
+			// Expanding a lazy node: set 'loading...' and call callback
+			// if( bExpand && this.data.isLazy && this.childList === null && !this._isLoading ) {
+			//     this._loadContent();
+			//     return;
+			// }
+			// Hide children, if node is collapsed
+			if( node.ul ) {
+				isVisible = (node.ul.style.display !== "none");
+				isExpanded = !!node.expanded;
+				if ( isVisible === isExpanded ) {
+					node.warn("nodeSetExpanded: UL.style.display already set");
+
+				} else if ( !effect || noAnimation ) {
+					node.ul.style.display = ( node.expanded || !parent ) ? "" : "none";
+
+				} else {
+					// The UI toggle() effect works with the ext-wide extension,
+					// while jQuery.animate() has problems when the title span
+					// has positon: absolute
+
+					// duration = opts.fx.duration || 200;
+					// easing = opts.fx.easing;
+					// $(node.ul).animate(opts.fx, duration, easing, function(){
+
+					// node.debug("nodeSetExpanded: animate start...");
+					$(node.ul).toggle(effect.effect, effect.options, effect.duration, function(){
+						// node.debug("nodeSetExpanded: animate done");
+						callback();
+					});
+					return;
+				}
+			}
+			callback();
+		};
+		// ^^^ Code above is executed after loading finshed.
+
+		// Load lazy nodes, if any. Then continue with _afterLoad()
+		if(flag && node.lazy && node.hasChildren() === undefined){
+			// node.debug("nodeSetExpanded: load start...");
+			node.load().done(function(){
+				// node.debug("nodeSetExpanded: load done");
+				if(dfd.notifyWith){ // requires jQuery 1.6+
+					dfd.notifyWith(node, ["loaded"]);
+				}
+				_afterLoad(function () { dfd.resolveWith(node); });
+			}).fail(function(errMsg){
+				_afterLoad(function () { dfd.rejectWith(node, ["load failed (" + errMsg + ")"]); });
+			});
+/*
+			var source = tree._triggerNodeEvent("lazyLoad", node, ctx.originalEvent);
+			_assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+			node.debug("nodeSetExpanded: load start...");
+			this._callHook("nodeLoadChildren", ctx, source).done(function(){
+				node.debug("nodeSetExpanded: load done");
+				if(dfd.notifyWith){ // requires jQuery 1.6+
+					dfd.notifyWith(node, ["loaded"]);
+				}
+				_afterLoad.call(tree);
+			}).fail(function(errMsg){
+				dfd.rejectWith(node, ["load failed (" + errMsg + ")"]);
+			});
+*/
+		}else{
+			_afterLoad(function () { dfd.resolveWith(node); });
+		}
+		// node.debug("nodeSetExpanded: returns");
+		return dfd.promise();
+	},
+	/** Focus or blur this node.
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	nodeSetFocus: function(ctx, flag) {
+		// ctx.node.debug("nodeSetFocus(" + flag + ")");
+		var ctx2,
+			tree = ctx.tree,
+			node = ctx.node;
+
+		flag = (flag !== false);
+
+		// Blur previous node if any
+		if(tree.focusNode){
+			if(tree.focusNode === node && flag){
+				// node.debug("nodeSetFocus(" + flag + "): nothing to do");
+				return;
+			}
+			ctx2 = $.extend({}, ctx, {node: tree.focusNode});
+			tree.focusNode = null;
+			this._triggerNodeEvent("blur", ctx2);
+			this._callHook("nodeRenderStatus", ctx2);
+		}
+		// Set focus to container and node
+		if(flag){
+			if( !this.hasFocus() ){
+				node.debug("nodeSetFocus: forcing container focus");
+				this._callHook("treeSetFocus", ctx, true, {calledByNode: true});
+			}
+			node.makeVisible({scrollIntoView: false});
+			tree.focusNode = node;
+//			node.debug("FOCUS...");
+//			$(node.span).find(".fancytree-title").focus();
+			this._triggerNodeEvent("focus", ctx);
+//          if(ctx.options.autoActivate){
+//              tree.nodeSetActive(ctx, true);
+//          }
+			if(ctx.options.autoScroll){
+				node.scrollIntoView();
+			}
+			this._callHook("nodeRenderStatus", ctx);
+		}
+	},
+	/** (De)Select node, return new status (sync).
+	 *
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	nodeSetSelected: function(ctx, flag) {
+		var node = ctx.node,
+			tree = ctx.tree,
+			opts = ctx.options;
+		// flag defaults to true
+		flag = (flag !== false);
+
+		node.debug("nodeSetSelected(" + flag + ")", ctx);
+		if( node.unselectable){
+			return;
+		}
+		// TODO: !!node.expanded is nicer, but doesn't pass jshint
+		// https://github.com/jshint/jshint/issues/455
+//        if( !!node.expanded === !!flag){
+		if((node.selected && flag) || (!node.selected && !flag)){
+			return !!node.selected;
+		}else if ( this._triggerNodeEvent("beforeSelect", node, ctx.originalEvent) === false ){
+			return !!node.selected;
+		}
+		if(flag && opts.selectMode === 1){
+			// single selection mode
+			if(tree.lastSelectedNode){
+				tree.lastSelectedNode.setSelected(false);
+			}
+		}else if(opts.selectMode === 3){
+			// multi.hier selection mode
+			node.selected = flag;
+//			this._fixSelectionState(node);
+			node.fixSelection3AfterClick();
+		}
+		node.selected = flag;
+		this.nodeRenderStatus(ctx);
+		tree.lastSelectedNode = flag ? node : null;
+		tree._triggerNodeEvent("select", ctx);
+	},
+	/** Show node status (ok, loading, error) using styles and a dummy child node.
+	 *
+	 * @param {EventData} ctx
+	 * @param status
+	 * @param message
+	 * @param details
+	 * @since 2.3
+	 */
+	nodeSetStatus: function(ctx, status, message, details) {
+		var node = ctx.node,
+			tree = ctx.tree;
+			// cn = ctx.options._classNames;
+
+		function _clearStatusNode() {
+			// Remove dedicated dummy node, if any
+			var firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				try{
+					// I've seen exceptions here with loadKeyPath...
+					if(node.ul){
+						node.ul.removeChild(firstChild.li);
+						firstChild.li = null; // avoid leaks (DT issue 215)
+					}
+				}catch(e){}
+				if( node.children.length === 1 ){
+					node.children = [];
+				}else{
+					node.children.shift();
+				}
+			}
+		}
+		function _setStatusNode(data, type) {
+			// Create/modify the dedicated dummy node for 'loading...' or
+			// 'error!' status. (only called for direct child of the invisible
+			// system root)
+			var firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				$.extend(firstChild, data);
+				// tree._callHook("nodeRender", firstChild);
+				tree._callHook("nodeRenderTitle", firstChild);
+			} else {
+				data.key = "_statusNode";
+				node._setChildren([data]);
+				node.children[0].statusNodeType = type;
+				tree.render();
+			}
+			return node.children[0];
+		}
+
+		switch( status ){
+		case "ok":
+			_clearStatusNode();
+			// $(node.span).removeClass(cn.loading).removeClass(cn.error);
+			node._isLoading = false;
+			node._error = null;
+			node.renderStatus();
+			break;
+		case "loading":
+			// $(node.span).removeClass(cn.error).addClass(cn.loading);
+			if( !node.parent ) {
+				_setStatusNode({
+					title: tree.options.strings.loading + (message ? " (" + message + ") " : ""),
+					tooltip: details,
+					extraClasses: "fancytree-statusnode-wait"
+				}, status);
+			}
+			node._isLoading = true;
+			node._error = null;
+			node.renderStatus();
+			break;
+		case "error":
+			// $(node.span).removeClass(cn.loading).addClass(cn.error);
+			_setStatusNode({
+				title: tree.options.strings.loadError + (message ? " (" + message + ") " : ""),
+				tooltip: details,
+				extraClasses: "fancytree-statusnode-error"
+			}, status);
+			node._isLoading = false;
+			node._error = { message: message, details: details };
+			node.renderStatus();
+			break;
+		default:
+			$.error("invalid node status " + status);
+		}
+	},
+	/**
+	 *
+	 * @param {EventData} ctx
+	 */
+	nodeToggleExpanded: function(ctx) {
+		return this.nodeSetExpanded(ctx, !ctx.node.expanded);
+	},
+	/**
+	 * @param {EventData} ctx
+	 */
+	nodeToggleSelected: function(ctx) {
+		return this.nodeSetSelected(ctx, !ctx.node.selected);
+	},
+	/** Remove all nodes.
+	 * @param {EventData} ctx
+	 */
+	treeClear: function(ctx) {
+		var tree = ctx.tree;
+		tree.activeNode = null;
+		tree.focusNode = null;
+		tree.$div.find(">ul.fancytree-container").empty();
+		// TODO: call destructors and remove reference loops
+		tree.rootNode.children = null;
+	},
+	/** Widget was created (called only once, even it re-initialized).
+	 * @param {EventData} ctx
+	 */
+	treeCreate: function(ctx) {
+	},
+	/** Widget was destroyed.
+	 * @param {EventData} ctx
+	 */
+	treeDestroy: function(ctx) {
+		this.$div.find(">ul.fancytree-container").remove();
+		this.$source && this.$source.removeClass("ui-helper-hidden");
+	},
+	/** Widget was (re-)initialized.
+	 * @param {EventData} ctx
+	 */
+	treeInit: function(ctx) {
+		//this.debug("Fancytree.treeInit()");
+		this.treeLoad(ctx);
+	},
+	/** Parse Fancytree from source, as configured in the options.
+	 * @param {EventData} ctx
+	 * @param {object} [source] optional new source (use last data otherwise)
+	 */
+	treeLoad: function(ctx, source) {
+		var type, $ul,
+			tree = ctx.tree,
+			$container = ctx.widget.element,
+			dfd,
+			// calling context for root node
+			rootCtx = $.extend({}, ctx, {node: this.rootNode});
+
+		if(tree.rootNode.children){
+			this.treeClear(ctx);
+		}
+		source = source || this.options.source;
+
+		if(!source){
+			type = $container.data("type") || "html";
+			switch(type){
+			case "html":
+				$ul = $container.find(">ul:first");
+				$ul.addClass("ui-fancytree-source ui-helper-hidden");
+				source = $.ui.fancytree.parseHtml($ul);
+				// allow to init tree.data.foo from <ul data-foo=''>
+				this.data = $.extend(this.data, _getElementDataAsDict($ul));
+				break;
+			case "json":
+	//            $().addClass("ui-helper-hidden");
+				source = $.parseJSON($container.text());
+				if(source.children){
+					if(source.title){tree.title = source.title;}
+					source = source.children;
+				}
+				break;
+			default:
+				$.error("Invalid data-type: " + type);
+			}
+		}else if(typeof source === "string"){
+			// TODO: source is an element ID
+			$.error("Not implemented");
+		}
+
+		// Trigger fancytreeinit after nodes have been loaded
+		dfd = this.nodeLoadChildren(rootCtx, source).done(function(){
+			tree.render();
+			if( ctx.options.selectMode === 3 ){
+				tree.rootNode.fixSelection3FromEndNodes();
+			}
+			if( tree.activeNode && tree.options.activeVisible ) {
+				tree.activeNode.makeVisible();
+			}
+			tree._triggerTreeEvent("init", null, { status: true });
+		}).fail(function(){
+			tree.render();
+			tree._triggerTreeEvent("init", null, { status: false });
+		});
+		return dfd;
+	},
+	/** Node was inserted into or removed from the tree.
+	 * @param {EventData} ctx
+	 * @param {boolean} add
+	 * @param {FancytreeNode} node
+	 */
+	treeRegisterNode: function(ctx, add, node) {
+	},
+	/** Widget got focus.
+	 * @param {EventData} ctx
+	 * @param {boolean} [flag=true]
+	 */
+	treeSetFocus: function(ctx, flag, callOpts) {
+		flag = (flag !== false);
+
+		// this.debug("treeSetFocus(" + flag + "), callOpts: " + callOpts, this.hasFocus());
+		// this.debug("    focusNode: " + this.focusNode);
+		// this.debug("    activeNode: " + this.activeNode);
+		if( flag !== this.hasFocus() ){
+			this._hasFocus = flag;
+			if( !flag && this.focusNode ) {
+				// Node also looses focus if widget blurs
+				this.focusNode.setFocus(false);
+			}
+			this.$container.toggleClass("fancytree-treefocus", flag);
+			this._triggerTreeEvent(flag ? "focusTree" : "blurTree");
+		}
+	}
+});
+
+
+/* ******************************************************************************
+ * jQuery UI widget boilerplate
+ */
+
+/**
+ * The plugin (derrived from <a href=" http://api.jqueryui.com/jQuery.widget/">jQuery.Widget</a>).<br>
+ * This constructor is not called directly. Use `$(selector).fancytree({})`
+ * to initialize the plugin instead.<br>
+ * <pre class="sh_javascript sunlight-highlight-javascript">// Access widget methods and members:
+ * var tree = $("#tree").fancytree("getTree");
+ * var node = $("#tree").fancytree("getActiveNode", "1234");
+ * </pre>
+ *
+ * @mixin Fancytree_Widget
+ */
+
+$.widget("ui.fancytree",
+	/** @lends Fancytree_Widget# */
+	{
+	/**These options will be used as defaults
+	 * @type {FancytreeOptions}
+	 */
+	options:
+	{
+		activeVisible: true,
+		ajax: {
+			type: "GET",
+			cache: false, // false: Append random '_' argument to the request url to prevent caching.
+//          timeout: 0, // >0: Make sure we get an ajax error if server is unreachable
+			dataType: "json" // Expect json format and pass json object to callbacks.
+		},  //
+		aria: false, // TODO: default to true
+		autoActivate: true,
+		autoCollapse: false,
+//      autoFocus: false,
+		autoScroll: false,
+		checkbox: false,
+		/**defines click behavior*/
+		clickFolderMode: 4,
+		debugLevel: null, // 0..2 (null: use global setting $.ui.fancytree.debugInfo)
+		disabled: false, // TODO: required anymore?
+		enableAspx: true, // TODO: document
+		extensions: [],
+		// fx: { height: "toggle", duration: 200 },
+		// toggleEffect: { effect: "drop", options: {direction: "left"}, duration: 200 },
+		// toggleEffect: { effect: "slide", options: {direction: "up"}, duration: 200 },
+		toggleEffect: { effect: "blind", options: {direction: "vertical", scale: "box"}, duration: 200 },
+		generateIds: false,
+		icons: true,
+		idPrefix: "ft_",
+		focusOnSelect: false,
+		keyboard: true,
+		keyPathSeparator: "/",
+		minExpandLevel: 1,
+		quicksearch: false,
+		scrollOfs: {top: 0, bottom: 0},
+		scrollParent: null,
+		selectMode: 2,
+		strings: {
+			loading: "Loading&#8230;",
+			loadError: "Load error!"
+		},
+		tabbable: true,
+		titlesTabbable: false,
+		_classNames: {
+			node: "fancytree-node",
+			folder: "fancytree-folder",
+			combinedExpanderPrefix: "fancytree-exp-",
+			combinedIconPrefix: "fancytree-ico-",
+			hasChildren: "fancytree-has-children",
+			active: "fancytree-active",
+			selected: "fancytree-selected",
+			expanded: "fancytree-expanded",
+			lazy: "fancytree-lazy",
+			focused: "fancytree-focused",
+			partsel: "fancytree-partsel",
+			unselectable: "fancytree-unselectable",
+			lastsib: "fancytree-lastsib",
+			loading: "fancytree-loading",
+			error: "fancytree-error"
+		},
+		// events
+		lazyLoad: null,
+		postProcess: null
+	},
+	/* Set up the widget, Called on first $().fancytree() */
+	_create: function() {
+		this.tree = new Fancytree(this);
+
+		this.$source = this.source || this.element.data("type") === "json" ? this.element
+			: this.element.find(">ul:first");
+		// Subclass Fancytree instance with all enabled extensions
+		var extension, extName, i,
+			extensions = this.options.extensions,
+			base = this.tree;
+
+		for(i=0; i<extensions.length; i++){
+			extName = extensions[i];
+			extension = $.ui.fancytree._extensions[extName];
+			if(!extension){
+				$.error("Could not apply extension '" + extName + "' (it is not registered, did you forget to include it?)");
+			}
+			// Add extension options as tree.options.EXTENSION
+//			_assert(!this.tree.options[extName], "Extension name must not exist as option name: " + extName);
+			this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);
+			// Add a namespace tree.ext.EXTENSION, to hold instance data
+			_assert(this.tree.ext[extName] === undefined, "Extension name must not exist as Fancytree.ext attribute: '" + extName + "'");
+//			this.tree[extName] = extension;
+			this.tree.ext[extName] = {};
+			// Subclass Fancytree methods using proxies.
+			_subclassObject(this.tree, base, extension, extName);
+			// current extension becomes base for the next extension
+			base = extension;
+		}
+		//
+		this.tree._callHook("treeCreate", this.tree);
+		// Note: 'fancytreecreate' event is fired by widget base class
+//        this.tree._triggerTreeEvent("create");
+	},
+
+	/* Called on every $().fancytree() */
+	_init: function() {
+		this.tree._callHook("treeInit", this.tree);
+		// TODO: currently we call bind after treeInit, because treeInit
+		// might change tree.$container.
+		// It would be better, to move ebent binding into hooks altogether
+		this._bind();
+	},
+
+	/* Use the _setOption method to respond to changes to options */
+	_setOption: function(key, value) {
+		var callDefault = true,
+			rerender = false;
+		switch( key ) {
+		case "aria":
+		case "checkbox":
+		case "icons":
+		case "minExpandLevel":
+		case "tabbable":
+//		case "nolink":
+			this.tree._callHook("treeCreate", this.tree);
+			rerender = true;
+			break;
+		case "source":
+			callDefault = false;
+			this.tree._callHook("treeLoad", this.tree, value);
+			break;
+		}
+		this.tree.debug("set option " + key + "=" + value + " <" + typeof(value) + ">");
+		if(callDefault){
+			// In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget
+			$.Widget.prototype._setOption.apply(this, arguments);
+			// TODO: In jQuery UI 1.9 and above, you use the _super method instead
+//          this._super( "_setOption", key, value );
+		}
+		if(rerender){
+			this.tree.render(true, false);  // force, not-deep
+		}
+	},
+
+	/** Use the destroy method to clean up any modifications your widget has made to the DOM */
+	destroy: function() {
+		this._unbind();
+		this.tree._callHook("treeDestroy", this.tree);
+		// In jQuery UI 1.8, you must invoke the destroy method from the base widget
+		$.Widget.prototype.destroy.call(this);
+		// TODO: delete tree and nodes to make garbage collect easier?
+		// TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method
+	},
+
+	// -------------------------------------------------------------------------
+
+	/* Remove all event handlers for our namespace */
+	_unbind: function() {
+		var ns = this.tree._ns;
+		this.element.unbind(ns);
+		this.tree.$container.unbind(ns);
+		$(document).unbind(ns);
+	},
+	/* Add mouse and kyboard handlers to the container */
+	_bind: function() {
+		var that = this,
+			opts = this.options,
+			tree = this.tree,
+			ns = tree._ns
+			// selstartEvent = ( $.support.selectstart ? "selectstart" : "mousedown" )
+			;
+
+		// Remove all previuous handlers for this tree
+		this._unbind();
+
+		//alert("keydown" + ns + "foc=" + tree.hasFocus() + tree.$container);
+		// tree.debug("bind events; container: ", tree.$container);
+		tree.$container.on("focusin" + ns + " focusout" + ns, function(event){
+			var node = FT.getNode(event),
+				flag = (event.type === "focusin");
+			// tree.debug("Tree container got event " + event.type, node, event);
+			// tree.treeOnFocusInOut.call(tree, event);
+			if(node){
+				// For example clicking into an <input> that is part of a node
+				tree._callHook("nodeSetFocus", node, flag);
+			}else{
+				tree._callHook("treeSetFocus", tree, flag);
+			}
+		}).on("selectstart" + ns, "span.fancytree-title", function(event){
+			// prevent mouse-drags to select text ranges
+			// tree.debug("<span title> got event " + event.type);
+			event.preventDefault();
+		}).on("keydown" + ns, function(event){
+			// TODO: also bind keyup and keypress
+			// tree.debug("got event " + event.type + ", hasFocus:" + tree.hasFocus());
+			// if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){
+			if(opts.disabled || opts.keyboard === false ){
+				return true;
+			}
+			var res,
+				node = tree.focusNode, // node may be null
+				ctx = tree._makeHookContext(node || tree, event),
+				prevPhase = tree.phase;
+
+			try {
+				tree.phase = "userEvent";
+				// If a 'fancytreekeydown' handler returns false, skip the default
+				// handling (implemented by tree.nodeKeydown()).
+				if(node){
+					res = tree._triggerNodeEvent("keydown", node, event);
+				}else{
+					res = tree._triggerTreeEvent("keydown", event);
+				}
+				if ( res === "preventNav" ){
+					res = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls
+				} else if ( res !== false ){
+					res = tree._callHook("nodeKeydown", ctx);
+				}
+				return res;
+			} finally {
+				tree.phase = prevPhase;
+			}
+		}).on("click" + ns + " dblclick" + ns, function(event){
+			// that.tree.debug("event(" + event + "): !");
+			if(opts.disabled){
+				return true;
+			}
+			var ctx,
+				et = FT.getEventTarget(event),
+				node = et.node,
+				tree = that.tree,
+				prevPhase = tree.phase;
+
+			// that.tree.debug("event(" + event.type + "): node: ", node);
+			if( !node ){
+				return true;  // Allow bubbling of other events
+			}
+			ctx = tree._makeHookContext(node, event);
+//			that.tree.debug("event(" + event.type + "): node: ", node);
+			try {
+				tree.phase = "userEvent";
+				switch(event.type) {
+				case "click":
+					ctx.targetType = et.type;
+					return ( tree._triggerNodeEvent("click", ctx, event) === false ) ? false : tree._callHook("nodeClick", ctx);
+				case "dblclick":
+					ctx.targetType = et.type;
+					return ( tree._triggerNodeEvent("dblclick", ctx, event) === false ) ? false : tree._callHook("nodeDblclick", ctx);
+				}
+//             } catch(e) {
+// //                var _ = null; // DT issue 117 // TODO
+//                 $.error(e);
+			} finally {
+				tree.phase = prevPhase;
+			}
+		});
+	},
+	/** Return the active node or null.
+	 * @returns {FancytreeNode}
+	 */
+	getActiveNode: function() {
+		return this.tree.activeNode;
+	},
+	/** Return the matching node or null.
+	 * @param {string} key
+	 * @returns {FancytreeNode}
+	 */
+	getNodeByKey: function(key) {
+		return this.tree.getNodeByKey(key);
+	},
+	/** Return the invisible system root node.
+	 * @returns {FancytreeNode}
+	 */
+	getRootNode: function() {
+		return this.tree.rootNode;
+	},
+	/** Return the current tree instance.
+	 * @returns {Fancytree}
+	 */
+	getTree: function() {
+		return this.tree;
+	}
+});
+
+// $.ui.fancytree was created by the widget factory. Create a local shortcut:
+FT = $.ui.fancytree;
+
+/**
+ * Static members in the `$.ui.fancytree` namespace.<br>
+ * <br>
+ * <pre class="sh_javascript sunlight-highlight-javascript">// Access static members:
+ * var node = $.ui.fancytree.getNode(element);
+ * alert($.ui.fancytree.version);
+ * </pre>
+ *
+ * @mixin Fancytree_Static
+ */
+$.extend($.ui.fancytree,
+	/** @lends Fancytree_Static# */
+	{
+	/** @type {string} */
+	version: "2.13.0",      // Set to semver by 'grunt release'
+	/** @type {string} */
+	buildType: "production", // Set to 'production' by 'grunt build'
+	/** @type {int} */
+	debugLevel: 1,            // Set to 1 by 'grunt build'
+							  // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
+
+	_nextId: 1,
+	_nextNodeKey: 1,
+	_extensions: {},
+	// focusTree: null,
+
+	/** Expose class object as $.ui.fancytree._FancytreeClass */
+	_FancytreeClass: Fancytree,
+	/** Expose class object as $.ui.fancytree._FancytreeNodeClass */
+	_FancytreeNodeClass: FancytreeNode,
+	/* Feature checks to provide backwards compatibility */
+	jquerySupports: {
+		// http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+		positionMyOfs: isVersionAtLeast($.ui.version, 1, 9)
+		},
+	/** Throw an error if condition fails (debug method).
+	 * @param {boolean} cond
+	 * @param {string} msg
+	 */
+	assert: function(cond, msg){
+		return _assert(cond, msg);
+	},
+	/** Return a function that executes *fn* at most every *timeout* ms.
+	 * @param {integer} timeout
+	 * @param {function} fn
+	 * @param {boolean} [invokeAsap=false]
+	 * @param {any} [ctx]
+	 */
+	debounce: function(timeout, fn, invokeAsap, ctx) {
+		var timer;
+		if(arguments.length === 3 && typeof invokeAsap !== "boolean") {
+			ctx = invokeAsap;
+			invokeAsap = false;
+		}
+		return function() {
+			var args = arguments;
+			ctx = ctx || this;
+			invokeAsap && !timer && fn.apply(ctx, args);
+			clearTimeout(timer);
+			timer = setTimeout(function() {
+				invokeAsap || fn.apply(ctx, args);
+				timer = null;
+			}, timeout);
+		};
+	},
+	/** Write message to console if debugLevel >= 2
+	 * @param {string} msg
+	 */
+	debug: function(msg){
+		/*jshint expr:true */
+		($.ui.fancytree.debugLevel >= 2) && consoleApply("log", arguments);
+	},
+	/** Write error message to console.
+	 * @param {string} msg
+	 */
+	error: function(msg){
+		consoleApply("error", arguments);
+	},
+	/** Convert &lt;, &gt;, &amp;, &quot;, &#39;, &#x2F; to the equivalent entities.
+	 *
+	 * @param {string} s
+	 * @returns {string}
+	 */
+	escapeHtml: function(s){
+		return ("" + s).replace(/[&<>"'\/]/g, function (s) {
+			return ENTITY_MAP[s];
+		});
+	},
+	/** Make jQuery.position() arguments backwards compatible, i.e. if
+	 * jQuery UI version <= 1.8, convert
+	 *   { my: "left+3 center", at: "left bottom", of: $target }
+	 * to
+	 *   { my: "left center", at: "left bottom", of: $target, offset: "3  0" }
+	 *
+	 * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+	 * and http://jsfiddle.net/mar10/6xtu9a4e/
+	 */
+	fixPositionOptions: function(opts) {
+		if( opts.offset || ("" + opts.my + opts.at ).indexOf("%") >= 0 ) {
+		   $.error("expected new position syntax (but '%' is not supported)");
+		}
+		if( ! $.ui.fancytree.jquerySupports.positionMyOfs ) {
+			var // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]
+				myParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.my),
+				atParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.at),
+				// convert to numbers
+				dx = (myParts[2] ? (+myParts[2]) : 0) + (atParts[2] ? (+atParts[2]) : 0),
+				dy = (myParts[4] ? (+myParts[4]) : 0) + (atParts[4] ? (+atParts[4]) : 0);
+
+			opts = $.extend({}, opts, { // make a copy and overwrite
+				my: myParts[1] + " " + myParts[3],
+				at: atParts[1] + " " + atParts[3]
+			});
+			if( dx || dy ) {
+				opts.offset = "" + dx + " " + dy;
+			}
+		}
+		return opts;
+	},
+	/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+	 *
+	 * @param {Event} event Mouse event, e.g. click, ...
+	 * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+	 */
+	getEventTargetType: function(event){
+		return this.getEventTarget(event).type;
+	},
+	/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+	 *
+	 * @param {Event} event Mouse event, e.g. click, ...
+	 * @returns {object} Return a {node: FancytreeNode, type: TYPE} object
+	 *     TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+	 */
+	getEventTarget: function(event){
+		var tcn = event && event.target ? event.target.className : "",
+			res = {node: this.getNode(event.target), type: undefined};
+		// We use a fast version of $(res.node).hasClass()
+		// See http://jsperf.com/test-for-classname/2
+		if( /\bfancytree-title\b/.test(tcn) ){
+			res.type = "title";
+		}else if( /\bfancytree-expander\b/.test(tcn) ){
+			res.type = (res.node.hasChildren() === false ? "prefix" : "expander");
+		}else if( /\bfancytree-checkbox\b/.test(tcn) || /\bfancytree-radio\b/.test(tcn) ){
+			res.type = "checkbox";
+		}else if( /\bfancytree-icon\b/.test(tcn) ){
+			res.type = "icon";
+		}else if( /\bfancytree-node\b/.test(tcn) ){
+			// Somewhere near the title
+			res.type = "title";
+		}else if( event && event.target && $(event.target).closest(".fancytree-title").length ) {
+			// #228: clicking an embedded element inside a title
+			res.type = "title";
+		}
+		return res;
+	},
+	/** Return a FancytreeNode instance from element, event, or jQuery object.
+	 *
+	 * @param {Element | jQueryObject | Event} el
+	 * @returns {FancytreeNode} matching node or null
+	 */
+	getNode: function(el){
+		if(el instanceof FancytreeNode){
+			return el; // el already was a FancytreeNode
+		}else if(el.selector !== undefined){
+			el = el[0]; // el was a jQuery object: use the DOM element
+		}else if(el.originalEvent !== undefined){
+			el = el.target; // el was an Event
+		}
+		while( el ) {
+			if(el.ftnode) {
+				return el.ftnode;
+			}
+			el = el.parentNode;
+		}
+		return null;
+	},
+	/** Return a Fancytree instance, from element, index, event, or jQueryObject.
+	 *
+	 * @param {Element | jQueryObject | Event | integer | string} [el]
+	 * @returns {Fancytree} matching tree or null
+	 * @example
+	 * $.ui.fancytree.getTree();   // Get first Fancytree instance on page
+	 * $.ui.fancytree.getTree(1);  // Get second Fancytree instance on page
+	 * $.ui.fancytree.getTree("#tree"); // Get tree for this matching element
+	 *
+	 * @since 2.13
+	 */
+	getTree: function(el){
+		var widget;
+
+		if( el instanceof Fancytree ) {
+			return el; // el already was a Fancytree
+		}
+		if( el === undefined ) {
+			el = 0;  // get first tree
+		}
+		if( typeof el === "number" ) {
+			el = $(".fancytree-container").eq(el); // el was an integer: return nth instance
+		} else if( typeof el === "string" ) {
+			el = $(el).eq(0); // el was a selector: use first match
+		} else if( el.selector !== undefined ) {
+			el = el.eq(0); // el was a jQuery object: use the first DOM element
+		} else if( el.originalEvent !== undefined ) {
+			el = $(el.target); // el was an Event
+		}
+		el = el.closest(":ui-fancytree");
+		widget = el.data("ui-fancytree") || el.data("fancytree"); // the latter is required by jQuery <= 1.8
+		return widget ? widget.tree : null;
+	},
+	/** Write message to console if debugLevel >= 1
+	 * @param {string} msg
+	 */
+	info: function(msg){
+		/*jshint expr:true */
+		($.ui.fancytree.debugLevel >= 1) && consoleApply("info", arguments);
+	},
+	/** Convert a keydown or mouse event to a canonical string like 'ctrl+a', 'ctrl+shift+f2', 'shift+leftdblclick'.
+	 * This is especially handy for switch-statements in event handlers.
+	 * @param {event}
+	 * @returns {string}
+	 */
+	eventToString: function(event) {
+		// Poor-man's hotkeys. See here for a complete implementation:
+		//   https://github.com/jeresig/jquery.hotkeys
+		var which = event.which,
+			et = event.type,
+			s = [];
+
+		if( event.altKey ) { s.push("alt"); }
+		if( event.ctrlKey ) { s.push("ctrl"); }
+		if( event.metaKey ) { s.push("meta"); }
+		if( event.shiftKey ) { s.push("shift"); }
+
+		if( et === "click" || et === "dblclick" ) {
+			s.push(MOUSE_BUTTONS[event.button] + et);
+		} else {
+			if( !IGNORE_KEYCODES[which] ) {
+				s.push( SPECIAL_KEYCODES[which] || String.fromCharCode(which).toLowerCase() );
+			}
+		}
+		return s.join("+");
+	},
+	/* @deprecated: use eventToString(event) instead.
+	 */
+	keyEventToString: function(event) {
+		this.warn("keyEventToString() is deprecated: use eventToString()");
+		return this.eventToString(event);
+	},
+	/**
+	 * Parse tree data from HTML <ul> markup
+	 *
+	 * @param {jQueryObject} $ul
+	 * @returns {NodeData[]}
+	 */
+	parseHtml: function($ul) {
+		// TODO: understand this:
+		/*jshint validthis:true */
+		var classes, className, extraClasses, i, iPos, l, tmp, tmp2,
+			$children = $ul.find(">li"),
+			children = [];
+
+		$children.each(function() {
+			var allData, lowerCaseAttr,
+				$li = $(this),
+				$liSpan = $li.find(">span:first", this),
+				$liA = $liSpan.length ? null : $li.find(">a:first"),
+				d = { tooltip: null, data: {} };
+
+			if( $liSpan.length ) {
+				d.title = $liSpan.html();
+
+			} else if( $liA && $liA.length ) {
+				// If a <li><a> tag is specified, use it literally and extract href/target.
+				d.title = $liA.html();
+				d.data.href = $liA.attr("href");
+				d.data.target = $liA.attr("target");
+				d.tooltip = $liA.attr("title");
+
+			} else {
+				// If only a <li> tag is specified, use the trimmed string up to
+				// the next child <ul> tag.
+				d.title = $li.html();
+				iPos = d.title.search(/<ul/i);
+				if( iPos >= 0 ){
+					d.title = d.title.substring(0, iPos);
+				}
+			}
+			d.title = $.trim(d.title);
+
+			// Make sure all fields exist
+			for(i=0, l=CLASS_ATTRS.length; i<l; i++){
+				d[CLASS_ATTRS[i]] = undefined;
+			}
+			// Initialize to `true`, if class is set and collect extraClasses
+			classes = this.className.split(" ");
+			extraClasses = [];
+			for(i=0, l=classes.length; i<l; i++){
+				className = classes[i];
+				if(CLASS_ATTR_MAP[className]){
+					d[className] = true;
+				}else{
+					extraClasses.push(className);
+				}
+			}
+			d.extraClasses = extraClasses.join(" ");
+
+			// Parse node options from ID, title and class attributes
+			tmp = $li.attr("title");
+			if( tmp ){
+				d.tooltip = tmp; // overrides <a title='...'>
+			}
+			tmp = $li.attr("id");
+			if( tmp ){
+				d.key = tmp;
+			}
+			// Add <li data-NAME='...'> as node.data.NAME
+			allData = _getElementDataAsDict($li);
+			if( allData && !$.isEmptyObject(allData) ) {
+				// #507: convert data-hidecheckbox (lower case) to hideCheckbox
+				for( lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP ) {
+					if( allData.hasOwnProperty(lowerCaseAttr) ) {
+						allData[NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]] = allData[lowerCaseAttr];
+						delete allData[lowerCaseAttr];
+					}
+				}
+				// #56: Allow to set special node.attributes from data-...
+				for(i=0, l=NODE_ATTRS.length; i<l; i++){
+					tmp = NODE_ATTRS[i];
+					tmp2 = allData[tmp];
+					if( tmp2 != null ) {
+						delete allData[tmp];
+						d[tmp] = tmp2;
+					}
+				}
+				// All other data-... goes to node.data...
+				$.extend(d.data, allData);
+			}
+			// Recursive reading of child nodes, if LI tag contains an UL tag
+			$ul = $li.find(">ul:first");
+			if( $ul.length ) {
+				d.children = $.ui.fancytree.parseHtml($ul);
+			}else{
+				d.children = d.lazy ? undefined : null;
+			}
+			children.push(d);
+//            FT.debug("parse ", d, children);
+		});
+		return children;
+	},
+	/** Add Fancytree extension definition to the list of globally available extensions.
+	 *
+	 * @param {object} definition
+	 */
+	registerExtension: function(definition){
+		_assert(definition.name != null, "extensions must have a `name` property.");
+		_assert(definition.version != null, "extensions must have a `version` property.");
+		$.ui.fancytree._extensions[definition.name] = definition;
+	},
+	/** Inverse of escapeHtml().
+	 *
+	 * @param {string} s
+	 * @returns {string}
+	 */
+	unescapeHtml: function(s){
+		var e = document.createElement("div");
+		e.innerHTML = s;
+		return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
+	},
+	/** Write warning message to console.
+	 * @param {string} msg
+	 */
+	warn: function(msg){
+		consoleApply("warn", arguments);
+	}
+});
+
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.menu.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.menu.js
new file mode 100644
index 00000000000..23c22ae3ccb
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.menu.js
@@ -0,0 +1,155 @@
+/*!
+ * jquery.fancytree.menu.js
+ *
+ * Enable jQuery UI Menu as context menu for tree nodes.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @see http://api.jqueryui.com/menu/
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+// prevent duplicate loading
+// if ( $.ui.fancytree && $.ui.fancytree.version ) {
+//     $.ui.fancytree.warn("Fancytree: duplicate include");
+//     return;
+// }
+
+$.ui.fancytree.registerExtension({
+	name: "menu",
+	version: "0.0.1",
+	// Default options for this extension.
+	options: {
+		enable: true,
+		selector: null,  //
+		position: {},    //
+		// Events:
+		create: $.noop,  //
+		beforeOpen: $.noop,    //
+		open: $.noop,    //
+		focus: $.noop,   //
+		select: $.noop,  //
+		close: $.noop    //
+	},
+	// Override virtual methods for this extension.
+	// `this`       : is this extension object
+	// `this._base` : the Fancytree instance
+	// `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
+	treeInit: function(ctx){
+		var opts = ctx.options,
+			tree = ctx.tree;
+
+		this._superApply(arguments);
+
+		// Prepare an object that will be passed with menu events
+		tree.ext.menu.data = {
+			tree: tree,
+			node: null,
+			$menu: null,
+			menuId: null
+		};
+
+//        tree.$container[0].oncontextmenu = function() {return false;};
+		// Replace the standard browser context menu with out own
+		tree.$container.delegate("span.fancytree-node", "contextmenu", function(event) {
+			var node = $.ui.fancytree.getNode(event),
+				ctx = {node: node, tree: node.tree, originalEvent: event, options: tree.options};
+			tree.ext.menu._openMenu(ctx);
+			return false;
+		});
+
+		// Use jquery.ui.menu
+		$(opts.menu.selector).menu({
+			create: function(event, ui){
+				tree.ext.menu.data.$menu = $(this).menu("widget");
+				var data = $.extend({}, tree.ext.menu.data);
+				opts.menu.create.call(tree, event, data);
+			},
+			focus: function(event, ui){
+				var data = $.extend({}, tree.ext.menu.data, {
+					menuItem: ui.item,
+					menuId: ui.item.find(">a").attr("href")
+				});
+				opts.menu.focus.call(tree, event, data);
+			},
+			select: function(event, ui){
+				var data = $.extend({}, tree.ext.menu.data, {
+					menuItem: ui.item,
+					menuId: ui.item.find(">a").attr("href")
+				});
+				if( opts.menu.select.call(tree, event, data) !== false){
+					tree.ext.menu._closeMenu(ctx);
+				}
+			}
+		}).hide();
+	},
+	treeDestroy: function(ctx){
+		this._superApply(arguments);
+	},
+	_openMenu: function(ctx){
+		var data,
+			tree = ctx.tree,
+			opts = ctx.options,
+			$menu = $(opts.menu.selector);
+
+		tree.ext.menu.data.node = ctx.node;
+		data = $.extend({}, tree.ext.menu.data);
+
+		if( opts.menu.beforeOpen.call(tree, ctx.originalEvent, data) === false){
+			return;
+		}
+
+		$(document).bind("keydown.fancytree", function(event){
+			if( event.which === $.ui.keyCode.ESCAPE ){
+				tree.ext.menu._closeMenu(ctx);
+			}
+		}).bind("mousedown.fancytree", function(event){
+			// Close menu when clicked outside menu
+			if( $(event.target).closest(".ui-menu-item").length === 0 ){
+				tree.ext.menu._closeMenu(ctx);
+			}
+		});
+//        $menu.position($.extend({my: "left top", at: "left bottom", of: event}, opts.menu.position));
+		$menu
+			.css("position", "absolute")
+			.show()
+			.position({my: "left top", at: "right top", of: ctx.originalEvent, collision: "fit"})
+			.focus();
+
+		opts.menu.open.call(tree, ctx.originalEvent, data);
+	},
+	_closeMenu: function(ctx){
+		var $menu,
+			tree = ctx.tree,
+			opts = ctx.options,
+			data = $.extend({}, tree.ext.menu.data);
+		if( opts.menu.close.call(tree, ctx.originalEvent, data) === false){
+			return;
+		}
+		$menu = $(opts.menu.selector);
+		$(document).unbind("keydown.fancytree, mousedown.fancytree");
+		$menu.hide();
+		tree.ext.menu.data.node = null;
+	}
+//	,
+//	nodeClick: function(ctx) {
+//		var event = ctx.originalEvent;
+//		if(event.which === 2 || (event.which === 1 && event.ctrlKey)){
+//			event.preventDefault();
+//			ctx.tree.ext.menu._openMenu(ctx);
+//			return false;
+//		}
+//		this._superApply(arguments);
+//	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.persist.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.persist.js
new file mode 100644
index 00000000000..783bb74c166
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.persist.js
@@ -0,0 +1,383 @@
+/*!
+ * jquery.fancytree.persist.js
+ *
+ * Persist tree status in cookiesRemove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @depends: js-cookie or jquery-cookie
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+/* global Cookies:false */
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+var cookieGetter, cookieRemover, cookieSetter,
+	_assert = $.ui.fancytree.assert,
+	ACTIVE = "active",
+	EXPANDED = "expanded",
+	FOCUS = "focus",
+	SELECTED = "selected";
+
+if( typeof Cookies === "function" ) {
+	// Assume https://github.com/js-cookie/js-cookie
+	cookieSetter = Cookies.set;
+	cookieGetter = Cookies.get;
+	cookieRemover = Cookies.remove;
+} else {
+	// Fall back to https://github.com/carhartl/jquery-cookie
+	cookieSetter = cookieGetter = $.cookie;
+	cookieRemover = $.removeCookie;
+}
+
+/* Recursively load lazy nodes
+ * @param {string} mode 'load', 'expand', false
+ */
+function _loadLazyNodes(tree, local, keyList, mode, dfd) {
+	var i, key, l, node,
+		foundOne = false,
+		deferredList = [],
+		missingKeyList = [];
+
+	keyList = keyList || [];
+	dfd = dfd || $.Deferred();
+
+	for( i=0, l=keyList.length; i<l; i++ ) {
+		key = keyList[i];
+		node = tree.getNodeByKey(key);
+		if( node ) {
+			if( mode && node.isUndefined() ) {
+				foundOne = true;
+				tree.debug("_loadLazyNodes: " + node + " is lazy: loading...");
+				if( mode === "expand" ) {
+					deferredList.push(node.setExpanded());
+				} else {
+					deferredList.push(node.load());
+				}
+			} else {
+				tree.debug("_loadLazyNodes: " + node + " already loaded.");
+				node.setExpanded();
+			}
+		} else {
+			missingKeyList.push(key);
+			tree.debug("_loadLazyNodes: " + node + " was not yet found.");
+		}
+	}
+
+	$.when.apply($, deferredList).always(function(){
+		// All lazy-expands have finished
+		if( foundOne && missingKeyList.length > 0 ) {
+			// If we read new nodes from server, try to resolve yet-missing keys
+			_loadLazyNodes(tree, local, missingKeyList, mode, dfd);
+		} else {
+			if( missingKeyList.length ) {
+				tree.warn("_loadLazyNodes: could not load those keys: ", missingKeyList);
+				for( i=0, l=missingKeyList.length; i<l; i++ ) {
+					key = keyList[i];
+					local._appendKey(EXPANDED, keyList[i], false);
+				}
+			}
+			dfd.resolve();
+		}
+	});
+	return dfd;
+}
+
+
+/**
+ * [ext-persist] Remove persistence cookies of the given type(s).
+ * Called like
+ *     $("#tree").fancytree("getTree").clearCookies("active expanded focus selected");
+ *
+ * @alias Fancytree#clearCookies
+ * @requires jquery.fancytree.persist.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.clearCookies = function(types){
+	var local = this.ext.persist,
+		prefix = local.cookiePrefix;
+
+	types = types || "active expanded focus selected";
+	if(types.indexOf(ACTIVE) >= 0){
+		local._data(prefix + ACTIVE, null);
+	}
+	if(types.indexOf(EXPANDED) >= 0){
+		local._data(prefix + EXPANDED, null);
+	}
+	if(types.indexOf(FOCUS) >= 0){
+		local._data(prefix + FOCUS, null);
+	}
+	if(types.indexOf(SELECTED) >= 0){
+		local._data(prefix + SELECTED, null);
+	}
+};
+
+
+/**
+ * [ext-persist] Return persistence information from cookies
+ *
+ * Called like
+ *     $("#tree").fancytree("getTree").getPersistData();
+ *
+ * @alias Fancytree#getPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.getPersistData = function(){
+	var local = this.ext.persist,
+		prefix = local.cookiePrefix,
+		delim = local.cookieDelimiter,
+		res = {};
+
+	res[ACTIVE] = local._data(prefix + ACTIVE);
+	res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim);
+	res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim);
+	res[FOCUS] = local._data(prefix + FOCUS);
+	return res;
+};
+
+
+/* *****************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "persist",
+	version: "0.3.0",
+	// Default options for this extension.
+	options: {
+		cookieDelimiter: "~",
+		cookiePrefix: undefined, // 'fancytree-<treeId>-' by default
+		cookie: {
+			raw: false,
+			expires: "",
+			path: "",
+			domain: "",
+			secure: false
+		},
+		expandLazy: false,     // true: recursively expand and load lazy nodes
+		fireActivate: true,    // false: suppress `activate` event after active node was restored
+		overrideSource: true,  // true: cookie takes precedence over `source` data attributes.
+		store: "auto",         // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore
+		types: "active expanded focus selected"
+	},
+
+	/* Generic read/write string data to cookie, sessionStorage or localStorage. */
+	_data: function(key, value){
+		var ls = this._local.localStorage; // null, sessionStorage, or localStorage
+
+		if( value === undefined ) {
+			return ls ? ls.getItem(key) : cookieGetter(key);
+		} else if ( value === null ) {
+			if( ls ) {
+				ls.removeItem(key);
+			} else {
+				cookieRemover(key);
+			}
+		} else {
+			if( ls ) {
+				ls.setItem(key, value);
+			} else {
+				cookieSetter(key, value, this.options.persist.cookie);
+			}
+		}
+	},
+
+	/* Append `key` to a cookie. */
+	_appendKey: function(type, key, flag){
+		key = "" + key; // #90
+		var local = this._local,
+			instOpts = this.options.persist,
+			delim = instOpts.cookieDelimiter,
+			cookieName = local.cookiePrefix + type,
+			data = local._data(cookieName),
+			keyList = data ? data.split(delim) : [],
+			idx = $.inArray(key, keyList);
+		// Remove, even if we add a key,  so the key is always the last entry
+		if(idx >= 0){
+			keyList.splice(idx, 1);
+		}
+		// Append key to cookie
+		if(flag){
+			keyList.push(key);
+		}
+		local._data(cookieName, keyList.join(delim));
+	},
+
+	treeInit: function(ctx){
+		var tree = ctx.tree,
+			opts = ctx.options,
+			local = this._local,
+			instOpts = this.options.persist;
+
+		// For 'auto' or 'cookie' mode, the cookie plugin must be available
+		_assert((instOpts.store !== "auto" && instOpts.store !== "cookie") || cookieGetter,
+			"Missing required plugin for 'persist' extension: js.cookie.js or jquery.cookie.js");
+
+		local.cookiePrefix = instOpts.cookiePrefix || ("fancytree-" + tree._id + "-");
+		local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
+		local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
+		local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
+		local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
+		if( instOpts.store === "cookie" || !window.localStorage ) {
+			local.localStorage = null;
+		} else {
+			local.localStorage = (instOpts.store === "local") ? window.localStorage : window.sessionStorage;
+		}
+
+		// Bind init-handler to apply cookie state
+		tree.$div.bind("fancytreeinit", function(event){
+			var cookie, dfd, i, keyList, node,
+				prevFocus = local._data(local.cookiePrefix + FOCUS), // record this before node.setActive() overrides it;
+				noEvents = instOpts.fireActivate === false;
+
+			// tree.debug("document.cookie:", document.cookie);
+
+			cookie = local._data(local.cookiePrefix + EXPANDED);
+			keyList = cookie && cookie.split(instOpts.cookieDelimiter);
+
+			if( local.storeExpanded ) {
+				// Recursively load nested lazy nodes if expandLazy is 'expand' or 'load'
+				// Also remove expand-cookies for unmatched nodes
+				dfd = _loadLazyNodes(tree, local, keyList, instOpts.expandLazy ? "expand" : false , null);
+			} else {
+				// nothing to do
+				dfd = new $.Deferred().resolve();
+			}
+
+			dfd.done(function(){
+				if(local.storeSelected){
+					cookie = local._data(local.cookiePrefix + SELECTED);
+					if(cookie){
+						keyList = cookie.split(instOpts.cookieDelimiter);
+						for(i=0; i<keyList.length; i++){
+							node = tree.getNodeByKey(keyList[i]);
+							if(node){
+								if(node.selected === undefined || instOpts.overrideSource && (node.selected === false)){
+//									node.setSelected();
+									node.selected = true;
+									node.renderStatus();
+								}
+							}else{
+								// node is no longer member of the tree: remove from cookie also
+								local._appendKey(SELECTED, keyList[i], false);
+							}
+						}
+					}
+					// In selectMode 3 we have to fix the child nodes, since we
+					// only stored the selected *top* nodes
+					if( tree.options.selectMode === 3 ){
+						tree.visit(function(n){
+							if( n.selected ) {
+								n.fixSelection3AfterClick();
+								return "skip";
+							}
+						});
+					}
+				}
+				if(local.storeActive){
+					cookie = local._data(local.cookiePrefix + ACTIVE);
+					if(cookie && (opts.persist.overrideSource || !tree.activeNode)){
+						node = tree.getNodeByKey(cookie);
+						if(node){
+							node.debug("persist: set active", cookie);
+							// We only want to set the focus if the container
+							// had the keyboard focus before
+							node.setActive(true, {
+								noFocus: true,
+								noEvents: noEvents
+							});
+						}
+					}
+				}
+				if(local.storeFocus && prevFocus){
+					node = tree.getNodeByKey(prevFocus);
+					if(node){
+						// node.debug("persist: set focus", cookie);
+						if( tree.options.titlesTabbable ) {
+							$(node.span).find(".fancytree-title").focus();
+						} else {
+							$(tree.$container).focus();
+						}
+						// node.setFocus();
+					}
+				}
+				tree._triggerTreeEvent("restore", null, {});
+			});
+		});
+		// Init the tree
+		return this._superApply(arguments);
+	},
+	nodeSetActive: function(ctx, flag, opts) {
+		var res,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if(local.storeActive){
+			local._data(local.cookiePrefix + ACTIVE, this.activeNode ? this.activeNode.key : null);
+		}
+		return res;
+	},
+	nodeSetExpanded: function(ctx, flag, opts) {
+		var res,
+			node = ctx.node,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if(local.storeExpanded){
+			local._appendKey(EXPANDED, node.key, flag);
+		}
+		return res;
+	},
+	nodeSetFocus: function(ctx, flag) {
+		var res,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if( local.storeFocus ) {
+			local._data(local.cookiePrefix + FOCUS, this.focusNode ? this.focusNode.key : null);
+		}
+		return res;
+	},
+	nodeSetSelected: function(ctx, flag) {
+		var res, selNodes,
+			tree = ctx.tree,
+			node = ctx.node,
+			local = this._local;
+
+		flag = (flag !== false);
+		res = this._superApply(arguments);
+
+		if(local.storeSelected){
+			if( tree.options.selectMode === 3 ){
+				// In selectMode 3 we only store the the selected *top* nodes.
+				// De-selecting a node may also de-select some parents, so we
+				// calculate the current status again
+				selNodes = $.map(tree.getSelectedNodes(true), function(n){
+					return n.key;
+				});
+				selNodes = selNodes.join(ctx.options.persist.cookieDelimiter);
+				local._data(local.cookiePrefix + SELECTED, selNodes);
+			} else {
+				// beforeSelect can prevent the change - flag doesn't reflect the node.selected state
+				local._appendKey(SELECTED, node.key, node.selected);
+			}
+		}
+		return res;
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.table.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.table.js
new file mode 100644
index 00000000000..4367b9dfcd2
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.table.js
@@ -0,0 +1,366 @@
+/*!
+ * jquery.fancytree.table.js
+ *
+ * Render tree as table (aka 'treegrid', 'tabletree').
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/* *****************************************************************************
+ * Private functions and variables
+ */
+function _assert(cond, msg){
+	msg = msg || "";
+	if(!cond){
+		$.error("Assertion failed " + msg);
+	}
+}
+
+function insertSiblingAfter(referenceNode, newNode) {
+	referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+}
+
+/* Show/hide all rows that are structural descendants of `parent`. */
+function setChildRowVisibility(parent, flag) {
+	parent.visit(function(node){
+		var tr = node.tr;
+		// currentFlag = node.hide ? false : flag; // fix for ext-filter
+		if(tr){
+			tr.style.display = (node.hide || !flag) ? "none" : "";
+		}
+		if(!node.expanded){
+			return "skip";
+		}
+	});
+}
+
+/* Find node that is rendered in previous row. */
+function findPrevRowNode(node){
+	var i, last, prev,
+		parent = node.parent,
+		siblings = parent ? parent.children : null;
+
+	if(siblings && siblings.length > 1 && siblings[0] !== node){
+		// use the lowest descendant of the preceeding sibling
+		i = $.inArray(node, siblings);
+		prev = siblings[i - 1];
+		_assert(prev.tr);
+		// descend to lowest child (with a <tr> tag)
+		while(prev.children){
+			last = prev.children[prev.children.length - 1];
+			if(!last.tr){
+				break;
+			}
+			prev = last;
+		}
+	}else{
+		// if there is no preceding sibling, use the direct parent
+		prev = parent;
+	}
+	return prev;
+}
+
+
+$.ui.fancytree.registerExtension({
+	name: "table",
+	version: "0.2.1",
+	// Default options for this extension.
+	options: {
+		checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
+		customStatus: false,	 // true: generate renderColumns events for status nodes
+		indentation: 16,         // indent every node level by 16px
+		nodeColumnIdx: 0         // render node expander, icon, and title to this column (default: #0)
+	},
+	// Overide virtual methods for this extension.
+	// `this`       : is this extension object
+	// `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+	treeInit: function(ctx){
+		var i, $row, tdRole,
+			tree = ctx.tree,
+			$table = tree.widget.element;
+
+		$table.addClass("fancytree-container fancytree-ext-table");
+		tree.tbody = $table.find("> tbody")[0];
+		tree.columnCount = $("thead >tr >th", $table).length;
+		$(tree.tbody).empty();
+
+		tree.rowFragment = document.createDocumentFragment();
+		$row = $("<tr />");
+		tdRole = "";
+		if(ctx.options.aria){
+			$row.attr("role", "row");
+			tdRole = " role='gridcell'";
+		}
+		for(i=0; i<tree.columnCount; i++) {
+			if(ctx.options.table.nodeColumnIdx === i){
+				$row.append("<td" + tdRole + "><span class='fancytree-node' /></td>");
+			}else{
+				$row.append("<td" + tdRole + " />");
+			}
+		}
+		tree.rowFragment.appendChild($row.get(0));
+
+		// Make sure that status classes are set on the node's <tr> elements
+		tree.statusClassPropName = "tr";
+		tree.ariaPropName = "tr";
+		this.nodeContainerAttrName = "tr";
+
+		// #489: make sure $container is set to <table>, even if ext-dnd is listed before ext-table
+		tree.$container = $table;
+
+		this._superApply(arguments);
+
+		// standard Fancytree created a root UL
+		$(tree.rootNode.ul).remove();
+		tree.rootNode.ul = null;
+//		tree.$container = $table;
+		// Add container to the TAB chain
+		this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1");
+		if(this.options.aria){
+			tree.$container
+				.attr("role", "treegrid")
+				.attr("aria-readonly", true);
+		}
+	},
+	/* Called by nodeRender to sync node order with tag order.*/
+//    nodeFixOrder: function(ctx) {
+//    },
+	nodeRemoveChildMarkup: function(ctx) {
+		var node = ctx.node;
+//		node.debug("nodeRemoveChildMarkup()");
+		node.visit(function(n){
+			if(n.tr){
+				$(n.tr).remove();
+				n.tr = null;
+			}
+		});
+	},
+	nodeRemoveMarkup: function(ctx) {
+		var node = ctx.node;
+//		node.debug("nodeRemoveMarkup()");
+		if(node.tr){
+			$(node.tr).remove();
+			node.tr = null;
+		}
+		this.nodeRemoveChildMarkup(ctx);
+	},
+	/* Override standard render. */
+	nodeRender: function(ctx, force, deep, collapsed, _recursive) {
+		var children, firstTr, i, l, newRow, prevNode, prevTr, subCtx,
+			tree = ctx.tree,
+			node = ctx.node,
+			opts = ctx.options,
+			isRootNode = !node.parent;
+
+		if( !_recursive ){
+			ctx.hasCollapsedParents = node.parent && !node.parent.expanded;
+		}
+		// $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr));
+		if( !isRootNode ){
+			if(!node.tr){
+				if( ctx.hasCollapsedParents && !deep ) {
+					// #166: we assume that the parent will be (recursively) rendered
+					// later anyway.
+					node.debug("nodeRender ignored due to unrendered parent");
+					return;
+				}
+				// Create new <tr> after previous row
+				newRow = tree.rowFragment.firstChild.cloneNode(true);
+				prevNode = findPrevRowNode(node);
+				// $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key);
+				_assert(prevNode);
+				if(collapsed === true && _recursive){
+					// hide all child rows, so we can use an animation to show it later
+					newRow.style.display = "none";
+				}else if(deep && ctx.hasCollapsedParents){
+					// also hide this row if deep === true but any parent is collapsed
+					newRow.style.display = "none";
+//					newRow.style.color = "red";
+				}
+				if(!prevNode.tr){
+					_assert(!prevNode.parent, "prev. row must have a tr, or is system root");
+					tree.tbody.appendChild(newRow);
+				}else{
+					insertSiblingAfter(prevNode.tr, newRow);
+				}
+				node.tr = newRow;
+				if( node.key && opts.generateIds ){
+					node.tr.id = opts.idPrefix + node.key;
+				}
+				node.tr.ftnode = node;
+				if(opts.aria){
+					// TODO: why doesn't this work:
+//                  node.li.role = "treeitem";
+					$(node.tr).attr("aria-labelledby", "ftal_" + node.key);
+				}
+				node.span = $("span.fancytree-node", node.tr).get(0);
+				// Set icon, link, and title (normally this is only required on initial render)
+				this.nodeRenderTitle(ctx);
+				// Allow tweaking, binding, after node was created for the first time
+//				tree._triggerNodeEvent("createNode", ctx);
+				if ( opts.createNode ){
+					opts.createNode.call(tree, {type: "createNode"}, ctx);
+				}
+			} else {
+				if( force ) {
+					// Set icon, link, and title (normally this is only required on initial render)
+					this.nodeRenderTitle(ctx); // triggers renderColumns()
+				} else {
+					// Update element classes according to node state
+					this.nodeRenderStatus(ctx);
+				}
+			}
+		}
+		// Allow tweaking after node state was rendered
+//		tree._triggerNodeEvent("renderNode", ctx);
+		if ( opts.renderNode ){
+			opts.renderNode.call(tree, {type: "renderNode"}, ctx);
+		}
+		// Visit child nodes
+		// Add child markup
+		children = node.children;
+		if(children && (isRootNode || deep || node.expanded)){
+			for(i=0, l=children.length; i<l; i++) {
+				subCtx = $.extend({}, ctx, {node: children[i]});
+				subCtx.hasCollapsedParents = subCtx.hasCollapsedParents || !node.expanded;
+				this.nodeRender(subCtx, force, deep, collapsed, true);
+			}
+		}
+		// Make sure, that <tr> order matches node.children order.
+		if(children && !_recursive){ // we only have to do it once, for the root branch
+			prevTr = node.tr || null;
+			firstTr = tree.tbody.firstChild;
+			// Iterate over all descendants
+			node.visit(function(n){
+				if(n.tr){
+					if(!n.parent.expanded && n.tr.style.display !== "none"){
+						// fix after a node was dropped over a collapsed
+						n.tr.style.display = "none";
+						setChildRowVisibility(n, false);
+					}
+					if(n.tr.previousSibling !== prevTr){
+						node.debug("_fixOrder: mismatch at node: " + n);
+						var nextTr = prevTr ? prevTr.nextSibling : firstTr;
+						tree.tbody.insertBefore(n.tr, nextTr);
+					}
+					prevTr = n.tr;
+				}
+			});
+		}
+		// Update element classes according to node state
+		// if(!isRootNode){
+		// 	this.nodeRenderStatus(ctx);
+		// }
+	},
+	nodeRenderTitle: function(ctx, title) {
+		var $cb,
+			node = ctx.node,
+			opts = ctx.options;
+
+		this._superApply(arguments);
+		// Move checkbox to custom column
+		if(opts.checkbox && opts.table.checkboxColumnIdx != null ){
+			$cb = $("span.fancytree-checkbox", node.span).detach();
+			$(node.tr).find("td").eq(+opts.table.checkboxColumnIdx).html($cb);
+		}
+		// Update element classes according to node state
+		if( ! node.isRoot() ){
+			this.nodeRenderStatus(ctx);
+		}
+		if( !opts.table.customStatus && node.isStatusNode() ) {
+			// default rendering for status node: leave other cells empty
+		} else if ( opts.renderColumns ) {
+			// Let user code write column content
+			opts.renderColumns.call(ctx.tree, {type: "renderColumns"}, ctx);
+		}
+	},
+	nodeRenderStatus: function(ctx) {
+		var indent,
+			node = ctx.node,
+			opts = ctx.options;
+
+		this._superApply(arguments);
+
+		$(node.tr).removeClass("fancytree-node");
+		// indent
+		indent = (node.getLevel() - 1) * opts.table.indentation;
+		$(node.span).css({paddingLeft: indent + "px"});  // #460
+		// $(node.span).css({marginLeft: indent + "px"});
+	 },
+	/* Expand node, return Deferred.promise. */
+	nodeSetExpanded: function(ctx, flag, opts) {
+		var dfd = new $.Deferred(),
+			subOpts = $.extend({}, opts, {noEvents: true, noAnimation: true});
+
+		opts = opts || {};
+
+		function _afterExpand(ok) {
+			flag = (flag !== false);
+			setChildRowVisibility(ctx.node, flag);
+			if( ok ) {
+				if( flag && ctx.options.autoScroll && !opts.noAnimation && ctx.node.hasChildren() ) {
+					// Scroll down to last child, but keep current node visible
+					ctx.node.getLastChild().scrollIntoView(true, {topNode: ctx.node}).always(function(){
+						if( !opts.noEvents ) {
+							ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+						}
+						dfd.resolveWith(ctx.node);
+					});
+				} else {
+					if( !opts.noEvents ) {
+						ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+					}
+					dfd.resolveWith(ctx.node);
+				}
+			} else {
+				if( !opts.noEvents ) {
+					ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
+				}
+				dfd.rejectWith(ctx.node);
+			}
+		}
+		// Call base-expand with disabled  events and animation
+		this._super(ctx, flag, subOpts).done(function () {
+			_afterExpand(true);
+		}).fail(function () {
+			_afterExpand(false);
+		});
+		return dfd.promise();
+	},
+	nodeSetStatus: function(ctx, status, message, details) {
+		if(status === "ok"){
+			var node = ctx.node,
+				firstChild = ( node.children ? node.children[0] : null );
+			if ( firstChild && firstChild.isStatusNode() ) {
+				$(firstChild.tr).remove();
+			}
+		}
+		return this._superApply(arguments);
+	},
+	treeClear: function(ctx) {
+		this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode));
+		return this._superApply(arguments);
+	},
+	treeDestroy: function(ctx) {
+		this.$container.find("tbody").empty();
+		this.$source && this.$source.removeClass("ui-helper-hidden");
+	}
+	/*,
+	treeSetFocus: function(ctx, flag) {
+//	        alert("treeSetFocus" + ctx.tree.$container);
+		ctx.tree.$container.focus();
+		$.ui.fancytree.focusTree = ctx.tree;
+	}*/
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.themeroller.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.themeroller.js
new file mode 100644
index 00000000000..be9ba09df9b
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.themeroller.js
@@ -0,0 +1,78 @@
+/*!
+ * jquery.fancytree.themeroller.js
+ *
+ * Enable jQuery UI ThemeRoller styles.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @see http://jqueryui.com/themeroller/
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "themeroller",
+	version: "0.0.1",
+	// Default options for this extension.
+	options: {
+		activeClass: "ui-state-active",
+		foccusClass: "ui-state-focus",
+		hoverClass: "ui-state-hover",
+		selectedClass: "ui-state-highlight"
+	},
+
+	treeInit: function(ctx){
+		this._superApply(arguments);
+		var $el = ctx.widget.element;
+
+		if($el[0].nodeName === "TABLE"){
+			$el.addClass("ui-widget ui-corner-all");
+			$el.find(">thead tr").addClass("ui-widget-header");
+			$el.find(">tbody").addClass("ui-widget-conent");
+		}else{
+			$el.addClass("ui-widget ui-widget-content ui-corner-all");
+		}
+
+		$el.delegate(".fancytree-node", "mouseenter mouseleave", function(event){
+			var node = $.ui.fancytree.getNode(event.target),
+				flag = (event.type === "mouseenter");
+			node.debug("hover: " + flag);
+			$(node.tr ? node.tr : node.span).toggleClass("ui-state-hover ui-corner-all", flag);
+		});
+	},
+	treeDestroy: function(ctx){
+		this._superApply(arguments);
+		ctx.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all");
+	},
+	nodeRenderStatus: function(ctx){
+		var node = ctx.node,
+			$el = $(node.tr ? node.tr : node.span);
+		this._superApply(arguments);
+/*
+		.ui-state-highlight: Class to be applied to highlighted or selected elements. Applies "highlight" container styles to an element and its child text, links, and icons.
+		.ui-state-error: Class to be applied to error messaging container elements. Applies "error" container styles to an element and its child text, links, and icons.
+		.ui-state-error-text: An additional class that applies just the error text color without background. Can be used on form labels for instance. Also applies error icon color to child icons.
+
+		.ui-state-default: Class to be applied to clickable button-like elements. Applies "clickable default" container styles to an element and its child text, links, and icons.
+		.ui-state-hover: Class to be applied on mouseover to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+		.ui-state-focus: Class to be applied on keyboard focus to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+		.ui-state-active: Class to be applied on mousedown to clickable button-like elements. Applies "clickable active" container styles to an element and its child text, links, and icons.
+*/
+		$el.toggleClass("ui-state-active", node.isActive());
+		$el.toggleClass("ui-state-focus", node.hasFocus());
+		$el.toggleClass("ui-state-highlight", node.isSelected());
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.wide.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.wide.js
new file mode 100644
index 00000000000..e3a41b70d8e
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-fancytree/js/src/jquery.fancytree.wide.js
@@ -0,0 +1,183 @@
+/*!
+ * jquery.fancytree.wide.js
+ * Support for 100% wide selection bars.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.13.0
+ * @date 2015-11-16T07:33
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+var reNumUnit = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/; // split "1.5em" to ["1.5", "em"]
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+// var _assert = $.ui.fancytree.assert;
+
+/* Calculate inner width without scrollbar */
+// function realInnerWidth($el) {
+// 	// http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
+// //	inst.contWidth = parseFloat(this.$container.css("width"), 10);
+// 	// 'Client width without scrollbar' - 'padding'
+// 	return $el[0].clientWidth - ($el.innerWidth() -  parseFloat($el.css("width"), 10));
+// }
+
+/* Create a global embedded CSS style for the tree. */
+function defineHeadStyleElement(id, cssText) {
+	id = "fancytree-style-" + id;
+	var $headStyle = $("#" + id);
+
+	if( !cssText ) {
+		$headStyle.remove();
+		return null;
+	}
+	if( !$headStyle.length ) {
+		$headStyle = $("<style />")
+			.attr("id", id)
+			.addClass("fancytree-style")
+			.prop("type", "text/css")
+			.appendTo("head");
+	}
+	try {
+		$headStyle.html(cssText);
+	} catch ( e ) {
+		// fix for IE 6-8
+		$headStyle[0].styleSheet.cssText = cssText;
+	}
+	return $headStyle;
+}
+
+/* Calculate the CSS rules that indent title spans. */
+function renderLevelCss(containerId, depth, levelOfs, lineOfs, measureUnit) {
+	var i,
+		prefix = "#" + containerId + " span.fancytree-level-",
+		rules = [];
+
+	for(i = 0; i < depth; i++) {
+		rules.push(prefix + (i + 1) + " span.fancytree-title { padding-left: " +
+			(i * levelOfs + lineOfs) + measureUnit + "; }");
+	}
+	// Some UI animations wrap the UL inside a DIV and set position:relative on both.
+	// This breaks the left:0 and padding-left:nn settings of the title
+	rules.push("#" + containerId +
+		" div.ui-effects-wrapper ul li span.fancytree-title " +
+		"{ padding-left: 3px; position: static; width: auto; }");
+	return rules.join("\n");
+}
+
+
+// /**
+//  * [ext-wide] Recalculate the width of the selection bar after the tree container
+//  * was resized.<br>
+//  * May be called explicitly on container resize, since there is no resize event
+//  * for DIV tags.
+//  *
+//  * @alias Fancytree#wideUpdate
+//  * @requires jquery.fancytree.wide.js
+//  */
+// $.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){
+// 	var inst = this.ext.wide,
+// 		prevCw = inst.contWidth,
+// 		prevLo = inst.lineOfs;
+
+// 	inst.contWidth = realInnerWidth(this.$container);
+// 	// Each title is precceeded by 2 or 3 icons (16px + 3 margin)
+// 	//     + 1px title border and 3px title padding
+// 	// TODO: use code from treeInit() below
+// 	inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19;
+// 	if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) {
+// 		this.debug("wideUpdate: " + inst.contWidth);
+// 		this.visit(function(node){
+// 			node.tree._callHook("nodeRenderTitle", node);
+// 		});
+// 	}
+// };
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+	name: "wide",
+	version: "0.0.3",
+	// Default options for this extension.
+	options: {
+		iconWidth: null,  // Adjust this if @fancy-icon-width != "16px"
+		iconSpacing: null, // Adjust this if @fancy-icon-spacing != "3px"
+		levelOfs: null    // Adjust this if ul padding != "16px"
+	},
+
+	treeCreate: function(ctx){
+		this._superApply(arguments);
+		this.$container.addClass("fancytree-ext-wide");
+
+		var containerId, cssText, iconSpacingUnit, iconWidthUnit, levelOfsUnit,
+			instOpts = ctx.options.wide,
+			// css sniffing
+			$dummyLI = $("<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />")
+				.appendTo(ctx.tree.$container),
+			$dummyIcon = $dummyLI.find(".fancytree-icon"),
+			$dummyUL = $dummyLI.find("ul"),
+			// $dummyTitle = $dummyLI.find(".fancytree-title"),
+			iconSpacing = instOpts.iconSpacing || $dummyIcon.css("margin-left"),
+			iconWidth = instOpts.iconWidth || $dummyIcon.css("width"),
+			levelOfs = instOpts.levelOfs || $dummyUL.css("padding-left");
+
+		$dummyLI.remove();
+
+		iconSpacingUnit = iconSpacing.match(reNumUnit)[2];
+		iconSpacing = parseFloat(iconSpacing, 10);
+		iconWidthUnit = iconWidth.match(reNumUnit)[2];
+		iconWidth = parseFloat(iconWidth, 10);
+		levelOfsUnit = levelOfs.match(reNumUnit)[2];
+		if( iconSpacingUnit !== iconWidthUnit || levelOfsUnit !== iconWidthUnit ) {
+			$.error("iconWidth, iconSpacing, and levelOfs must have the same css measure unit");
+		}
+		this._local.measureUnit = iconWidthUnit;
+		this._local.levelOfs = parseFloat(levelOfs);
+		this._local.lineOfs = (1 + (ctx.options.checkbox ? 1 : 0) + (ctx.options.icons ? 1 : 0)) * (iconWidth + iconSpacing) + iconSpacing;
+		this._local.maxDepth = 10;
+
+		// Get/Set a unique Id on the container (if not already exists)
+		containerId = this.$container.uniqueId().attr("id");
+		// Generated css rules for some levels (extended on demand)
+		cssText = renderLevelCss(containerId, this._local.maxDepth,
+			this._local.levelOfs, this._local.lineOfs, this._local.measureUnit);
+		defineHeadStyleElement(containerId, cssText);
+	},
+	treeDestroy: function(ctx){
+		// Remove generated css rules
+		defineHeadStyleElement(this.$container.attr("id"), null);
+		return this._superApply(arguments);
+	},
+	nodeRenderStatus: function(ctx) {
+		var containerId, cssText, res,
+			node = ctx.node,
+			level = node.getLevel();
+
+		res = this._superApply(arguments);
+		// Generate some more level-n rules if required
+		if( level > this._local.maxDepth ) {
+			containerId = this.$container.attr("id");
+			this._local.maxDepth *= 2;
+			node.debug("Define global ext-wide css up to level " + this._local.maxDepth);
+			cssText = renderLevelCss(containerId, this._local.maxDepth,
+				this._local.levelOfs, this._local.lineOfs, this._local.measureUnit);
+			defineHeadStyleElement(containerId, cssText);
+		}
+		// Add level-n class to apply indentation padding.
+		// (Setting element style would not work, since it cannot easily be
+		// overriden while animations run)
+		$(node.span).addClass("fancytree-level-" + level);
+		return res;
+	}
+});
+}(jQuery, window, document));
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/LICENSE.txt b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/LICENSE.txt
new file mode 100644
index 00000000000..5bed848ae9d
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/LICENSE.txt
@@ -0,0 +1 @@
+Open Source - MIT License
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/VERSION.txt b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/VERSION.txt
new file mode 100644
index 00000000000..67437808808
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/VERSION.txt
@@ -0,0 +1 @@
+1.11.4
\ No newline at end of file
diff --git a/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/js/jquery-ui-custom.js b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/js/jquery-ui-custom.js
new file mode 100644
index 00000000000..31ee9cd8116
--- /dev/null
+++ b/plasmid/source/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/jquery-ui/js/jquery-ui-custom.js
@@ -0,0 +1,16617 @@
+/*! jQuery UI - v1.11.4 - 2015-03-11
+* http://jqueryui.com
+* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js
+* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
+
+(function( factory ) {
+	if ( typeof define === "function" && define.amd ) {
+
+		// AMD. Register as an anonymous module.
+		define([ "jquery" ], factory );
+	} else {
+
+		// Browser globals
+		factory( jQuery );
+	}
+}(function( $ ) {
+/*!
+ * jQuery UI Core 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/ui-core/
+ */
+
+
+// $.ui might exist from components with no dependencies, e.g., $.ui.position
+$.ui = $.ui || {};
+
+$.extend( $.ui, {
+	version: "1.11.4",
+
+	keyCode: {
+		BACKSPACE: 8,
+		COMMA: 188,
+		DELETE: 46,
+		DOWN: 40,
+		END: 35,
+		ENTER: 13,
+		ESCAPE: 27,
+		HOME: 36,
+		LEFT: 37,
+		PAGE_DOWN: 34,
+		PAGE_UP: 33,
+		PERIOD: 190,
+		RIGHT: 39,
+		SPACE: 32,
+		TAB: 9,
+		UP: 38
+	}
+});
+
+// plugins
+$.fn.extend({
+	scrollParent: function( includeHidden ) {
+		var position = this.css( "position" ),
+			excludeStaticParent = position === "absolute",
+			overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
+			scrollParent = this.parents().filter( function() {
+				var parent = $( this );
+				if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
+					return false;
+				}
+				return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
+			}).eq( 0 );
+
+		return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
+	},
+
+	uniqueId: (function() {
+		var uuid = 0;
+
+		return function() {
+			return this.each(function() {
+				if ( !this.id ) {
+					this.id = "ui-id-" + ( ++uuid );
+				}
+			});
+		};
+	})(),
+
+	removeUniqueId: function() {
+		return this.each(function() {
+			if ( /^ui-id-\d+$/.test( this.id ) ) {
+				$( this ).removeAttr( "id" );
+			}
+		});
+	}
+});
+
+// selectors
+function focusable( element, isTabIndexNotNaN ) {
+	var map, mapName, img,
+		nodeName = element.nodeName.toLowerCase();
+	if ( "area" === nodeName ) {
+		map = element.parentNode;
+		mapName = map.name;
+		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
+			return false;
+		}
+		img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
+		return !!img && visible( img );
+	}
+	return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ?
+		!element.disabled :
+		"a" === nodeName ?
+			element.href || isTabIndexNotNaN :
+			isTabIndexNotNaN) &&
+		// the element and all of its ancestors must be visible
+		visible( element );
+}
+
+function visible( element ) {
+	return $.expr.filters.visible( element ) &&
+		!$( element ).parents().addBack().filter(function() {
+			return $.css( this, "visibility" ) === "hidden";
+		}).length;
+}
+
+$.extend( $.expr[ ":" ], {
+	data: $.expr.createPseudo ?
+		$.expr.createPseudo(function( dataName ) {
+			return function( elem ) {
+				return !!$.data( elem, dataName );
+			};
+		}) :
+		// support: jQuery <1.8
+		function( elem, i, match ) {
+			return !!$.data( elem, match[ 3 ] );
+		},
+
+	focusable: function( element ) {
+		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
+	},
+
+	tabbable: function( element ) {
+		var tabIndex = $.attr( element, "tabindex" ),
+			isTabIndexNaN = isNaN( tabIndex );
+		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
+	}
+});
+
+// support: jQuery <1.8
+if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
+	$.each( [ "Width", "Height" ], function( i, name ) {
+		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
+			type = name.toLowerCase(),
+			orig = {
+				innerWidth: $.fn.innerWidth,
+				innerHeight: $.fn.innerHeight,
+				outerWidth: $.fn.outerWidth,
+				outerHeight: $.fn.outerHeight
+			};
+
+		function reduce( elem, size, border, margin ) {
+			$.each( side, function() {
+				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
+				if ( border ) {
+					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
+				}
+				if ( margin ) {
+					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
+				}
+			});
+			return size;
+		}
+
+		$.fn[ "inner" + name ] = function( size ) {
+			if ( size === undefined ) {
+				return orig[ "inner" + name ].call( this );
+			}
+
+			return this.each(function() {
+				$( this ).css( type, reduce( this, size ) + "px" );
+			});
+		};
+
+		$.fn[ "outer" + name] = function( size, margin ) {
+			if ( typeof size !== "number" ) {
+				return orig[ "outer" + name ].call( this, size );
+			}
+
+			return this.each(function() {
+				$( this).css( type, reduce( this, size, true, margin ) + "px" );
+			});
+		};
+	});
+}
+
+// support: jQuery <1.8
+if ( !$.fn.addBack ) {
+	$.fn.addBack = function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter( selector )
+		);
+	};
+}
+
+// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
+if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
+	$.fn.removeData = (function( removeData ) {
+		return function( key ) {
+			if ( arguments.length ) {
+				return removeData.call( this, $.camelCase( key ) );
+			} else {
+				return removeData.call( this );
+			}
+		};
+	})( $.fn.removeData );
+}
+
+// deprecated
+$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
+
+$.fn.extend({
+	focus: (function( orig ) {
+		return function( delay, fn ) {
+			return typeof delay === "number" ?
+				this.each(function() {
+					var elem = this;
+					setTimeout(function() {
+						$( elem ).focus();
+						if ( fn ) {
+							fn.call( elem );
+						}
+					}, delay );
+				}) :
+				orig.apply( this, arguments );
+		};
+	})( $.fn.focus ),
+
+	disableSelection: (function() {
+		var eventType = "onselectstart" in document.createElement( "div" ) ?
+			"selectstart" :
+			"mousedown";
+
+		return function() {
+			return this.bind( eventType + ".ui-disableSelection", function( event ) {
+				event.preventDefault();
+			});
+		};
+	})(),
+
+	enableSelection: function() {
+		return this.unbind( ".ui-disableSelection" );
+	},
+
+	zIndex: function( zIndex ) {
+		if ( zIndex !== undefined ) {
+			return this.css( "zIndex", zIndex );
+		}
+
+		if ( this.length ) {
+			var elem = $( this[ 0 ] ), position, value;
+			while ( elem.length && elem[ 0 ] !== document ) {
+				// Ignore z-index if position is set to a value where z-index is ignored by the browser
+				// This makes behavior of this function consistent across browsers
+				// WebKit always returns auto if the element is positioned
+				position = elem.css( "position" );
+				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
+					// IE returns 0 when zIndex is not specified
+					// other browsers return a string
+					// we ignore the case of nested elements with an explicit value of 0
+					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
+					value = parseInt( elem.css( "zIndex" ), 10 );
+					if ( !isNaN( value ) && value !== 0 ) {
+						return value;
+					}
+				}
+				elem = elem.parent();
+			}
+		}
+
+		return 0;
+	}
+});
+
+// $.ui.plugin is deprecated. Use $.widget() extensions instead.
+$.ui.plugin = {
+	add: function( module, option, set ) {
+		var i,
+			proto = $.ui[ module ].prototype;
+		for ( i in set ) {
+			proto.plugins[ i ] = proto.plugins[ i ] || [];
+			proto.plugins[ i ].push( [ option, set[ i ] ] );
+		}
+	},
+	call: function( instance, name, args, allowDisconnected ) {
+		var i,
+			set = instance.plugins[ name ];
+
+		if ( !set ) {
+			return;
+		}
+
+		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
+			return;
+		}
+
+		for ( i = 0; i < set.length; i++ ) {
+			if ( instance.options[ set[ i ][ 0 ] ] ) {
+				set[ i ][ 1 ].apply( instance.element, args );
+			}
+		}
+	}
+};
+
+
+/*!
+ * jQuery UI Widget 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/jQuery.widget/
+ */
+
+
+var widget_uuid = 0,
+	widget_slice = Array.prototype.slice;
+
+$.cleanData = (function( orig ) {
+	return function( elems ) {
+		var events, elem, i;
+		for ( i = 0; (elem = elems[i]) != null; i++ ) {
+			try {
+
+				// Only trigger remove when necessary to save time
+				events = $._data( elem, "events" );
+				if ( events && events.remove ) {
+					$( elem ).triggerHandler( "remove" );
+				}
+
+			// http://bugs.jquery.com/ticket/8235
+			} catch ( e ) {}
+		}
+		orig( elems );
+	};
+})( $.cleanData );
+
+$.widget = function( name, base, prototype ) {
+	var fullName, existingConstructor, constructor, basePrototype,
+		// proxiedPrototype allows the provided prototype to remain unmodified
+		// so that it can be used as a mixin for multiple widgets (#8876)
+		proxiedPrototype = {},
+		namespace = name.split( "." )[ 0 ];
+
+	name = name.split( "." )[ 1 ];
+	fullName = namespace + "-" + name;
+
+	if ( !prototype ) {
+		prototype = base;
+		base = $.Widget;
+	}
+
+	// create selector for plugin
+	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
+		return !!$.data( elem, fullName );
+	};
+
+	$[ namespace ] = $[ namespace ] || {};
+	existingConstructor = $[ namespace ][ name ];
+	constructor = $[ namespace ][ name ] = function( options, element ) {
+		// allow instantiation without "new" keyword
+		if ( !this._createWidget ) {
+			return new constructor( options, element );
+		}
+
+		// allow instantiation without initializing for simple inheritance
+		// must use "new" keyword (the code above always passes args)
+		if ( arguments.length ) {
+			this._createWidget( options, element );
+		}
+	};
+	// extend with the existing constructor to carry over any static properties
+	$.extend( constructor, existingConstructor, {
+		version: prototype.version,
+		// copy the object used to create the prototype in case we need to
+		// redefine the widget later
+		_proto: $.extend( {}, prototype ),
+		// track widgets that inherit from this widget in case this widget is
+		// redefined after a widget inherits from it
+		_childConstructors: []
+	});
+
+	basePrototype = new base();
+	// we need to make the options hash a property directly on the new instance
+	// otherwise we'll modify the options hash on the prototype that we're
+	// inheriting from
+	basePrototype.options = $.widget.extend( {}, basePrototype.options );
+	$.each( prototype, function( prop, value ) {
+		if ( !$.isFunction( value ) ) {
+			proxiedPrototype[ prop ] = value;
+			return;
+		}
+		proxiedPrototype[ prop ] = (function() {
+			var _super = function() {
+					return base.prototype[ prop ].apply( this, arguments );
+				},
+				_superApply = function( args ) {
+					return base.prototype[ prop ].apply( this, args );
+				};
+			return function() {
+				var __super = this._super,
+					__superApply = this._superApply,
+					returnValue;
+
+				this._super = _super;
+				this._superApply = _superApply;
+
+				returnValue = value.apply( this, arguments );
+
+				this._super = __super;
+				this._superApply = __superApply;
+
+				return returnValue;
+			};
+		})();
+	});
+	constructor.prototype = $.widget.extend( basePrototype, {
+		// TODO: remove support for widgetEventPrefix
+		// always use the name + a colon as the prefix, e.g., draggable:start
+		// don't prefix for widgets that aren't DOM-based
+		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
+	}, proxiedPrototype, {
+		constructor: constructor,
+		namespace: namespace,
+		widgetName: name,
+		widgetFullName: fullName
+	});
+
+	// If this widget is being redefined then we need to find all widgets that
+	// are inheriting from it and redefine all of them so that they inherit from
+	// the new version of this widget. We're essentially trying to replace one
+	// level in the prototype chain.
+	if ( existingConstructor ) {
+		$.each( existingConstructor._childConstructors, function( i, child ) {
+			var childPrototype = child.prototype;
+
+			// redefine the child widget using the same prototype that was
+			// originally used, but inherit from the new version of the base
+			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
+		});
+		// remove the list of existing child constructors from the old constructor
+		// so the old child constructors can be garbage collected
+		delete existingConstructor._childConstructors;
+	} else {
+		base._childConstructors.push( constructor );
+	}
+
+	$.widget.bridge( name, constructor );
+
+	return constructor;
+};
+
+$.widget.extend = function( target ) {
+	var input = widget_slice.call( arguments, 1 ),
+		inputIndex = 0,
+		inputLength = input.length,
+		key,
+		value;
+	for ( ; inputIndex < inputLength; inputIndex++ ) {
+		for ( key in input[ inputIndex ] ) {
+			value = input[ inputIndex ][ key ];
+			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
+				// Clone objects
+				if ( $.isPlainObject( value ) ) {
+					target[ key ] = $.isPlainObject( target[ key ] ) ?
+						$.widget.extend( {}, target[ key ], value ) :
+						// Don't extend strings, arrays, etc. with objects
+						$.widget.extend( {}, value );
+				// Copy everything else by reference
+				} else {
+					target[ key ] = value;
+				}
+			}
+		}
+	}
+	return target;
+};
+
+$.widget.bridge = function( name, object ) {
+	var fullName = object.prototype.widgetFullName || name;
+	$.fn[ name ] = function( options ) {
+		var isMethodCall = typeof options === "string",
+			args = widget_slice.call( arguments, 1 ),
+			returnValue = this;
+
+		if ( isMethodCall ) {
+			this.each(function() {
+				var methodValue,
+					instance = $.data( this, fullName );
+				if ( options === "instance" ) {
+					returnValue = instance;
+					return false;
+				}
+				if ( !instance ) {
+					return $.error( "cannot call methods on " + name + " prior to initialization; " +
+						"attempted to call method '" + options + "'" );
+				}
+				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
+					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
+				}
+				methodValue = instance[ options ].apply( instance, args );
+				if ( methodValue !== instance && methodValue !== undefined ) {
+					returnValue = methodValue && methodValue.jquery ?
+						returnValue.pushStack( methodValue.get() ) :
+						methodValue;
+					return false;
+				}
+			});
+		} else {
+
+			// Allow multiple hashes to be passed on init
+			if ( args.length ) {
+				options = $.widget.extend.apply( null, [ options ].concat(args) );
+			}
+
+			this.each(function() {
+				var instance = $.data( this, fullName );
+				if ( instance ) {
+					instance.option( options || {} );
+					if ( instance._init ) {
+						instance._init();
+					}
+				} else {
+					$.data( this, fullName, new object( options, this ) );
+				}
+			});
+		}
+
+		return returnValue;
+	};
+};
+
+$.Widget = function( /* options, element */ ) {};
+$.Widget._childConstructors = [];
+
+$.Widget.prototype = {
+	widgetName: "widget",
+	widgetEventPrefix: "",
+	defaultElement: "<div>",
+	options: {
+		disabled: false,
+
+		// callbacks
+		create: null
+	},
+	_createWidget: function( options, element ) {
+		element = $( element || this.defaultElement || this )[ 0 ];
+		this.element = $( element );
+		this.uuid = widget_uuid++;
+		this.eventNamespace = "." + this.widgetName + this.uuid;
+
+		this.bindings = $();
+		this.hoverable = $();
+		this.focusable = $();
+
+		if ( element !== this ) {
+			$.data( element, this.widgetFullName, this );
+			this._on( true, this.element, {
+				remove: function( event ) {
+					if ( event.target === element ) {
+						this.destroy();
+					}
+				}
+			});
+			this.document = $( element.style ?
+				// element within the document
+				element.ownerDocument :
+				// element is window or document
+				element.document || element );
+			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
+		}
+
+		this.options = $.widget.extend( {},
+			this.options,
+			this._getCreateOptions(),
+			options );
+
+		this._create();
+		this._trigger( "create", null, this._getCreateEventData() );
+		this._init();
+	},
+	_getCreateOptions: $.noop,
+	_getCreateEventData: $.noop,
+	_create: $.noop,
+	_init: $.noop,
+
+	destroy: function() {
+		this._destroy();
+		// we can probably remove the unbind calls in 2.0
+		// all event bindings should go through this._on()
+		this.element
+			.unbind( this.eventNamespace )
+			.removeData( this.widgetFullName )
+			// support: jquery <1.6.3
+			// http://bugs.jquery.com/ticket/9413
+			.removeData( $.camelCase( this.widgetFullName ) );
+		this.widget()
+			.unbind( this.eventNamespace )
+			.removeAttr( "aria-disabled" )
+			.removeClass(
+				this.widgetFullName + "-disabled " +
+				"ui-state-disabled" );
+
+		// clean up events and states
+		this.bindings.unbind( this.eventNamespace );
+		this.hoverable.removeClass( "ui-state-hover" );
+		this.focusable.removeClass( "ui-state-focus" );
+	},
+	_destroy: $.noop,
+
+	widget: function() {
+		return this.element;
+	},
+
+	option: function( key, value ) {
+		var options = key,
+			parts,
+			curOption,
+			i;
+
+		if ( arguments.length === 0 ) {
+			// don't return a reference to the internal hash
+			return $.widget.extend( {}, this.options );
+		}
+
+		if ( typeof key === "string" ) {
+			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+			options = {};
+			parts = key.split( "." );
+			key = parts.shift();
+			if ( parts.length ) {
+				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
+				for ( i = 0; i < parts.length - 1; i++ ) {
+					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
+					curOption = curOption[ parts[ i ] ];
+				}
+				key = parts.pop();
+				if ( arguments.length === 1 ) {
+					return curOption[ key ] === undefined ? null : curOption[ key ];
+				}
+				curOption[ key ] = value;
+			} else {
+				if ( arguments.length === 1 ) {
+					return this.options[ key ] === undefined ? null : this.options[ key ];
+				}
+				options[ key ] = value;
+			}
+		}
+
+		this._setOptions( options );
+
+		return this;
+	},
+	_setOptions: function( options ) {
+		var key;
+
+		for ( key in options ) {
+			this._setOption( key, options[ key ] );
+		}
+
+		return this;
+	},
+	_setOption: function( key, value ) {
+		this.options[ key ] = value;
+
+		if ( key === "disabled" ) {
+			this.widget()
+				.toggleClass( this.widgetFullName + "-disabled", !!value );
+
+			// If the widget is becoming disabled, then nothing is interactive
+			if ( value ) {
+				this.hoverable.removeClass( "ui-state-hover" );
+				this.focusable.removeClass( "ui-state-focus" );
+			}
+		}
+
+		return this;
+	},
+
+	enable: function() {
+		return this._setOptions({ disabled: false });
+	},
+	disable: function() {
+		return this._setOptions({ disabled: true });
+	},
+
+	_on: function( suppressDisabledCheck, element, handlers ) {
+		var delegateElement,
+			instance = this;
+
+		// no suppressDisabledCheck flag, shuffle arguments
+		if ( typeof suppressDisabledCheck !== "boolean" ) {
+			handlers = element;
+			element = suppressDisabledCheck;
+			suppressDisabledCheck = false;
+		}
+
+		// no element argument, shuffle and use this.element
+		if ( !handlers ) {
+			handlers = element;
+			element = this.element;
+			delegateElement = this.widget();
+		} else {
+			element = delegateElement = $( element );
+			this.bindings = this.bindings.add( element );
+		}
+
+		$.each( handlers, function( event, handler ) {
+			function handlerProxy() {
+				// allow widgets to customize the disabled handling
+				// - disabled as an array instead of boolean
+				// - disabled class as method for disabling individual parts
+				if ( !suppressDisabledCheck &&
+						( instance.options.disabled === true ||
+							$( this ).hasClass( "ui-state-disabled" ) ) ) {
+					return;
+				}
+				return ( typeof handler === "string" ? instance[ handler ] : handler )
+					.apply( instance, arguments );
+			}
+
+			// copy the guid so direct unbinding works
+			if ( typeof handler !== "string" ) {
+				handlerProxy.guid = handler.guid =
+					handler.guid || handlerProxy.guid || $.guid++;
+			}
+
+			var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
+				eventName = match[1] + instance.eventNamespace,
+				selector = match[2];
+			if ( selector ) {
+				delegateElement.delegate( selector, eventName, handlerProxy );
+			} else {
+				element.bind( eventName, handlerProxy );
+			}
+		});
+	},
+
+	_off: function( element, eventName ) {
+		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
+			this.eventNamespace;
+		element.unbind( eventName ).undelegate( eventName );
+
+		// Clear the stack to avoid memory leaks (#10056)
+		this.bindings = $( this.bindings.not( element ).get() );
+		this.focusable = $( this.focusable.not( element ).get() );
+		this.hoverable = $( this.hoverable.not( element ).get() );
+	},
+
+	_delay: function( handler, delay ) {
+		function handlerProxy() {
+			return ( typeof handler === "string" ? instance[ handler ] : handler )
+				.apply( instance, arguments );
+		}
+		var instance = this;
+		return setTimeout( handlerProxy, delay || 0 );
+	},
+
+	_hoverable: function( element ) {
+		this.hoverable = this.hoverable.add( element );
+		this._on( element, {
+			mouseenter: function( event ) {
+				$( event.currentTarget ).addClass( "ui-state-hover" );
+			},
+			mouseleave: function( event ) {
+				$( event.currentTarget ).removeClass( "ui-state-hover" );
+			}
+		});
+	},
+
+	_focusable: function( element ) {
+		this.focusable = this.focusable.add( element );
+		this._on( element, {
+			focusin: function( event ) {
+				$( event.currentTarget ).addClass( "ui-state-focus" );
+			},
+			focusout: function( event ) {
+				$( event.currentTarget ).removeClass( "ui-state-focus" );
+			}
+		});
+	},
+
+	_trigger: function( type, event, data ) {
+		var prop, orig,
+			callback = this.options[ type ];
+
+		data = data || {};
+		event = $.Event( event );
+		event.type = ( type === this.widgetEventPrefix ?
+			type :
+			this.widgetEventPrefix + type ).toLowerCase();
+		// the original event may come from any element
+		// so we need to reset the target on the new event
+		event.target = this.element[ 0 ];
+
+		// copy original event properties over to the new event
+		orig = event.originalEvent;
+		if ( orig ) {
+			for ( prop in orig ) {
+				if ( !( prop in event ) ) {
+					event[ prop ] = orig[ prop ];
+				}
+			}
+		}
+
+		this.element.trigger( event, data );
+		return !( $.isFunction( callback ) &&
+			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
+			event.isDefaultPrevented() );
+	}
+};
+
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
+	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
+		if ( typeof options === "string" ) {
+			options = { effect: options };
+		}
+		var hasOptions,
+			effectName = !options ?
+				method :
+				options === true || typeof options === "number" ?
+					defaultEffect :
+					options.effect || defaultEffect;
+		options = options || {};
+		if ( typeof options === "number" ) {
+			options = { duration: options };
+		}
+		hasOptions = !$.isEmptyObject( options );
+		options.complete = callback;
+		if ( options.delay ) {
+			element.delay( options.delay );
+		}
+		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
+			element[ method ]( options );
+		} else if ( effectName !== method && element[ effectName ] ) {
+			element[ effectName ]( options.duration, options.easing, callback );
+		} else {
+			element.queue(function( next ) {
+				$( this )[ method ]();
+				if ( callback ) {
+					callback.call( element[ 0 ] );
+				}
+				next();
+			});
+		}
+	};
+});
+
+var widget = $.widget;
+
+
+/*!
+ * jQuery UI Mouse 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/mouse/
+ */
+
+
+var mouseHandled = false;
+$( document ).mouseup( function() {
+	mouseHandled = false;
+});
+
+var mouse = $.widget("ui.mouse", {
+	version: "1.11.4",
+	options: {
+		cancel: "input,textarea,button,select,option",
+		distance: 1,
+		delay: 0
+	},
+	_mouseInit: function() {
+		var that = this;
+
+		this.element
+			.bind("mousedown." + this.widgetName, function(event) {
+				return that._mouseDown(event);
+			})
+			.bind("click." + this.widgetName, function(event) {
+				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
+					$.removeData(event.target, that.widgetName + ".preventClickEvent");
+					event.stopImmediatePropagation();
+					return false;
+				}
+			});
+
+		this.started = false;
+	},
+
+	// TODO: make sure destroying one instance of mouse doesn't mess with
+	// other instances of mouse
+	_mouseDestroy: function() {
+		this.element.unbind("." + this.widgetName);
+		if ( this._mouseMoveDelegate ) {
+			this.document
+				.unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
+				.unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
+		}
+	},
+
+	_mouseDown: function(event) {
+		// don't let more than one widget handle mouseStart
+		if ( mouseHandled ) {
+			return;
+		}
+
+		this._mouseMoved = false;
+
+		// we may have missed mouseup (out of window)
+		(this._mouseStarted && this._mouseUp(event));
+
+		this._mouseDownEvent = event;
+
+		var that = this,
+			btnIsLeft = (event.which === 1),
+			// event.target.nodeName works around a bug in IE 8 with
+			// disabled inputs (#7620)
+			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
+		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+			return true;
+		}
+
+		this.mouseDelayMet = !this.options.delay;
+		if (!this.mouseDelayMet) {
+			this._mouseDelayTimer = setTimeout(function() {
+				that.mouseDelayMet = true;
+			}, this.options.delay);
+		}
+
+		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+			this._mouseStarted = (this._mouseStart(event) !== false);
+			if (!this._mouseStarted) {
+				event.preventDefault();
+				return true;
+			}
+		}
+
+		// Click event may never have fired (Gecko & Opera)
+		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
+			$.removeData(event.target, this.widgetName + ".preventClickEvent");
+		}
+
+		// these delegates are required to keep context
+		this._mouseMoveDelegate = function(event) {
+			return that._mouseMove(event);
+		};
+		this._mouseUpDelegate = function(event) {
+			return that._mouseUp(event);
+		};
+
+		this.document
+			.bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
+			.bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
+
+		event.preventDefault();
+
+		mouseHandled = true;
+		return true;
+	},
+
+	_mouseMove: function(event) {
+		// Only check for mouseups outside the document if you've moved inside the document
+		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
+		// fire a mousemove event if content is placed under the cursor. See #7778
+		// Support: IE <9
+		if ( this._mouseMoved ) {
+			// IE mouseup check - mouseup happened when mouse was out of window
+			if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
+				return this._mouseUp(event);
+
+			// Iframe mouseup check - mouseup occurred in another document
+			} else if ( !event.which ) {
+				return this._mouseUp( event );
+			}
+		}
+
+		if ( event.which || event.button ) {
+			this._mouseMoved = true;
+		}
+
+		if (this._mouseStarted) {
+			this._mouseDrag(event);
+			return event.preventDefault();
+		}
+
+		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+			this._mouseStarted =
+				(this._mouseStart(this._mouseDownEvent, event) !== false);
+			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+		}
+
+		return !this._mouseStarted;
+	},
+
+	_mouseUp: function(event) {
+		this.document
+			.unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
+			.unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
+
+		if (this._mouseStarted) {
+			this._mouseStarted = false;
+
+			if (event.target === this._mouseDownEvent.target) {
+				$.data(event.target, this.widgetName + ".preventClickEvent", true);
+			}
+
+			this._mouseStop(event);
+		}
+
+		mouseHandled = false;
+		return false;
+	},
+
+	_mouseDistanceMet: function(event) {
+		return (Math.max(
+				Math.abs(this._mouseDownEvent.pageX - event.pageX),
+				Math.abs(this._mouseDownEvent.pageY - event.pageY)
+			) >= this.options.distance
+		);
+	},
+
+	_mouseDelayMet: function(/* event */) {
+		return this.mouseDelayMet;
+	},
+
+	// These are placeholder methods, to be overriden by extending plugin
+	_mouseStart: function(/* event */) {},
+	_mouseDrag: function(/* event */) {},
+	_mouseStop: function(/* event */) {},
+	_mouseCapture: function(/* event */) { return true; }
+});
+
+
+/*!
+ * jQuery UI Position 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/position/
+ */
+
+(function() {
+
+$.ui = $.ui || {};
+
+var cachedScrollbarWidth, supportsOffsetFractions,
+	max = Math.max,
+	abs = Math.abs,
+	round = Math.round,
+	rhorizontal = /left|center|right/,
+	rvertical = /top|center|bottom/,
+	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
+	rposition = /^\w+/,
+	rpercent = /%$/,
+	_position = $.fn.position;
+
+function getOffsets( offsets, width, height ) {
+	return [
+		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
+		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
+	];
+}
+
+function parseCss( element, property ) {
+	return parseInt( $.css( element, property ), 10 ) || 0;
+}
+
+function getDimensions( elem ) {
+	var raw = elem[0];
+	if ( raw.nodeType === 9 ) {
+		return {
+			width: elem.width(),
+			height: elem.height(),
+			offset: { top: 0, left: 0 }
+		};
+	}
+	if ( $.isWindow( raw ) ) {
+		return {
+			width: elem.width(),
+			height: elem.height(),
+			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
+		};
+	}
+	if ( raw.preventDefault ) {
+		return {
+			width: 0,
+			height: 0,
+			offset: { top: raw.pageY, left: raw.pageX }
+		};
+	}
+	return {
+		width: elem.outerWidth(),
+		height: elem.outerHeight(),
+		offset: elem.offset()
+	};
+}
+
+$.position = {
+	scrollbarWidth: function() {
+		if ( cachedScrollbarWidth !== undefined ) {
+			return cachedScrollbarWidth;
+		}
+		var w1, w2,
+			div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
+			innerDiv = div.children()[0];
+
+		$( "body" ).append( div );
+		w1 = innerDiv.offsetWidth;
+		div.css( "overflow", "scroll" );
+
+		w2 = innerDiv.offsetWidth;
+
+		if ( w1 === w2 ) {
+			w2 = div[0].clientWidth;
+		}
+
+		div.remove();
+
+		return (cachedScrollbarWidth = w1 - w2);
+	},
+	getScrollInfo: function( within ) {
+		var overflowX = within.isWindow || within.isDocument ? "" :
+				within.element.css( "overflow-x" ),
+			overflowY = within.isWindow || within.isDocument ? "" :
+				within.element.css( "overflow-y" ),
+			hasOverflowX = overflowX === "scroll" ||
+				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
+			hasOverflowY = overflowY === "scroll" ||
+				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
+		return {
+			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
+			height: hasOverflowX ? $.position.scrollbarWidth() : 0
+		};
+	},
+	getWithinInfo: function( element ) {
+		var withinElement = $( element || window ),
+			isWindow = $.isWindow( withinElement[0] ),
+			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
+		return {
+			element: withinElement,
+			isWindow: isWindow,
+			isDocument: isDocument,
+			offset: withinElement.offset() || { left: 0, top: 0 },
+			scrollLeft: withinElement.scrollLeft(),
+			scrollTop: withinElement.scrollTop(),
+
+			// support: jQuery 1.6.x
+			// jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
+			width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
+			height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
+		};
+	}
+};
+
+$.fn.position = function( options ) {
+	if ( !options || !options.of ) {
+		return _position.apply( this, arguments );
+	}
+
+	// make a copy, we don't want to modify arguments
+	options = $.extend( {}, options );
+
+	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
+		target = $( options.of ),
+		within = $.position.getWithinInfo( options.within ),
+		scrollInfo = $.position.getScrollInfo( within ),
+		collision = ( options.collision || "flip" ).split( " " ),
+		offsets = {};
+
+	dimensions = getDimensions( target );
+	if ( target[0].preventDefault ) {
+		// force left top to allow flipping
+		options.at = "left top";
+	}
+	targetWidth = dimensions.width;
+	targetHeight = dimensions.height;
+	targetOffset = dimensions.offset;
+	// clone to reuse original targetOffset later
+	basePosition = $.extend( {}, targetOffset );
+
+	// force my and at to have valid horizontal and vertical positions
+	// if a value is missing or invalid, it will be converted to center
+	$.each( [ "my", "at" ], function() {
+		var pos = ( options[ this ] || "" ).split( " " ),
+			horizontalOffset,
+			verticalOffset;
+
+		if ( pos.length === 1) {
+			pos = rhorizontal.test( pos[ 0 ] ) ?
+				pos.concat( [ "center" ] ) :
+				rvertical.test( pos[ 0 ] ) ?
+					[ "center" ].concat( pos ) :
+					[ "center", "center" ];
+		}
+		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
+		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
+
+		// calculate offsets
+		horizontalOffset = roffset.exec( pos[ 0 ] );
+		verticalOffset = roffset.exec( pos[ 1 ] );
+		offsets[ this ] = [
+			horizontalOffset ? horizontalOffset[ 0 ] : 0,
+			verticalOffset ? verticalOffset[ 0 ] : 0
+		];
+
+		// reduce to just the positions without the offsets
+		options[ this ] = [
+			rposition.exec( pos[ 0 ] )[ 0 ],
+			rposition.exec( pos[ 1 ] )[ 0 ]
+		];
+	});
+
+	// normalize collision option
+	if ( collision.length === 1 ) {
+		collision[ 1 ] = collision[ 0 ];
+	}
+
+	if ( options.at[ 0 ] === "right" ) {
+		basePosition.left += targetWidth;
+	} else if ( options.at[ 0 ] === "center" ) {
+		basePosition.left += targetWidth / 2;
+	}
+
+	if ( options.at[ 1 ] === "bottom" ) {
+		basePosition.top += targetHeight;
+	} else if ( options.at[ 1 ] === "center" ) {
+		basePosition.top += targetHeight / 2;
+	}
+
+	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
+	basePosition.left += atOffset[ 0 ];
+	basePosition.top += atOffset[ 1 ];
+
+	return this.each(function() {
+		var collisionPosition, using,
+			elem = $( this ),
+			elemWidth = elem.outerWidth(),
+			elemHeight = elem.outerHeight(),
+			marginLeft = parseCss( this, "marginLeft" ),
+			marginTop = parseCss( this, "marginTop" ),
+			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
+			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
+			position = $.extend( {}, basePosition ),
+			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
+
+		if ( options.my[ 0 ] === "right" ) {
+			position.left -= elemWidth;
+		} else if ( options.my[ 0 ] === "center" ) {
+			position.left -= elemWidth / 2;
+		}
+
+		if ( options.my[ 1 ] === "bottom" ) {
+			position.top -= elemHeight;
+		} else if ( options.my[ 1 ] === "center" ) {
+			position.top -= elemHeight / 2;
+		}
+
+		position.left += myOffset[ 0 ];
+		position.top += myOffset[ 1 ];
+
+		// if the browser doesn't support fractions, then round for consistent results
+		if ( !supportsOffsetFractions ) {
+			position.left = round( position.left );
+			position.top = round( position.top );
+		}
+
+		collisionPosition = {
+			marginLeft: marginLeft,
+			marginTop: marginTop
+		};
+
+		$.each( [ "left", "top" ], function( i, dir ) {
+			if ( $.ui.position[ collision[ i ] ] ) {
+				$.ui.position[ collision[ i ] ][ dir ]( position, {
+					targetWidth: targetWidth,
+					targetHeight: targetHeight,
+					elemWidth: elemWidth,
+					elemHeight: elemHeight,
+					collisionPosition: collisionPosition,
+					collisionWidth: collisionWidth,
+					collisionHeight: collisionHeight,
+					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
+					my: options.my,
+					at: options.at,
+					within: within,
+					elem: elem
+				});
+			}
+		});
+
+		if ( options.using ) {
+			// adds feedback as second argument to using callback, if present
+			using = function( props ) {
+				var left = targetOffset.left - position.left,
+					right = left + targetWidth - elemWidth,
+					top = targetOffset.top - position.top,
+					bottom = top + targetHeight - elemHeight,
+					feedback = {
+						target: {
+							element: target,
+							left: targetOffset.left,
+							top: targetOffset.top,
+							width: targetWidth,
+							height: targetHeight
+						},
+						element: {
+							element: elem,
+							left: position.left,
+							top: position.top,
+							width: elemWidth,
+							height: elemHeight
+						},
+						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
+						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
+					};
+				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
+					feedback.horizontal = "center";
+				}
+				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
+					feedback.vertical = "middle";
+				}
+				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
+					feedback.important = "horizontal";
+				} else {
+					feedback.important = "vertical";
+				}
+				options.using.call( this, props, feedback );
+			};
+		}
+
+		elem.offset( $.extend( position, { using: using } ) );
+	});
+};
+
+$.ui.position = {
+	fit: {
+		left: function( position, data ) {
+			var within = data.within,
+				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
+				outerWidth = within.width,
+				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+				overLeft = withinOffset - collisionPosLeft,
+				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
+				newOverRight;
+
+			// element is wider than within
+			if ( data.collisionWidth > outerWidth ) {
+				// element is initially over the left side of within
+				if ( overLeft > 0 && overRight <= 0 ) {
+					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
+					position.left += overLeft - newOverRight;
+				// element is initially over right side of within
+				} else if ( overRight > 0 && overLeft <= 0 ) {
+					position.left = withinOffset;
+				// element is initially over both left and right sides of within
+				} else {
+					if ( overLeft > overRight ) {
+						position.left = withinOffset + outerWidth - data.collisionWidth;
+					} else {
+						position.left = withinOffset;
+					}
+				}
+			// too far left -> align with left edge
+			} else if ( overLeft > 0 ) {
+				position.left += overLeft;
+			// too far right -> align with right edge
+			} else if ( overRight > 0 ) {
+				position.left -= overRight;
+			// adjust based on position and margin
+			} else {
+				position.left = max( position.left - collisionPosLeft, position.left );
+			}
+		},
+		top: function( position, data ) {
+			var within = data.within,
+				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
+				outerHeight = data.within.height,
+				collisionPosTop = position.top - data.collisionPosition.marginTop,
+				overTop = withinOffset - collisionPosTop,
+				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
+				newOverBottom;
+
+			// element is taller than within
+			if ( data.collisionHeight > outerHeight ) {
+				// element is initially over the top of within
+				if ( overTop > 0 && overBottom <= 0 ) {
+					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
+					position.top += overTop - newOverBottom;
+				// element is initially over bottom of within
+				} else if ( overBottom > 0 && overTop <= 0 ) {
+					position.top = withinOffset;
+				// element is initially over both top and bottom of within
+				} else {
+					if ( overTop > overBottom ) {
+						position.top = withinOffset + outerHeight - data.collisionHeight;
+					} else {
+						position.top = withinOffset;
+					}
+				}
+			// too far up -> align with top
+			} else if ( overTop > 0 ) {
+				position.top += overTop;
+			// too far down -> align with bottom edge
+			} else if ( overBottom > 0 ) {
+				position.top -= overBottom;
+			// adjust based on position and margin
+			} else {
+				position.top = max( position.top - collisionPosTop, position.top );
+			}
+		}
+	},
+	flip: {
+		left: function( position, data ) {
+			var within = data.within,
+				withinOffset = within.offset.left + within.scrollLeft,
+				outerWidth = within.width,
+				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
+				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+				overLeft = collisionPosLeft - offsetLeft,
+				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
+				myOffset = data.my[ 0 ] === "left" ?
+					-data.elemWidth :
+					data.my[ 0 ] === "right" ?
+						data.elemWidth :
+						0,
+				atOffset = data.at[ 0 ] === "left" ?
+					data.targetWidth :
+					data.at[ 0 ] === "right" ?
+						-data.targetWidth :
+						0,
+				offset = -2 * data.offset[ 0 ],
+				newOverRight,
+				newOverLeft;
+
+			if ( overLeft < 0 ) {
+				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
+				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
+					position.left += myOffset + atOffset + offset;
+				}
+			} else if ( overRight > 0 ) {
+				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
+				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
+					position.left += myOffset + atOffset + offset;
+				}
+			}
+		},
+		top: function( position, data ) {
+			var within = data.within,
+				withinOffset = within.offset.top + within.scrollTop,
+				outerHeight = within.height,
+				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
+				collisionPosTop = position.top - data.collisionPosition.marginTop,
+				overTop = collisionPosTop - offsetTop,
+				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
+				top = data.my[ 1 ] === "top",
+				myOffset = top ?
+					-data.elemHeight :
+					data.my[ 1 ] === "bottom" ?
+						data.elemHeight :
+						0,
+				atOffset = data.at[ 1 ] === "top" ?
+					data.targetHeight :
+					data.at[ 1 ] === "bottom" ?
+						-data.targetHeight :
+						0,
+				offset = -2 * data.offset[ 1 ],
+				newOverTop,
+				newOverBottom;
+			if ( overTop < 0 ) {
+				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
+				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
+					position.top += myOffset + atOffset + offset;
+				}
+			} else if ( overBottom > 0 ) {
+				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
+				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
+					position.top += myOffset + atOffset + offset;
+				}
+			}
+		}
+	},
+	flipfit: {
+		left: function() {
+			$.ui.position.flip.left.apply( this, arguments );
+			$.ui.position.fit.left.apply( this, arguments );
+		},
+		top: function() {
+			$.ui.position.flip.top.apply( this, arguments );
+			$.ui.position.fit.top.apply( this, arguments );
+		}
+	}
+};
+
+// fraction support test
+(function() {
+	var testElement, testElementParent, testElementStyle, offsetLeft, i,
+		body = document.getElementsByTagName( "body" )[ 0 ],
+		div = document.createElement( "div" );
+
+	//Create a "fake body" for testing based on method used in jQuery.support
+	testElement = document.createElement( body ? "div" : "body" );
+	testElementStyle = {
+		visibility: "hidden",
+		width: 0,
+		height: 0,
+		border: 0,
+		margin: 0,
+		background: "none"
+	};
+	if ( body ) {
+		$.extend( testElementStyle, {
+			position: "absolute",
+			left: "-1000px",
+			top: "-1000px"
+		});
+	}
+	for ( i in testElementStyle ) {
+		testElement.style[ i ] = testElementStyle[ i ];
+	}
+	testElement.appendChild( div );
+	testElementParent = body || document.documentElement;
+	testElementParent.insertBefore( testElement, testElementParent.firstChild );
+
+	div.style.cssText = "position: absolute; left: 10.7432222px;";
+
+	offsetLeft = $( div ).offset().left;
+	supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
+
+	testElement.innerHTML = "";
+	testElementParent.removeChild( testElement );
+})();
+
+})();
+
+var position = $.ui.position;
+
+
+/*!
+ * jQuery UI Accordion 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/accordion/
+ */
+
+
+var accordion = $.widget( "ui.accordion", {
+	version: "1.11.4",
+	options: {
+		active: 0,
+		animate: {},
+		collapsible: false,
+		event: "click",
+		header: "> li > :first-child,> :not(li):even",
+		heightStyle: "auto",
+		icons: {
+			activeHeader: "ui-icon-triangle-1-s",
+			header: "ui-icon-triangle-1-e"
+		},
+
+		// callbacks
+		activate: null,
+		beforeActivate: null
+	},
+
+	hideProps: {
+		borderTopWidth: "hide",
+		borderBottomWidth: "hide",
+		paddingTop: "hide",
+		paddingBottom: "hide",
+		height: "hide"
+	},
+
+	showProps: {
+		borderTopWidth: "show",
+		borderBottomWidth: "show",
+		paddingTop: "show",
+		paddingBottom: "show",
+		height: "show"
+	},
+
+	_create: function() {
+		var options = this.options;
+		this.prevShow = this.prevHide = $();
+		this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
+			// ARIA
+			.attr( "role", "tablist" );
+
+		// don't allow collapsible: false and active: false / null
+		if ( !options.collapsible && (options.active === false || options.active == null) ) {
+			options.active = 0;
+		}
+
+		this._processPanels();
+		// handle negative values
+		if ( options.active < 0 ) {
+			options.active += this.headers.length;
+		}
+		this._refresh();
+	},
+
+	_getCreateEventData: function() {
+		return {
+			header: this.active,
+			panel: !this.active.length ? $() : this.active.next()
+		};
+	},
+
+	_createIcons: function() {
+		var icons = this.options.icons;
+		if ( icons ) {
+			$( "<span>" )
+				.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
+				.prependTo( this.headers );
+			this.active.children( ".ui-accordion-header-icon" )
+				.removeClass( icons.header )
+				.addClass( icons.activeHeader );
+			this.headers.addClass( "ui-accordion-icons" );
+		}
+	},
+
+	_destroyIcons: function() {
+		this.headers
+			.removeClass( "ui-accordion-icons" )
+			.children( ".ui-accordion-header-icon" )
+				.remove();
+	},
+
+	_destroy: function() {
+		var contents;
+
+		// clean up main element
+		this.element
+			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
+			.removeAttr( "role" );
+
+		// clean up headers
+		this.headers
+			.removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
+				"ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
+			.removeAttr( "role" )
+			.removeAttr( "aria-expanded" )
+			.removeAttr( "aria-selected" )
+			.removeAttr( "aria-controls" )
+			.removeAttr( "tabIndex" )
+			.removeUniqueId();
+
+		this._destroyIcons();
+
+		// clean up content panels
+		contents = this.headers.next()
+			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
+				"ui-accordion-content ui-accordion-content-active ui-state-disabled" )
+			.css( "display", "" )
+			.removeAttr( "role" )
+			.removeAttr( "aria-hidden" )
+			.removeAttr( "aria-labelledby" )
+			.removeUniqueId();
+
+		if ( this.options.heightStyle !== "content" ) {
+			contents.css( "height", "" );
+		}
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "active" ) {
+			// _activate() will handle invalid values and update this.options
+			this._activate( value );
+			return;
+		}
+
+		if ( key === "event" ) {
+			if ( this.options.event ) {
+				this._off( this.headers, this.options.event );
+			}
+			this._setupEvents( value );
+		}
+
+		this._super( key, value );
+
+		// setting collapsible: false while collapsed; open first panel
+		if ( key === "collapsible" && !value && this.options.active === false ) {
+			this._activate( 0 );
+		}
+
+		if ( key === "icons" ) {
+			this._destroyIcons();
+			if ( value ) {
+				this._createIcons();
+			}
+		}
+
+		// #5332 - opacity doesn't cascade to positioned elements in IE
+		// so we need to add the disabled class to the headers and panels
+		if ( key === "disabled" ) {
+			this.element
+				.toggleClass( "ui-state-disabled", !!value )
+				.attr( "aria-disabled", value );
+			this.headers.add( this.headers.next() )
+				.toggleClass( "ui-state-disabled", !!value );
+		}
+	},
+
+	_keydown: function( event ) {
+		if ( event.altKey || event.ctrlKey ) {
+			return;
+		}
+
+		var keyCode = $.ui.keyCode,
+			length = this.headers.length,
+			currentIndex = this.headers.index( event.target ),
+			toFocus = false;
+
+		switch ( event.keyCode ) {
+			case keyCode.RIGHT:
+			case keyCode.DOWN:
+				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
+				break;
+			case keyCode.LEFT:
+			case keyCode.UP:
+				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
+				break;
+			case keyCode.SPACE:
+			case keyCode.ENTER:
+				this._eventHandler( event );
+				break;
+			case keyCode.HOME:
+				toFocus = this.headers[ 0 ];
+				break;
+			case keyCode.END:
+				toFocus = this.headers[ length - 1 ];
+				break;
+		}
+
+		if ( toFocus ) {
+			$( event.target ).attr( "tabIndex", -1 );
+			$( toFocus ).attr( "tabIndex", 0 );
+			toFocus.focus();
+			event.preventDefault();
+		}
+	},
+
+	_panelKeyDown: function( event ) {
+		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
+			$( event.currentTarget ).prev().focus();
+		}
+	},
+
+	refresh: function() {
+		var options = this.options;
+		this._processPanels();
+
+		// was collapsed or no panel
+		if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
+			options.active = false;
+			this.active = $();
+		// active false only when collapsible is true
+		} else if ( options.active === false ) {
+			this._activate( 0 );
+		// was active, but active panel is gone
+		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
+			// all remaining panel are disabled
+			if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
+				options.active = false;
+				this.active = $();
+			// activate previous panel
+			} else {
+				this._activate( Math.max( 0, options.active - 1 ) );
+			}
+		// was active, active panel still exists
+		} else {
+			// make sure active index is correct
+			options.active = this.headers.index( this.active );
+		}
+
+		this._destroyIcons();
+
+		this._refresh();
+	},
+
+	_processPanels: function() {
+		var prevHeaders = this.headers,
+			prevPanels = this.panels;
+
+		this.headers = this.element.find( this.options.header )
+			.addClass( "ui-accordion-header ui-state-default ui-corner-all" );
+
+		this.panels = this.headers.next()
+			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
+			.filter( ":not(.ui-accordion-content-active)" )
+			.hide();
+
+		// Avoid memory leaks (#10056)
+		if ( prevPanels ) {
+			this._off( prevHeaders.not( this.headers ) );
+			this._off( prevPanels.not( this.panels ) );
+		}
+	},
+
+	_refresh: function() {
+		var maxHeight,
+			options = this.options,
+			heightStyle = options.heightStyle,
+			parent = this.element.parent();
+
+		this.active = this._findActive( options.active )
+			.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
+			.removeClass( "ui-corner-all" );
+		this.active.next()
+			.addClass( "ui-accordion-content-active" )
+			.show();
+
+		this.headers
+			.attr( "role", "tab" )
+			.each(function() {
+				var header = $( this ),
+					headerId = header.uniqueId().attr( "id" ),
+					panel = header.next(),
+					panelId = panel.uniqueId().attr( "id" );
+				header.attr( "aria-controls", panelId );
+				panel.attr( "aria-labelledby", headerId );
+			})
+			.next()
+				.attr( "role", "tabpanel" );
+
+		this.headers
+			.not( this.active )
+			.attr({
+				"aria-selected": "false",
+				"aria-expanded": "false",
+				tabIndex: -1
+			})
+			.next()
+				.attr({
+					"aria-hidden": "true"
+				})
+				.hide();
+
+		// make sure at least one header is in the tab order
+		if ( !this.active.length ) {
+			this.headers.eq( 0 ).attr( "tabIndex", 0 );
+		} else {
+			this.active.attr({
+				"aria-selected": "true",
+				"aria-expanded": "true",
+				tabIndex: 0
+			})
+			.next()
+				.attr({
+					"aria-hidden": "false"
+				});
+		}
+
+		this._createIcons();
+
+		this._setupEvents( options.event );
+
+		if ( heightStyle === "fill" ) {
+			maxHeight = parent.height();
+			this.element.siblings( ":visible" ).each(function() {
+				var elem = $( this ),
+					position = elem.css( "position" );
+
+				if ( position === "absolute" || position === "fixed" ) {
+					return;
+				}
+				maxHeight -= elem.outerHeight( true );
+			});
+
+			this.headers.each(function() {
+				maxHeight -= $( this ).outerHeight( true );
+			});
+
+			this.headers.next()
+				.each(function() {
+					$( this ).height( Math.max( 0, maxHeight -
+						$( this ).innerHeight() + $( this ).height() ) );
+				})
+				.css( "overflow", "auto" );
+		} else if ( heightStyle === "auto" ) {
+			maxHeight = 0;
+			this.headers.next()
+				.each(function() {
+					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
+				})
+				.height( maxHeight );
+		}
+	},
+
+	_activate: function( index ) {
+		var active = this._findActive( index )[ 0 ];
+
+		// trying to activate the already active panel
+		if ( active === this.active[ 0 ] ) {
+			return;
+		}
+
+		// trying to collapse, simulate a click on the currently active header
+		active = active || this.active[ 0 ];
+
+		this._eventHandler({
+			target: active,
+			currentTarget: active,
+			preventDefault: $.noop
+		});
+	},
+
+	_findActive: function( selector ) {
+		return typeof selector === "number" ? this.headers.eq( selector ) : $();
+	},
+
+	_setupEvents: function( event ) {
+		var events = {
+			keydown: "_keydown"
+		};
+		if ( event ) {
+			$.each( event.split( " " ), function( index, eventName ) {
+				events[ eventName ] = "_eventHandler";
+			});
+		}
+
+		this._off( this.headers.add( this.headers.next() ) );
+		this._on( this.headers, events );
+		this._on( this.headers.next(), { keydown: "_panelKeyDown" });
+		this._hoverable( this.headers );
+		this._focusable( this.headers );
+	},
+
+	_eventHandler: function( event ) {
+		var options = this.options,
+			active = this.active,
+			clicked = $( event.currentTarget ),
+			clickedIsActive = clicked[ 0 ] === active[ 0 ],
+			collapsing = clickedIsActive && options.collapsible,
+			toShow = collapsing ? $() : clicked.next(),
+			toHide = active.next(),
+			eventData = {
+				oldHeader: active,
+				oldPanel: toHide,
+				newHeader: collapsing ? $() : clicked,
+				newPanel: toShow
+			};
+
+		event.preventDefault();
+
+		if (
+				// click on active header, but not collapsible
+				( clickedIsActive && !options.collapsible ) ||
+				// allow canceling activation
+				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
+			return;
+		}
+
+		options.active = collapsing ? false : this.headers.index( clicked );
+
+		// when the call to ._toggle() comes after the class changes
+		// it causes a very odd bug in IE 8 (see #6720)
+		this.active = clickedIsActive ? $() : clicked;
+		this._toggle( eventData );
+
+		// switch classes
+		// corner classes on the previously active header stay after the animation
+		active.removeClass( "ui-accordion-header-active ui-state-active" );
+		if ( options.icons ) {
+			active.children( ".ui-accordion-header-icon" )
+				.removeClass( options.icons.activeHeader )
+				.addClass( options.icons.header );
+		}
+
+		if ( !clickedIsActive ) {
+			clicked
+				.removeClass( "ui-corner-all" )
+				.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
+			if ( options.icons ) {
+				clicked.children( ".ui-accordion-header-icon" )
+					.removeClass( options.icons.header )
+					.addClass( options.icons.activeHeader );
+			}
+
+			clicked
+				.next()
+				.addClass( "ui-accordion-content-active" );
+		}
+	},
+
+	_toggle: function( data ) {
+		var toShow = data.newPanel,
+			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
+
+		// handle activating a panel during the animation for another activation
+		this.prevShow.add( this.prevHide ).stop( true, true );
+		this.prevShow = toShow;
+		this.prevHide = toHide;
+
+		if ( this.options.animate ) {
+			this._animate( toShow, toHide, data );
+		} else {
+			toHide.hide();
+			toShow.show();
+			this._toggleComplete( data );
+		}
+
+		toHide.attr({
+			"aria-hidden": "true"
+		});
+		toHide.prev().attr({
+			"aria-selected": "false",
+			"aria-expanded": "false"
+		});
+		// if we're switching panels, remove the old header from the tab order
+		// if we're opening from collapsed state, remove the previous header from the tab order
+		// if we're collapsing, then keep the collapsing header in the tab order
+		if ( toShow.length && toHide.length ) {
+			toHide.prev().attr({
+				"tabIndex": -1,
+				"aria-expanded": "false"
+			});
+		} else if ( toShow.length ) {
+			this.headers.filter(function() {
+				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
+			})
+			.attr( "tabIndex", -1 );
+		}
+
+		toShow
+			.attr( "aria-hidden", "false" )
+			.prev()
+				.attr({
+					"aria-selected": "true",
+					"aria-expanded": "true",
+					tabIndex: 0
+				});
+	},
+
+	_animate: function( toShow, toHide, data ) {
+		var total, easing, duration,
+			that = this,
+			adjust = 0,
+			boxSizing = toShow.css( "box-sizing" ),
+			down = toShow.length &&
+				( !toHide.length || ( toShow.index() < toHide.index() ) ),
+			animate = this.options.animate || {},
+			options = down && animate.down || animate,
+			complete = function() {
+				that._toggleComplete( data );
+			};
+
+		if ( typeof options === "number" ) {
+			duration = options;
+		}
+		if ( typeof options === "string" ) {
+			easing = options;
+		}
+		// fall back from options to animation in case of partial down settings
+		easing = easing || options.easing || animate.easing;
+		duration = duration || options.duration || animate.duration;
+
+		if ( !toHide.length ) {
+			return toShow.animate( this.showProps, duration, easing, complete );
+		}
+		if ( !toShow.length ) {
+			return toHide.animate( this.hideProps, duration, easing, complete );
+		}
+
+		total = toShow.show().outerHeight();
+		toHide.animate( this.hideProps, {
+			duration: duration,
+			easing: easing,
+			step: function( now, fx ) {
+				fx.now = Math.round( now );
+			}
+		});
+		toShow
+			.hide()
+			.animate( this.showProps, {
+				duration: duration,
+				easing: easing,
+				complete: complete,
+				step: function( now, fx ) {
+					fx.now = Math.round( now );
+					if ( fx.prop !== "height" ) {
+						if ( boxSizing === "content-box" ) {
+							adjust += fx.now;
+						}
+					} else if ( that.options.heightStyle !== "content" ) {
+						fx.now = Math.round( total - toHide.outerHeight() - adjust );
+						adjust = 0;
+					}
+				}
+			});
+	},
+
+	_toggleComplete: function( data ) {
+		var toHide = data.oldPanel;
+
+		toHide
+			.removeClass( "ui-accordion-content-active" )
+			.prev()
+				.removeClass( "ui-corner-top" )
+				.addClass( "ui-corner-all" );
+
+		// Work around for rendering bug in IE (#5421)
+		if ( toHide.length ) {
+			toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
+		}
+		this._trigger( "activate", null, data );
+	}
+});
+
+
+/*!
+ * jQuery UI Menu 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/menu/
+ */
+
+
+var menu = $.widget( "ui.menu", {
+	version: "1.11.4",
+	defaultElement: "<ul>",
+	delay: 300,
+	options: {
+		icons: {
+			submenu: "ui-icon-carat-1-e"
+		},
+		items: "> *",
+		menus: "ul",
+		position: {
+			my: "left-1 top",
+			at: "right top"
+		},
+		role: "menu",
+
+		// callbacks
+		blur: null,
+		focus: null,
+		select: null
+	},
+
+	_create: function() {
+		this.activeMenu = this.element;
+
+		// Flag used to prevent firing of the click handler
+		// as the event bubbles up through nested menus
+		this.mouseHandled = false;
+		this.element
+			.uniqueId()
+			.addClass( "ui-menu ui-widget ui-widget-content" )
+			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
+			.attr({
+				role: this.options.role,
+				tabIndex: 0
+			});
+
+		if ( this.options.disabled ) {
+			this.element
+				.addClass( "ui-state-disabled" )
+				.attr( "aria-disabled", "true" );
+		}
+
+		this._on({
+			// Prevent focus from sticking to links inside menu after clicking
+			// them (focus should always stay on UL during navigation).
+			"mousedown .ui-menu-item": function( event ) {
+				event.preventDefault();
+			},
+			"click .ui-menu-item": function( event ) {
+				var target = $( event.target );
+				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
+					this.select( event );
+
+					// Only set the mouseHandled flag if the event will bubble, see #9469.
+					if ( !event.isPropagationStopped() ) {
+						this.mouseHandled = true;
+					}
+
+					// Open submenu on click
+					if ( target.has( ".ui-menu" ).length ) {
+						this.expand( event );
+					} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
+
+						// Redirect focus to the menu
+						this.element.trigger( "focus", [ true ] );
+
+						// If the active item is on the top level, let it stay active.
+						// Otherwise, blur the active item since it is no longer visible.
+						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
+							clearTimeout( this.timer );
+						}
+					}
+				}
+			},
+			"mouseenter .ui-menu-item": function( event ) {
+				// Ignore mouse events while typeahead is active, see #10458.
+				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
+				// is over an item in the menu
+				if ( this.previousFilter ) {
+					return;
+				}
+				var target = $( event.currentTarget );
+				// Remove ui-state-active class from siblings of the newly focused menu item
+				// to avoid a jump caused by adjacent elements both having a class with a border
+				target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
+				this.focus( event, target );
+			},
+			mouseleave: "collapseAll",
+			"mouseleave .ui-menu": "collapseAll",
+			focus: function( event, keepActiveItem ) {
+				// If there's already an active item, keep it active
+				// If not, activate the first item
+				var item = this.active || this.element.find( this.options.items ).eq( 0 );
+
+				if ( !keepActiveItem ) {
+					this.focus( event, item );
+				}
+			},
+			blur: function( event ) {
+				this._delay(function() {
+					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
+						this.collapseAll( event );
+					}
+				});
+			},
+			keydown: "_keydown"
+		});
+
+		this.refresh();
+
+		// Clicks outside of a menu collapse any open menus
+		this._on( this.document, {
+			click: function( event ) {
+				if ( this._closeOnDocumentClick( event ) ) {
+					this.collapseAll( event );
+				}
+
+				// Reset the mouseHandled flag
+				this.mouseHandled = false;
+			}
+		});
+	},
+
+	_destroy: function() {
+		// Destroy (sub)menus
+		this.element
+			.removeAttr( "aria-activedescendant" )
+			.find( ".ui-menu" ).addBack()
+				.removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
+				.removeAttr( "role" )
+				.removeAttr( "tabIndex" )
+				.removeAttr( "aria-labelledby" )
+				.removeAttr( "aria-expanded" )
+				.removeAttr( "aria-hidden" )
+				.removeAttr( "aria-disabled" )
+				.removeUniqueId()
+				.show();
+
+		// Destroy menu items
+		this.element.find( ".ui-menu-item" )
+			.removeClass( "ui-menu-item" )
+			.removeAttr( "role" )
+			.removeAttr( "aria-disabled" )
+			.removeUniqueId()
+			.removeClass( "ui-state-hover" )
+			.removeAttr( "tabIndex" )
+			.removeAttr( "role" )
+			.removeAttr( "aria-haspopup" )
+			.children().each( function() {
+				var elem = $( this );
+				if ( elem.data( "ui-menu-submenu-carat" ) ) {
+					elem.remove();
+				}
+			});
+
+		// Destroy menu dividers
+		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
+	},
+
+	_keydown: function( event ) {
+		var match, prev, character, skip,
+			preventDefault = true;
+
+		switch ( event.keyCode ) {
+		case $.ui.keyCode.PAGE_UP:
+			this.previousPage( event );
+			break;
+		case $.ui.keyCode.PAGE_DOWN:
+			this.nextPage( event );
+			break;
+		case $.ui.keyCode.HOME:
+			this._move( "first", "first", event );
+			break;
+		case $.ui.keyCode.END:
+			this._move( "last", "last", event );
+			break;
+		case $.ui.keyCode.UP:
+			this.previous( event );
+			break;
+		case $.ui.keyCode.DOWN:
+			this.next( event );
+			break;
+		case $.ui.keyCode.LEFT:
+			this.collapse( event );
+			break;
+		case $.ui.keyCode.RIGHT:
+			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
+				this.expand( event );
+			}
+			break;
+		case $.ui.keyCode.ENTER:
+		case $.ui.keyCode.SPACE:
+			this._activate( event );
+			break;
+		case $.ui.keyCode.ESCAPE:
+			this.collapse( event );
+			break;
+		default:
+			preventDefault = false;
+			prev = this.previousFilter || "";
+			character = String.fromCharCode( event.keyCode );
+			skip = false;
+
+			clearTimeout( this.filterTimer );
+
+			if ( character === prev ) {
+				skip = true;
+			} else {
+				character = prev + character;
+			}
+
+			match = this._filterMenuItems( character );
+			match = skip && match.index( this.active.next() ) !== -1 ?
+				this.active.nextAll( ".ui-menu-item" ) :
+				match;
+
+			// If no matches on the current filter, reset to the last character pressed
+			// to move down the menu to the first item that starts with that character
+			if ( !match.length ) {
+				character = String.fromCharCode( event.keyCode );
+				match = this._filterMenuItems( character );
+			}
+
+			if ( match.length ) {
+				this.focus( event, match );
+				this.previousFilter = character;
+				this.filterTimer = this._delay(function() {
+					delete this.previousFilter;
+				}, 1000 );
+			} else {
+				delete this.previousFilter;
+			}
+		}
+
+		if ( preventDefault ) {
+			event.preventDefault();
+		}
+	},
+
+	_activate: function( event ) {
+		if ( !this.active.is( ".ui-state-disabled" ) ) {
+			if ( this.active.is( "[aria-haspopup='true']" ) ) {
+				this.expand( event );
+			} else {
+				this.select( event );
+			}
+		}
+	},
+
+	refresh: function() {
+		var menus, items,
+			that = this,
+			icon = this.options.icons.submenu,
+			submenus = this.element.find( this.options.menus );
+
+		this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
+
+		// Initialize nested menus
+		submenus.filter( ":not(.ui-menu)" )
+			.addClass( "ui-menu ui-widget ui-widget-content ui-front" )
+			.hide()
+			.attr({
+				role: this.options.role,
+				"aria-hidden": "true",
+				"aria-expanded": "false"
+			})
+			.each(function() {
+				var menu = $( this ),
+					item = menu.parent(),
+					submenuCarat = $( "<span>" )
+						.addClass( "ui-menu-icon ui-icon " + icon )
+						.data( "ui-menu-submenu-carat", true );
+
+				item
+					.attr( "aria-haspopup", "true" )
+					.prepend( submenuCarat );
+				menu.attr( "aria-labelledby", item.attr( "id" ) );
+			});
+
+		menus = submenus.add( this.element );
+		items = menus.find( this.options.items );
+
+		// Initialize menu-items containing spaces and/or dashes only as dividers
+		items.not( ".ui-menu-item" ).each(function() {
+			var item = $( this );
+			if ( that._isDivider( item ) ) {
+				item.addClass( "ui-widget-content ui-menu-divider" );
+			}
+		});
+
+		// Don't refresh list items that are already adapted
+		items.not( ".ui-menu-item, .ui-menu-divider" )
+			.addClass( "ui-menu-item" )
+			.uniqueId()
+			.attr({
+				tabIndex: -1,
+				role: this._itemRole()
+			});
+
+		// Add aria-disabled attribute to any disabled menu item
+		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
+
+		// If the active item has been removed, blur the menu
+		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
+			this.blur();
+		}
+	},
+
+	_itemRole: function() {
+		return {
+			menu: "menuitem",
+			listbox: "option"
+		}[ this.options.role ];
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "icons" ) {
+			this.element.find( ".ui-menu-icon" )
+				.removeClass( this.options.icons.submenu )
+				.addClass( value.submenu );
+		}
+		if ( key === "disabled" ) {
+			this.element
+				.toggleClass( "ui-state-disabled", !!value )
+				.attr( "aria-disabled", value );
+		}
+		this._super( key, value );
+	},
+
+	focus: function( event, item ) {
+		var nested, focused;
+		this.blur( event, event && event.type === "focus" );
+
+		this._scrollIntoView( item );
+
+		this.active = item.first();
+		focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
+		// Only update aria-activedescendant if there's a role
+		// otherwise we assume focus is managed elsewhere
+		if ( this.options.role ) {
+			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
+		}
+
+		// Highlight active parent menu item, if any
+		this.active
+			.parent()
+			.closest( ".ui-menu-item" )
+			.addClass( "ui-state-active" );
+
+		if ( event && event.type === "keydown" ) {
+			this._close();
+		} else {
+			this.timer = this._delay(function() {
+				this._close();
+			}, this.delay );
+		}
+
+		nested = item.children( ".ui-menu" );
+		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
+			this._startOpening(nested);
+		}
+		this.activeMenu = item.parent();
+
+		this._trigger( "focus", event, { item: item } );
+	},
+
+	_scrollIntoView: function( item ) {
+		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
+		if ( this._hasScroll() ) {
+			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
+			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
+			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
+			scroll = this.activeMenu.scrollTop();
+			elementHeight = this.activeMenu.height();
+			itemHeight = item.outerHeight();
+
+			if ( offset < 0 ) {
+				this.activeMenu.scrollTop( scroll + offset );
+			} else if ( offset + itemHeight > elementHeight ) {
+				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
+			}
+		}
+	},
+
+	blur: function( event, fromFocus ) {
+		if ( !fromFocus ) {
+			clearTimeout( this.timer );
+		}
+
+		if ( !this.active ) {
+			return;
+		}
+
+		this.active.removeClass( "ui-state-focus" );
+		this.active = null;
+
+		this._trigger( "blur", event, { item: this.active } );
+	},
+
+	_startOpening: function( submenu ) {
+		clearTimeout( this.timer );
+
+		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
+		// shift in the submenu position when mousing over the carat icon
+		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
+			return;
+		}
+
+		this.timer = this._delay(function() {
+			this._close();
+			this._open( submenu );
+		}, this.delay );
+	},
+
+	_open: function( submenu ) {
+		var position = $.extend({
+			of: this.active
+		}, this.options.position );
+
+		clearTimeout( this.timer );
+		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
+			.hide()
+			.attr( "aria-hidden", "true" );
+
+		submenu
+			.show()
+			.removeAttr( "aria-hidden" )
+			.attr( "aria-expanded", "true" )
+			.position( position );
+	},
+
+	collapseAll: function( event, all ) {
+		clearTimeout( this.timer );
+		this.timer = this._delay(function() {
+			// If we were passed an event, look for the submenu that contains the event
+			var currentMenu = all ? this.element :
+				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
+
+			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
+			if ( !currentMenu.length ) {
+				currentMenu = this.element;
+			}
+
+			this._close( currentMenu );
+
+			this.blur( event );
+			this.activeMenu = currentMenu;
+		}, this.delay );
+	},
+
+	// With no arguments, closes the currently active menu - if nothing is active
+	// it closes all menus.  If passed an argument, it will search for menus BELOW
+	_close: function( startMenu ) {
+		if ( !startMenu ) {
+			startMenu = this.active ? this.active.parent() : this.element;
+		}
+
+		startMenu
+			.find( ".ui-menu" )
+				.hide()
+				.attr( "aria-hidden", "true" )
+				.attr( "aria-expanded", "false" )
+			.end()
+			.find( ".ui-state-active" ).not( ".ui-state-focus" )
+				.removeClass( "ui-state-active" );
+	},
+
+	_closeOnDocumentClick: function( event ) {
+		return !$( event.target ).closest( ".ui-menu" ).length;
+	},
+
+	_isDivider: function( item ) {
+
+		// Match hyphen, em dash, en dash
+		return !/[^\-\u2014\u2013\s]/.test( item.text() );
+	},
+
+	collapse: function( event ) {
+		var newItem = this.active &&
+			this.active.parent().closest( ".ui-menu-item", this.element );
+		if ( newItem && newItem.length ) {
+			this._close();
+			this.focus( event, newItem );
+		}
+	},
+
+	expand: function( event ) {
+		var newItem = this.active &&
+			this.active
+				.children( ".ui-menu " )
+				.find( this.options.items )
+				.first();
+
+		if ( newItem && newItem.length ) {
+			this._open( newItem.parent() );
+
+			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
+			this._delay(function() {
+				this.focus( event, newItem );
+			});
+		}
+	},
+
+	next: function( event ) {
+		this._move( "next", "first", event );
+	},
+
+	previous: function( event ) {
+		this._move( "prev", "last", event );
+	},
+
+	isFirstItem: function() {
+		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
+	},
+
+	isLastItem: function() {
+		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
+	},
+
+	_move: function( direction, filter, event ) {
+		var next;
+		if ( this.active ) {
+			if ( direction === "first" || direction === "last" ) {
+				next = this.active
+					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
+					.eq( -1 );
+			} else {
+				next = this.active
+					[ direction + "All" ]( ".ui-menu-item" )
+					.eq( 0 );
+			}
+		}
+		if ( !next || !next.length || !this.active ) {
+			next = this.activeMenu.find( this.options.items )[ filter ]();
+		}
+
+		this.focus( event, next );
+	},
+
+	nextPage: function( event ) {
+		var item, base, height;
+
+		if ( !this.active ) {
+			this.next( event );
+			return;
+		}
+		if ( this.isLastItem() ) {
+			return;
+		}
+		if ( this._hasScroll() ) {
+			base = this.active.offset().top;
+			height = this.element.height();
+			this.active.nextAll( ".ui-menu-item" ).each(function() {
+				item = $( this );
+				return item.offset().top - base - height < 0;
+			});
+
+			this.focus( event, item );
+		} else {
+			this.focus( event, this.activeMenu.find( this.options.items )
+				[ !this.active ? "first" : "last" ]() );
+		}
+	},
+
+	previousPage: function( event ) {
+		var item, base, height;
+		if ( !this.active ) {
+			this.next( event );
+			return;
+		}
+		if ( this.isFirstItem() ) {
+			return;
+		}
+		if ( this._hasScroll() ) {
+			base = this.active.offset().top;
+			height = this.element.height();
+			this.active.prevAll( ".ui-menu-item" ).each(function() {
+				item = $( this );
+				return item.offset().top - base + height > 0;
+			});
+
+			this.focus( event, item );
+		} else {
+			this.focus( event, this.activeMenu.find( this.options.items ).first() );
+		}
+	},
+
+	_hasScroll: function() {
+		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
+	},
+
+	select: function( event ) {
+		// TODO: It should never be possible to not have an active item at this
+		// point, but the tests don't trigger mouseenter before click.
+		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
+		var ui = { item: this.active };
+		if ( !this.active.has( ".ui-menu" ).length ) {
+			this.collapseAll( event, true );
+		}
+		this._trigger( "select", event, ui );
+	},
+
+	_filterMenuItems: function(character) {
+		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
+			regex = new RegExp( "^" + escapedCharacter, "i" );
+
+		return this.activeMenu
+			.find( this.options.items )
+
+			// Only match on items, not dividers or other content (#10571)
+			.filter( ".ui-menu-item" )
+			.filter(function() {
+				return regex.test( $.trim( $( this ).text() ) );
+			});
+	}
+});
+
+
+/*!
+ * jQuery UI Autocomplete 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/autocomplete/
+ */
+
+
+$.widget( "ui.autocomplete", {
+	version: "1.11.4",
+	defaultElement: "<input>",
+	options: {
+		appendTo: null,
+		autoFocus: false,
+		delay: 300,
+		minLength: 1,
+		position: {
+			my: "left top",
+			at: "left bottom",
+			collision: "none"
+		},
+		source: null,
+
+		// callbacks
+		change: null,
+		close: null,
+		focus: null,
+		open: null,
+		response: null,
+		search: null,
+		select: null
+	},
+
+	requestIndex: 0,
+	pending: 0,
+
+	_create: function() {
+		// Some browsers only repeat keydown events, not keypress events,
+		// so we use the suppressKeyPress flag to determine if we've already
+		// handled the keydown event. #7269
+		// Unfortunately the code for & in keypress is the same as the up arrow,
+		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
+		// events when we know the keydown event was used to modify the
+		// search term. #7799
+		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
+			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
+			isTextarea = nodeName === "textarea",
+			isInput = nodeName === "input";
+
+		this.isMultiLine =
+			// Textareas are always multi-line
+			isTextarea ? true :
+			// Inputs are always single-line, even if inside a contentEditable element
+			// IE also treats inputs as contentEditable
+			isInput ? false :
+			// All other element types are determined by whether or not they're contentEditable
+			this.element.prop( "isContentEditable" );
+
+		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
+		this.isNewMenu = true;
+
+		this.element
+			.addClass( "ui-autocomplete-input" )
+			.attr( "autocomplete", "off" );
+
+		this._on( this.element, {
+			keydown: function( event ) {
+				if ( this.element.prop( "readOnly" ) ) {
+					suppressKeyPress = true;
+					suppressInput = true;
+					suppressKeyPressRepeat = true;
+					return;
+				}
+
+				suppressKeyPress = false;
+				suppressInput = false;
+				suppressKeyPressRepeat = false;
+				var keyCode = $.ui.keyCode;
+				switch ( event.keyCode ) {
+				case keyCode.PAGE_UP:
+					suppressKeyPress = true;
+					this._move( "previousPage", event );
+					break;
+				case keyCode.PAGE_DOWN:
+					suppressKeyPress = true;
+					this._move( "nextPage", event );
+					break;
+				case keyCode.UP:
+					suppressKeyPress = true;
+					this._keyEvent( "previous", event );
+					break;
+				case keyCode.DOWN:
+					suppressKeyPress = true;
+					this._keyEvent( "next", event );
+					break;
+				case keyCode.ENTER:
+					// when menu is open and has focus
+					if ( this.menu.active ) {
+						// #6055 - Opera still allows the keypress to occur
+						// which causes forms to submit
+						suppressKeyPress = true;
+						event.preventDefault();
+						this.menu.select( event );
+					}
+					break;
+				case keyCode.TAB:
+					if ( this.menu.active ) {
+						this.menu.select( event );
+					}
+					break;
+				case keyCode.ESCAPE:
+					if ( this.menu.element.is( ":visible" ) ) {
+						if ( !this.isMultiLine ) {
+							this._value( this.term );
+						}
+						this.close( event );
+						// Different browsers have different default behavior for escape
+						// Single press can mean undo or clear
+						// Double press in IE means clear the whole form
+						event.preventDefault();
+					}
+					break;
+				default:
+					suppressKeyPressRepeat = true;
+					// search timeout should be triggered before the input value is changed
+					this._searchTimeout( event );
+					break;
+				}
+			},
+			keypress: function( event ) {
+				if ( suppressKeyPress ) {
+					suppressKeyPress = false;
+					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
+						event.preventDefault();
+					}
+					return;
+				}
+				if ( suppressKeyPressRepeat ) {
+					return;
+				}
+
+				// replicate some key handlers to allow them to repeat in Firefox and Opera
+				var keyCode = $.ui.keyCode;
+				switch ( event.keyCode ) {
+				case keyCode.PAGE_UP:
+					this._move( "previousPage", event );
+					break;
+				case keyCode.PAGE_DOWN:
+					this._move( "nextPage", event );
+					break;
+				case keyCode.UP:
+					this._keyEvent( "previous", event );
+					break;
+				case keyCode.DOWN:
+					this._keyEvent( "next", event );
+					break;
+				}
+			},
+			input: function( event ) {
+				if ( suppressInput ) {
+					suppressInput = false;
+					event.preventDefault();
+					return;
+				}
+				this._searchTimeout( event );
+			},
+			focus: function() {
+				this.selectedItem = null;
+				this.previous = this._value();
+			},
+			blur: function( event ) {
+				if ( this.cancelBlur ) {
+					delete this.cancelBlur;
+					return;
+				}
+
+				clearTimeout( this.searching );
+				this.close( event );
+				this._change( event );
+			}
+		});
+
+		this._initSource();
+		this.menu = $( "<ul>" )
+			.addClass( "ui-autocomplete ui-front" )
+			.appendTo( this._appendTo() )
+			.menu({
+				// disable ARIA support, the live region takes care of that
+				role: null
+			})
+			.hide()
+			.menu( "instance" );
+
+		this._on( this.menu.element, {
+			mousedown: function( event ) {
+				// prevent moving focus out of the text field
+				event.preventDefault();
+
+				// IE doesn't prevent moving focus even with event.preventDefault()
+				// so we set a flag to know when we should ignore the blur event
+				this.cancelBlur = true;
+				this._delay(function() {
+					delete this.cancelBlur;
+				});
+
+				// clicking on the scrollbar causes focus to shift to the body
+				// but we can't detect a mouseup or a click immediately afterward
+				// so we have to track the next mousedown and close the menu if
+				// the user clicks somewhere outside of the autocomplete
+				var menuElement = this.menu.element[ 0 ];
+				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
+					this._delay(function() {
+						var that = this;
+						this.document.one( "mousedown", function( event ) {
+							if ( event.target !== that.element[ 0 ] &&
+									event.target !== menuElement &&
+									!$.contains( menuElement, event.target ) ) {
+								that.close();
+							}
+						});
+					});
+				}
+			},
+			menufocus: function( event, ui ) {
+				var label, item;
+				// support: Firefox
+				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
+				if ( this.isNewMenu ) {
+					this.isNewMenu = false;
+					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
+						this.menu.blur();
+
+						this.document.one( "mousemove", function() {
+							$( event.target ).trigger( event.originalEvent );
+						});
+
+						return;
+					}
+				}
+
+				item = ui.item.data( "ui-autocomplete-item" );
+				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
+					// use value to match what will end up in the input, if it was a key event
+					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
+						this._value( item.value );
+					}
+				}
+
+				// Announce the value in the liveRegion
+				label = ui.item.attr( "aria-label" ) || item.value;
+				if ( label && $.trim( label ).length ) {
+					this.liveRegion.children().hide();
+					$( "<div>" ).text( label ).appendTo( this.liveRegion );
+				}
+			},
+			menuselect: function( event, ui ) {
+				var item = ui.item.data( "ui-autocomplete-item" ),
+					previous = this.previous;
+
+				// only trigger when focus was lost (click on menu)
+				if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
+					this.element.focus();
+					this.previous = previous;
+					// #6109 - IE triggers two focus events and the second
+					// is asynchronous, so we need to reset the previous
+					// term synchronously and asynchronously :-(
+					this._delay(function() {
+						this.previous = previous;
+						this.selectedItem = item;
+					});
+				}
+
+				if ( false !== this._trigger( "select", event, { item: item } ) ) {
+					this._value( item.value );
+				}
+				// reset the term after the select event
+				// this allows custom select handling to work properly
+				this.term = this._value();
+
+				this.close( event );
+				this.selectedItem = item;
+			}
+		});
+
+		this.liveRegion = $( "<span>", {
+				role: "status",
+				"aria-live": "assertive",
+				"aria-relevant": "additions"
+			})
+			.addClass( "ui-helper-hidden-accessible" )
+			.appendTo( this.document[ 0 ].body );
+
+		// turning off autocomplete prevents the browser from remembering the
+		// value when navigating through history, so we re-enable autocomplete
+		// if the page is unloaded before the widget is destroyed. #7790
+		this._on( this.window, {
+			beforeunload: function() {
+				this.element.removeAttr( "autocomplete" );
+			}
+		});
+	},
+
+	_destroy: function() {
+		clearTimeout( this.searching );
+		this.element
+			.removeClass( "ui-autocomplete-input" )
+			.removeAttr( "autocomplete" );
+		this.menu.element.remove();
+		this.liveRegion.remove();
+	},
+
+	_setOption: function( key, value ) {
+		this._super( key, value );
+		if ( key === "source" ) {
+			this._initSource();
+		}
+		if ( key === "appendTo" ) {
+			this.menu.element.appendTo( this._appendTo() );
+		}
+		if ( key === "disabled" && value && this.xhr ) {
+			this.xhr.abort();
+		}
+	},
+
+	_appendTo: function() {
+		var element = this.options.appendTo;
+
+		if ( element ) {
+			element = element.jquery || element.nodeType ?
+				$( element ) :
+				this.document.find( element ).eq( 0 );
+		}
+
+		if ( !element || !element[ 0 ] ) {
+			element = this.element.closest( ".ui-front" );
+		}
+
+		if ( !element.length ) {
+			element = this.document[ 0 ].body;
+		}
+
+		return element;
+	},
+
+	_initSource: function() {
+		var array, url,
+			that = this;
+		if ( $.isArray( this.options.source ) ) {
+			array = this.options.source;
+			this.source = function( request, response ) {
+				response( $.ui.autocomplete.filter( array, request.term ) );
+			};
+		} else if ( typeof this.options.source === "string" ) {
+			url = this.options.source;
+			this.source = function( request, response ) {
+				if ( that.xhr ) {
+					that.xhr.abort();
+				}
+				that.xhr = $.ajax({
+					url: url,
+					data: request,
+					dataType: "json",
+					success: function( data ) {
+						response( data );
+					},
+					error: function() {
+						response([]);
+					}
+				});
+			};
+		} else {
+			this.source = this.options.source;
+		}
+	},
+
+	_searchTimeout: function( event ) {
+		clearTimeout( this.searching );
+		this.searching = this._delay(function() {
+
+			// Search if the value has changed, or if the user retypes the same value (see #7434)
+			var equalValues = this.term === this._value(),
+				menuVisible = this.menu.element.is( ":visible" ),
+				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
+
+			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
+				this.selectedItem = null;
+				this.search( null, event );
+			}
+		}, this.options.delay );
+	},
+
+	search: function( value, event ) {
+		value = value != null ? value : this._value();
+
+		// always save the actual value, not the one passed as an argument
+		this.term = this._value();
+
+		if ( value.length < this.options.minLength ) {
+			return this.close( event );
+		}
+
+		if ( this._trigger( "search", event ) === false ) {
+			return;
+		}
+
+		return this._search( value );
+	},
+
+	_search: function( value ) {
+		this.pending++;
+		this.element.addClass( "ui-autocomplete-loading" );
+		this.cancelSearch = false;
+
+		this.source( { term: value }, this._response() );
+	},
+
+	_response: function() {
+		var index = ++this.requestIndex;
+
+		return $.proxy(function( content ) {
+			if ( index === this.requestIndex ) {
+				this.__response( content );
+			}
+
+			this.pending--;
+			if ( !this.pending ) {
+				this.element.removeClass( "ui-autocomplete-loading" );
+			}
+		}, this );
+	},
+
+	__response: function( content ) {
+		if ( content ) {
+			content = this._normalize( content );
+		}
+		this._trigger( "response", null, { content: content } );
+		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
+			this._suggest( content );
+			this._trigger( "open" );
+		} else {
+			// use ._close() instead of .close() so we don't cancel future searches
+			this._close();
+		}
+	},
+
+	close: function( event ) {
+		this.cancelSearch = true;
+		this._close( event );
+	},
+
+	_close: function( event ) {
+		if ( this.menu.element.is( ":visible" ) ) {
+			this.menu.element.hide();
+			this.menu.blur();
+			this.isNewMenu = true;
+			this._trigger( "close", event );
+		}
+	},
+
+	_change: function( event ) {
+		if ( this.previous !== this._value() ) {
+			this._trigger( "change", event, { item: this.selectedItem } );
+		}
+	},
+
+	_normalize: function( items ) {
+		// assume all items have the right format when the first item is complete
+		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
+			return items;
+		}
+		return $.map( items, function( item ) {
+			if ( typeof item === "string" ) {
+				return {
+					label: item,
+					value: item
+				};
+			}
+			return $.extend( {}, item, {
+				label: item.label || item.value,
+				value: item.value || item.label
+			});
+		});
+	},
+
+	_suggest: function( items ) {
+		var ul = this.menu.element.empty();
+		this._renderMenu( ul, items );
+		this.isNewMenu = true;
+		this.menu.refresh();
+
+		// size and position menu
+		ul.show();
+		this._resizeMenu();
+		ul.position( $.extend({
+			of: this.element
+		}, this.options.position ) );
+
+		if ( this.options.autoFocus ) {
+			this.menu.next();
+		}
+	},
+
+	_resizeMenu: function() {
+		var ul = this.menu.element;
+		ul.outerWidth( Math.max(
+			// Firefox wraps long text (possibly a rounding bug)
+			// so we add 1px to avoid the wrapping (#7513)
+			ul.width( "" ).outerWidth() + 1,
+			this.element.outerWidth()
+		) );
+	},
+
+	_renderMenu: function( ul, items ) {
+		var that = this;
+		$.each( items, function( index, item ) {
+			that._renderItemData( ul, item );
+		});
+	},
+
+	_renderItemData: function( ul, item ) {
+		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
+	},
+
+	_renderItem: function( ul, item ) {
+		return $( "<li>" ).text( item.label ).appendTo( ul );
+	},
+
+	_move: function( direction, event ) {
+		if ( !this.menu.element.is( ":visible" ) ) {
+			this.search( null, event );
+			return;
+		}
+		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
+				this.menu.isLastItem() && /^next/.test( direction ) ) {
+
+			if ( !this.isMultiLine ) {
+				this._value( this.term );
+			}
+
+			this.menu.blur();
+			return;
+		}
+		this.menu[ direction ]( event );
+	},
+
+	widget: function() {
+		return this.menu.element;
+	},
+
+	_value: function() {
+		return this.valueMethod.apply( this.element, arguments );
+	},
+
+	_keyEvent: function( keyEvent, event ) {
+		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
+			this._move( keyEvent, event );
+
+			// prevents moving cursor to beginning/end of the text field in some browsers
+			event.preventDefault();
+		}
+	}
+});
+
+$.extend( $.ui.autocomplete, {
+	escapeRegex: function( value ) {
+		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
+	},
+	filter: function( array, term ) {
+		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
+		return $.grep( array, function( value ) {
+			return matcher.test( value.label || value.value || value );
+		});
+	}
+});
+
+// live region extension, adding a `messages` option
+// NOTE: This is an experimental API. We are still investigating
+// a full solution for string manipulation and internationalization.
+$.widget( "ui.autocomplete", $.ui.autocomplete, {
+	options: {
+		messages: {
+			noResults: "No search results.",
+			results: function( amount ) {
+				return amount + ( amount > 1 ? " results are" : " result is" ) +
+					" available, use up and down arrow keys to navigate.";
+			}
+		}
+	},
+
+	__response: function( content ) {
+		var message;
+		this._superApply( arguments );
+		if ( this.options.disabled || this.cancelSearch ) {
+			return;
+		}
+		if ( content && content.length ) {
+			message = this.options.messages.results( content.length );
+		} else {
+			message = this.options.messages.noResults;
+		}
+		this.liveRegion.children().hide();
+		$( "<div>" ).text( message ).appendTo( this.liveRegion );
+	}
+});
+
+var autocomplete = $.ui.autocomplete;
+
+
+/*!
+ * jQuery UI Button 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/button/
+ */
+
+
+var lastActive,
+	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
+	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
+	formResetHandler = function() {
+		var form = $( this );
+		setTimeout(function() {
+			form.find( ":ui-button" ).button( "refresh" );
+		}, 1 );
+	},
+	radioGroup = function( radio ) {
+		var name = radio.name,
+			form = radio.form,
+			radios = $( [] );
+		if ( name ) {
+			name = name.replace( /'/g, "\\'" );
+			if ( form ) {
+				radios = $( form ).find( "[name='" + name + "'][type=radio]" );
+			} else {
+				radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
+					.filter(function() {
+						return !this.form;
+					});
+			}
+		}
+		return radios;
+	};
+
+$.widget( "ui.button", {
+	version: "1.11.4",
+	defaultElement: "<button>",
+	options: {
+		disabled: null,
+		text: true,
+		label: null,
+		icons: {
+			primary: null,
+			secondary: null
+		}
+	},
+	_create: function() {
+		this.element.closest( "form" )
+			.unbind( "reset" + this.eventNamespace )
+			.bind( "reset" + this.eventNamespace, formResetHandler );
+
+		if ( typeof this.options.disabled !== "boolean" ) {
+			this.options.disabled = !!this.element.prop( "disabled" );
+		} else {
+			this.element.prop( "disabled", this.options.disabled );
+		}
+
+		this._determineButtonType();
+		this.hasTitle = !!this.buttonElement.attr( "title" );
+
+		var that = this,
+			options = this.options,
+			toggleButton = this.type === "checkbox" || this.type === "radio",
+			activeClass = !toggleButton ? "ui-state-active" : "";
+
+		if ( options.label === null ) {
+			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
+		}
+
+		this._hoverable( this.buttonElement );
+
+		this.buttonElement
+			.addClass( baseClasses )
+			.attr( "role", "button" )
+			.bind( "mouseenter" + this.eventNamespace, function() {
+				if ( options.disabled ) {
+					return;
+				}
+				if ( this === lastActive ) {
+					$( this ).addClass( "ui-state-active" );
+				}
+			})
+			.bind( "mouseleave" + this.eventNamespace, function() {
+				if ( options.disabled ) {
+					return;
+				}
+				$( this ).removeClass( activeClass );
+			})
+			.bind( "click" + this.eventNamespace, function( event ) {
+				if ( options.disabled ) {
+					event.preventDefault();
+					event.stopImmediatePropagation();
+				}
+			});
+
+		// Can't use _focusable() because the element that receives focus
+		// and the element that gets the ui-state-focus class are different
+		this._on({
+			focus: function() {
+				this.buttonElement.addClass( "ui-state-focus" );
+			},
+			blur: function() {
+				this.buttonElement.removeClass( "ui-state-focus" );
+			}
+		});
+
+		if ( toggleButton ) {
+			this.element.bind( "change" + this.eventNamespace, function() {
+				that.refresh();
+			});
+		}
+
+		if ( this.type === "checkbox" ) {
+			this.buttonElement.bind( "click" + this.eventNamespace, function() {
+				if ( options.disabled ) {
+					return false;
+				}
+			});
+		} else if ( this.type === "radio" ) {
+			this.buttonElement.bind( "click" + this.eventNamespace, function() {
+				if ( options.disabled ) {
+					return false;
+				}
+				$( this ).addClass( "ui-state-active" );
+				that.buttonElement.attr( "aria-pressed", "true" );
+
+				var radio = that.element[ 0 ];
+				radioGroup( radio )
+					.not( radio )
+					.map(function() {
+						return $( this ).button( "widget" )[ 0 ];
+					})
+					.removeClass( "ui-state-active" )
+					.attr( "aria-pressed", "false" );
+			});
+		} else {
+			this.buttonElement
+				.bind( "mousedown" + this.eventNamespace, function() {
+					if ( options.disabled ) {
+						return false;
+					}
+					$( this ).addClass( "ui-state-active" );
+					lastActive = this;
+					that.document.one( "mouseup", function() {
+						lastActive = null;
+					});
+				})
+				.bind( "mouseup" + this.eventNamespace, function() {
+					if ( options.disabled ) {
+						return false;
+					}
+					$( this ).removeClass( "ui-state-active" );
+				})
+				.bind( "keydown" + this.eventNamespace, function(event) {
+					if ( options.disabled ) {
+						return false;
+					}
+					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
+						$( this ).addClass( "ui-state-active" );
+					}
+				})
+				// see #8559, we bind to blur here in case the button element loses
+				// focus between keydown and keyup, it would be left in an "active" state
+				.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
+					$( this ).removeClass( "ui-state-active" );
+				});
+
+			if ( this.buttonElement.is("a") ) {
+				this.buttonElement.keyup(function(event) {
+					if ( event.keyCode === $.ui.keyCode.SPACE ) {
+						// TODO pass through original event correctly (just as 2nd argument doesn't work)
+						$( this ).click();
+					}
+				});
+			}
+		}
+
+		this._setOption( "disabled", options.disabled );
+		this._resetButton();
+	},
+
+	_determineButtonType: function() {
+		var ancestor, labelSelector, checked;
+
+		if ( this.element.is("[type=checkbox]") ) {
+			this.type = "checkbox";
+		} else if ( this.element.is("[type=radio]") ) {
+			this.type = "radio";
+		} else if ( this.element.is("input") ) {
+			this.type = "input";
+		} else {
+			this.type = "button";
+		}
+
+		if ( this.type === "checkbox" || this.type === "radio" ) {
+			// we don't search against the document in case the element
+			// is disconnected from the DOM
+			ancestor = this.element.parents().last();
+			labelSelector = "label[for='" + this.element.attr("id") + "']";
+			this.buttonElement = ancestor.find( labelSelector );
+			if ( !this.buttonElement.length ) {
+				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
+				this.buttonElement = ancestor.filter( labelSelector );
+				if ( !this.buttonElement.length ) {
+					this.buttonElement = ancestor.find( labelSelector );
+				}
+			}
+			this.element.addClass( "ui-helper-hidden-accessible" );
+
+			checked = this.element.is( ":checked" );
+			if ( checked ) {
+				this.buttonElement.addClass( "ui-state-active" );
+			}
+			this.buttonElement.prop( "aria-pressed", checked );
+		} else {
+			this.buttonElement = this.element;
+		}
+	},
+
+	widget: function() {
+		return this.buttonElement;
+	},
+
+	_destroy: function() {
+		this.element
+			.removeClass( "ui-helper-hidden-accessible" );
+		this.buttonElement
+			.removeClass( baseClasses + " ui-state-active " + typeClasses )
+			.removeAttr( "role" )
+			.removeAttr( "aria-pressed" )
+			.html( this.buttonElement.find(".ui-button-text").html() );
+
+		if ( !this.hasTitle ) {
+			this.buttonElement.removeAttr( "title" );
+		}
+	},
+
+	_setOption: function( key, value ) {
+		this._super( key, value );
+		if ( key === "disabled" ) {
+			this.widget().toggleClass( "ui-state-disabled", !!value );
+			this.element.prop( "disabled", !!value );
+			if ( value ) {
+				if ( this.type === "checkbox" || this.type === "radio" ) {
+					this.buttonElement.removeClass( "ui-state-focus" );
+				} else {
+					this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
+				}
+			}
+			return;
+		}
+		this._resetButton();
+	},
+
+	refresh: function() {
+		//See #8237 & #8828
+		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
+
+		if ( isDisabled !== this.options.disabled ) {
+			this._setOption( "disabled", isDisabled );
+		}
+		if ( this.type === "radio" ) {
+			radioGroup( this.element[0] ).each(function() {
+				if ( $( this ).is( ":checked" ) ) {
+					$( this ).button( "widget" )
+						.addClass( "ui-state-active" )
+						.attr( "aria-pressed", "true" );
+				} else {
+					$( this ).button( "widget" )
+						.removeClass( "ui-state-active" )
+						.attr( "aria-pressed", "false" );
+				}
+			});
+		} else if ( this.type === "checkbox" ) {
+			if ( this.element.is( ":checked" ) ) {
+				this.buttonElement
+					.addClass( "ui-state-active" )
+					.attr( "aria-pressed", "true" );
+			} else {
+				this.buttonElement
+					.removeClass( "ui-state-active" )
+					.attr( "aria-pressed", "false" );
+			}
+		}
+	},
+
+	_resetButton: function() {
+		if ( this.type === "input" ) {
+			if ( this.options.label ) {
+				this.element.val( this.options.label );
+			}
+			return;
+		}
+		var buttonElement = this.buttonElement.removeClass( typeClasses ),
+			buttonText = $( "<span></span>", this.document[0] )
+				.addClass( "ui-button-text" )
+				.html( this.options.label )
+				.appendTo( buttonElement.empty() )
+				.text(),
+			icons = this.options.icons,
+			multipleIcons = icons.primary && icons.secondary,
+			buttonClasses = [];
+
+		if ( icons.primary || icons.secondary ) {
+			if ( this.options.text ) {
+				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
+			}
+
+			if ( icons.primary ) {
+				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
+			}
+
+			if ( icons.secondary ) {
+				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
+			}
+
+			if ( !this.options.text ) {
+				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
+
+				if ( !this.hasTitle ) {
+					buttonElement.attr( "title", $.trim( buttonText ) );
+				}
+			}
+		} else {
+			buttonClasses.push( "ui-button-text-only" );
+		}
+		buttonElement.addClass( buttonClasses.join( " " ) );
+	}
+});
+
+$.widget( "ui.buttonset", {
+	version: "1.11.4",
+	options: {
+		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
+	},
+
+	_create: function() {
+		this.element.addClass( "ui-buttonset" );
+	},
+
+	_init: function() {
+		this.refresh();
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "disabled" ) {
+			this.buttons.button( "option", key, value );
+		}
+
+		this._super( key, value );
+	},
+
+	refresh: function() {
+		var rtl = this.element.css( "direction" ) === "rtl",
+			allButtons = this.element.find( this.options.items ),
+			existingButtons = allButtons.filter( ":ui-button" );
+
+		// Initialize new buttons
+		allButtons.not( ":ui-button" ).button();
+
+		// Refresh existing buttons
+		existingButtons.button( "refresh" );
+
+		this.buttons = allButtons
+			.map(function() {
+				return $( this ).button( "widget" )[ 0 ];
+			})
+				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
+				.filter( ":first" )
+					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
+				.end()
+				.filter( ":last" )
+					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
+				.end()
+			.end();
+	},
+
+	_destroy: function() {
+		this.element.removeClass( "ui-buttonset" );
+		this.buttons
+			.map(function() {
+				return $( this ).button( "widget" )[ 0 ];
+			})
+				.removeClass( "ui-corner-left ui-corner-right" )
+			.end()
+			.button( "destroy" );
+	}
+});
+
+var button = $.ui.button;
+
+
+/*!
+ * jQuery UI Datepicker 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/datepicker/
+ */
+
+
+$.extend($.ui, { datepicker: { version: "1.11.4" } });
+
+var datepicker_instActive;
+
+function datepicker_getZindex( elem ) {
+	var position, value;
+	while ( elem.length && elem[ 0 ] !== document ) {
+		// Ignore z-index if position is set to a value where z-index is ignored by the browser
+		// This makes behavior of this function consistent across browsers
+		// WebKit always returns auto if the element is positioned
+		position = elem.css( "position" );
+		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
+			// IE returns 0 when zIndex is not specified
+			// other browsers return a string
+			// we ignore the case of nested elements with an explicit value of 0
+			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
+			value = parseInt( elem.css( "zIndex" ), 10 );
+			if ( !isNaN( value ) && value !== 0 ) {
+				return value;
+			}
+		}
+		elem = elem.parent();
+	}
+
+	return 0;
+}
+/* Date picker manager.
+   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
+   Settings for (groups of) date pickers are maintained in an instance object,
+   allowing multiple different settings on the same page. */
+
+function Datepicker() {
+	this._curInst = null; // The current instance in use
+	this._keyEvent = false; // If the last event was a key event
+	this._disabledInputs = []; // List of date picker inputs that have been disabled
+	this._datepickerShowing = false; // True if the popup picker is showing , false if not
+	this._inDialog = false; // True if showing within a "dialog", false if not
+	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
+	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
+	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
+	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
+	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
+	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
+	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
+	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
+	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
+	this.regional = []; // Available regional settings, indexed by language code
+	this.regional[""] = { // Default regional settings
+		closeText: "Done", // Display text for close link
+		prevText: "Prev", // Display text for previous month link
+		nextText: "Next", // Display text for next month link
+		currentText: "Today", // Display text for current month link
+		monthNames: ["January","February","March","April","May","June",
+			"July","August","September","October","November","December"], // Names of months for drop-down and formatting
+		monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
+		dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
+		dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
+		dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
+		weekHeader: "Wk", // Column header for week of the year
+		dateFormat: "mm/dd/yy", // See format options on parseDate
+		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
+		isRTL: false, // True if right-to-left language, false if left-to-right
+		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+		yearSuffix: "" // Additional text to append to the year in the month headers
+	};
+	this._defaults = { // Global defaults for all the date picker instances
+		showOn: "focus", // "focus" for popup on focus,
+			// "button" for trigger button, or "both" for either
+		showAnim: "fadeIn", // Name of jQuery animation for popup
+		showOptions: {}, // Options for enhanced animations
+		defaultDate: null, // Used when field is blank: actual date,
+			// +/-number for offset from today, null for today
+		appendText: "", // Display text following the input box, e.g. showing the format
+		buttonText: "...", // Text for trigger button
+		buttonImage: "", // URL for trigger button image
+		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
+		hideIfNoPrevNext: false, // True to hide next/previous month links
+			// if not applicable, false to just disable them
+		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
+		gotoCurrent: false, // True if today link goes back to current selection instead
+		changeMonth: false, // True if month can be selected directly, false if only prev/next
+		changeYear: false, // True if year can be selected directly, false if only prev/next
+		yearRange: "c-10:c+10", // Range of years to display in drop-down,
+			// either relative to today's year (-nn:+nn), relative to currently displayed year
+			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
+		showOtherMonths: false, // True to show dates in other months, false to leave blank
+		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
+		showWeek: false, // True to show week of the year, false to not show it
+		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
+			// takes a Date and returns the number of the week for it
+		shortYearCutoff: "+10", // Short year values < this are in the current century,
+			// > this are in the previous century,
+			// string value starting with "+" for current year + value
+		minDate: null, // The earliest selectable date, or null for no limit
+		maxDate: null, // The latest selectable date, or null for no limit
+		duration: "fast", // Duration of display/closure
+		beforeShowDay: null, // Function that takes a date and returns an array with
+			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
+			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
+		beforeShow: null, // Function that takes an input field and
+			// returns a set of custom settings for the date picker
+		onSelect: null, // Define a callback function when a date is selected
+		onChangeMonthYear: null, // Define a callback function when the month or year is changed
+		onClose: null, // Define a callback function when the datepicker is closed
+		numberOfMonths: 1, // Number of months to show at a time
+		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
+		stepMonths: 1, // Number of months to step back/forward
+		stepBigMonths: 12, // Number of months to step back/forward for the big links
+		altField: "", // Selector for an alternate field to store selected dates into
+		altFormat: "", // The date format to use for the alternate field
+		constrainInput: true, // The input is constrained by the current date format
+		showButtonPanel: false, // True to show button panel, false to not show it
+		autoSize: false, // True to size the input for the date format, false to leave as is
+		disabled: false // The initial disabled state
+	};
+	$.extend(this._defaults, this.regional[""]);
+	this.regional.en = $.extend( true, {}, this.regional[ "" ]);
+	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
+	this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
+}
+
+$.extend(Datepicker.prototype, {
+	/* Class name added to elements to indicate already configured with a date picker. */
+	markerClassName: "hasDatepicker",
+
+	//Keep track of the maximum number of rows displayed (see #7043)
+	maxRows: 4,
+
+	// TODO rename to "widget" when switching to widget factory
+	_widgetDatepicker: function() {
+		return this.dpDiv;
+	},
+
+	/* Override the default settings for all instances of the date picker.
+	 * @param  settings  object - the new settings to use as defaults (anonymous object)
+	 * @return the manager object
+	 */
+	setDefaults: function(settings) {
+		datepicker_extendRemove(this._defaults, settings || {});
+		return this;
+	},
+
+	/* Attach the date picker to a jQuery selection.
+	 * @param  target	element - the target input field or division or span
+	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
+	 */
+	_attachDatepicker: function(target, settings) {
+		var nodeName, inline, inst;
+		nodeName = target.nodeName.toLowerCase();
+		inline = (nodeName === "div" || nodeName === "span");
+		if (!target.id) {
+			this.uuid += 1;
+			target.id = "dp" + this.uuid;
+		}
+		inst = this._newInst($(target), inline);
+		inst.settings = $.extend({}, settings || {});
+		if (nodeName === "input") {
+			this._connectDatepicker(target, inst);
+		} else if (inline) {
+			this._inlineDatepicker(target, inst);
+		}
+	},
+
+	/* Create a new instance object. */
+	_newInst: function(target, inline) {
+		var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
+		return {id: id, input: target, // associated target
+			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
+			drawMonth: 0, drawYear: 0, // month being drawn
+			inline: inline, // is datepicker inline or not
+			dpDiv: (!inline ? this.dpDiv : // presentation div
+			datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
+	},
+
+	/* Attach the date picker to an input field. */
+	_connectDatepicker: function(target, inst) {
+		var input = $(target);
+		inst.append = $([]);
+		inst.trigger = $([]);
+		if (input.hasClass(this.markerClassName)) {
+			return;
+		}
+		this._attachments(input, inst);
+		input.addClass(this.markerClassName).keydown(this._doKeyDown).
+			keypress(this._doKeyPress).keyup(this._doKeyUp);
+		this._autoSize(inst);
+		$.data(target, "datepicker", inst);
+		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
+		if( inst.settings.disabled ) {
+			this._disableDatepicker( target );
+		}
+	},
+
+	/* Make attachments based on settings. */
+	_attachments: function(input, inst) {
+		var showOn, buttonText, buttonImage,
+			appendText = this._get(inst, "appendText"),
+			isRTL = this._get(inst, "isRTL");
+
+		if (inst.append) {
+			inst.append.remove();
+		}
+		if (appendText) {
+			inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
+			input[isRTL ? "before" : "after"](inst.append);
+		}
+
+		input.unbind("focus", this._showDatepicker);
+
+		if (inst.trigger) {
+			inst.trigger.remove();
+		}
+
+		showOn = this._get(inst, "showOn");
+		if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
+			input.focus(this._showDatepicker);
+		}
+		if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
+			buttonText = this._get(inst, "buttonText");
+			buttonImage = this._get(inst, "buttonImage");
+			inst.trigger = $(this._get(inst, "buttonImageOnly") ?
+				$("<img/>").addClass(this._triggerClass).
+					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
+				$("<button type='button'></button>").addClass(this._triggerClass).
+					html(!buttonImage ? buttonText : $("<img/>").attr(
+					{ src:buttonImage, alt:buttonText, title:buttonText })));
+			input[isRTL ? "before" : "after"](inst.trigger);
+			inst.trigger.click(function() {
+				if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
+					$.datepicker._hideDatepicker();
+				} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
+					$.datepicker._hideDatepicker();
+					$.datepicker._showDatepicker(input[0]);
+				} else {
+					$.datepicker._showDatepicker(input[0]);
+				}
+				return false;
+			});
+		}
+	},
+
+	/* Apply the maximum length for the date format. */
+	_autoSize: function(inst) {
+		if (this._get(inst, "autoSize") && !inst.inline) {
+			var findMax, max, maxI, i,
+				date = new Date(2009, 12 - 1, 20), // Ensure double digits
+				dateFormat = this._get(inst, "dateFormat");
+
+			if (dateFormat.match(/[DM]/)) {
+				findMax = function(names) {
+					max = 0;
+					maxI = 0;
+					for (i = 0; i < names.length; i++) {
+						if (names[i].length > max) {
+							max = names[i].length;
+							maxI = i;
+						}
+					}
+					return maxI;
+				};
+				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
+					"monthNames" : "monthNamesShort"))));
+				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
+					"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
+			}
+			inst.input.attr("size", this._formatDate(inst, date).length);
+		}
+	},
+
+	/* Attach an inline date picker to a div. */
+	_inlineDatepicker: function(target, inst) {
+		var divSpan = $(target);
+		if (divSpan.hasClass(this.markerClassName)) {
+			return;
+		}
+		divSpan.addClass(this.markerClassName).append(inst.dpDiv);
+		$.data(target, "datepicker", inst);
+		this._setDate(inst, this._getDefaultDate(inst), true);
+		this._updateDatepicker(inst);
+		this._updateAlternate(inst);
+		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
+		if( inst.settings.disabled ) {
+			this._disableDatepicker( target );
+		}
+		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
+		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
+		inst.dpDiv.css( "display", "block" );
+	},
+
+	/* Pop-up the date picker in a "dialog" box.
+	 * @param  input element - ignored
+	 * @param  date	string or Date - the initial date to display
+	 * @param  onSelect  function - the function to call when a date is selected
+	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
+	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
+	 *					event - with x/y coordinates or
+	 *					leave empty for default (screen centre)
+	 * @return the manager object
+	 */
+	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
+		var id, browserWidth, browserHeight, scrollX, scrollY,
+			inst = this._dialogInst; // internal instance
+
+		if (!inst) {
+			this.uuid += 1;
+			id = "dp" + this.uuid;
+			this._dialogInput = $("<input type='text' id='" + id +
+				"' style='position: absolute; top: -100px; width: 0px;'/>");
+			this._dialogInput.keydown(this._doKeyDown);
+			$("body").append(this._dialogInput);
+			inst = this._dialogInst = this._newInst(this._dialogInput, false);
+			inst.settings = {};
+			$.data(this._dialogInput[0], "datepicker", inst);
+		}
+		datepicker_extendRemove(inst.settings, settings || {});
+		date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
+		this._dialogInput.val(date);
+
+		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+		if (!this._pos) {
+			browserWidth = document.documentElement.clientWidth;
+			browserHeight = document.documentElement.clientHeight;
+			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
+			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+			this._pos = // should use actual width/height below
+				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
+		}
+
+		// move input on screen for focus, but hidden behind dialog
+		this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
+		inst.settings.onSelect = onSelect;
+		this._inDialog = true;
+		this.dpDiv.addClass(this._dialogClass);
+		this._showDatepicker(this._dialogInput[0]);
+		if ($.blockUI) {
+			$.blockUI(this.dpDiv);
+		}
+		$.data(this._dialogInput[0], "datepicker", inst);
+		return this;
+	},
+
+	/* Detach a datepicker from its control.
+	 * @param  target	element - the target input field or division or span
+	 */
+	_destroyDatepicker: function(target) {
+		var nodeName,
+			$target = $(target),
+			inst = $.data(target, "datepicker");
+
+		if (!$target.hasClass(this.markerClassName)) {
+			return;
+		}
+
+		nodeName = target.nodeName.toLowerCase();
+		$.removeData(target, "datepicker");
+		if (nodeName === "input") {
+			inst.append.remove();
+			inst.trigger.remove();
+			$target.removeClass(this.markerClassName).
+				unbind("focus", this._showDatepicker).
+				unbind("keydown", this._doKeyDown).
+				unbind("keypress", this._doKeyPress).
+				unbind("keyup", this._doKeyUp);
+		} else if (nodeName === "div" || nodeName === "span") {
+			$target.removeClass(this.markerClassName).empty();
+		}
+
+		if ( datepicker_instActive === inst ) {
+			datepicker_instActive = null;
+		}
+	},
+
+	/* Enable the date picker to a jQuery selection.
+	 * @param  target	element - the target input field or division or span
+	 */
+	_enableDatepicker: function(target) {
+		var nodeName, inline,
+			$target = $(target),
+			inst = $.data(target, "datepicker");
+
+		if (!$target.hasClass(this.markerClassName)) {
+			return;
+		}
+
+		nodeName = target.nodeName.toLowerCase();
+		if (nodeName === "input") {
+			target.disabled = false;
+			inst.trigger.filter("button").
+				each(function() { this.disabled = false; }).end().
+				filter("img").css({opacity: "1.0", cursor: ""});
+		} else if (nodeName === "div" || nodeName === "span") {
+			inline = $target.children("." + this._inlineClass);
+			inline.children().removeClass("ui-state-disabled");
+			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+				prop("disabled", false);
+		}
+		this._disabledInputs = $.map(this._disabledInputs,
+			function(value) { return (value === target ? null : value); }); // delete entry
+	},
+
+	/* Disable the date picker to a jQuery selection.
+	 * @param  target	element - the target input field or division or span
+	 */
+	_disableDatepicker: function(target) {
+		var nodeName, inline,
+			$target = $(target),
+			inst = $.data(target, "datepicker");
+
+		if (!$target.hasClass(this.markerClassName)) {
+			return;
+		}
+
+		nodeName = target.nodeName.toLowerCase();
+		if (nodeName === "input") {
+			target.disabled = true;
+			inst.trigger.filter("button").
+				each(function() { this.disabled = true; }).end().
+				filter("img").css({opacity: "0.5", cursor: "default"});
+		} else if (nodeName === "div" || nodeName === "span") {
+			inline = $target.children("." + this._inlineClass);
+			inline.children().addClass("ui-state-disabled");
+			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+				prop("disabled", true);
+		}
+		this._disabledInputs = $.map(this._disabledInputs,
+			function(value) { return (value === target ? null : value); }); // delete entry
+		this._disabledInputs[this._disabledInputs.length] = target;
+	},
+
+	/* Is the first field in a jQuery collection disabled as a datepicker?
+	 * @param  target	element - the target input field or division or span
+	 * @return boolean - true if disabled, false if enabled
+	 */
+	_isDisabledDatepicker: function(target) {
+		if (!target) {
+			return false;
+		}
+		for (var i = 0; i < this._disabledInputs.length; i++) {
+			if (this._disabledInputs[i] === target) {
+				return true;
+			}
+		}
+		return false;
+	},
+
+	/* Retrieve the instance data for the target control.
+	 * @param  target  element - the target input field or division or span
+	 * @return  object - the associated instance data
+	 * @throws  error if a jQuery problem getting data
+	 */
+	_getInst: function(target) {
+		try {
+			return $.data(target, "datepicker");
+		}
+		catch (err) {
+			throw "Missing instance data for this datepicker";
+		}
+	},
+
+	/* Update or retrieve the settings for a date picker attached to an input field or division.
+	 * @param  target  element - the target input field or division or span
+	 * @param  name	object - the new settings to update or
+	 *				string - the name of the setting to change or retrieve,
+	 *				when retrieving also "all" for all instance settings or
+	 *				"defaults" for all global defaults
+	 * @param  value   any - the new value for the setting
+	 *				(omit if above is an object or to retrieve a value)
+	 */
+	_optionDatepicker: function(target, name, value) {
+		var settings, date, minDate, maxDate,
+			inst = this._getInst(target);
+
+		if (arguments.length === 2 && typeof name === "string") {
+			return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
+				(inst ? (name === "all" ? $.extend({}, inst.settings) :
+				this._get(inst, name)) : null));
+		}
+
+		settings = name || {};
+		if (typeof name === "string") {
+			settings = {};
+			settings[name] = value;
+		}
+
+		if (inst) {
+			if (this._curInst === inst) {
+				this._hideDatepicker();
+			}
+
+			date = this._getDateDatepicker(target, true);
+			minDate = this._getMinMaxDate(inst, "min");
+			maxDate = this._getMinMaxDate(inst, "max");
+			datepicker_extendRemove(inst.settings, settings);
+			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
+			if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
+				inst.settings.minDate = this._formatDate(inst, minDate);
+			}
+			if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
+				inst.settings.maxDate = this._formatDate(inst, maxDate);
+			}
+			if ( "disabled" in settings ) {
+				if ( settings.disabled ) {
+					this._disableDatepicker(target);
+				} else {
+					this._enableDatepicker(target);
+				}
+			}
+			this._attachments($(target), inst);
+			this._autoSize(inst);
+			this._setDate(inst, date);
+			this._updateAlternate(inst);
+			this._updateDatepicker(inst);
+		}
+	},
+
+	// change method deprecated
+	_changeDatepicker: function(target, name, value) {
+		this._optionDatepicker(target, name, value);
+	},
+
+	/* Redraw the date picker attached to an input field or division.
+	 * @param  target  element - the target input field or division or span
+	 */
+	_refreshDatepicker: function(target) {
+		var inst = this._getInst(target);
+		if (inst) {
+			this._updateDatepicker(inst);
+		}
+	},
+
+	/* Set the dates for a jQuery selection.
+	 * @param  target element - the target input field or division or span
+	 * @param  date	Date - the new date
+	 */
+	_setDateDatepicker: function(target, date) {
+		var inst = this._getInst(target);
+		if (inst) {
+			this._setDate(inst, date);
+			this._updateDatepicker(inst);
+			this._updateAlternate(inst);
+		}
+	},
+
+	/* Get the date(s) for the first entry in a jQuery selection.
+	 * @param  target element - the target input field or division or span
+	 * @param  noDefault boolean - true if no default date is to be used
+	 * @return Date - the current date
+	 */
+	_getDateDatepicker: function(target, noDefault) {
+		var inst = this._getInst(target);
+		if (inst && !inst.inline) {
+			this._setDateFromField(inst, noDefault);
+		}
+		return (inst ? this._getDate(inst) : null);
+	},
+
+	/* Handle keystrokes. */
+	_doKeyDown: function(event) {
+		var onSelect, dateStr, sel,
+			inst = $.datepicker._getInst(event.target),
+			handled = true,
+			isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
+
+		inst._keyEvent = true;
+		if ($.datepicker._datepickerShowing) {
+			switch (event.keyCode) {
+				case 9: $.datepicker._hideDatepicker();
+						handled = false;
+						break; // hide on tab out
+				case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
+									$.datepicker._currentClass + ")", inst.dpDiv);
+						if (sel[0]) {
+							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+						}
+
+						onSelect = $.datepicker._get(inst, "onSelect");
+						if (onSelect) {
+							dateStr = $.datepicker._formatDate(inst);
+
+							// trigger custom callback
+							onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
+						} else {
+							$.datepicker._hideDatepicker();
+						}
+
+						return false; // don't submit the form
+				case 27: $.datepicker._hideDatepicker();
+						break; // hide on escape
+				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+							-$.datepicker._get(inst, "stepBigMonths") :
+							-$.datepicker._get(inst, "stepMonths")), "M");
+						break; // previous month/year on page up/+ ctrl
+				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+							+$.datepicker._get(inst, "stepBigMonths") :
+							+$.datepicker._get(inst, "stepMonths")), "M");
+						break; // next month/year on page down/+ ctrl
+				case 35: if (event.ctrlKey || event.metaKey) {
+							$.datepicker._clearDate(event.target);
+						}
+						handled = event.ctrlKey || event.metaKey;
+						break; // clear on ctrl or command +end
+				case 36: if (event.ctrlKey || event.metaKey) {
+							$.datepicker._gotoToday(event.target);
+						}
+						handled = event.ctrlKey || event.metaKey;
+						break; // current on ctrl or command +home
+				case 37: if (event.ctrlKey || event.metaKey) {
+							$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
+						}
+						handled = event.ctrlKey || event.metaKey;
+						// -1 day on ctrl or command +left
+						if (event.originalEvent.altKey) {
+							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
+								-$.datepicker._get(inst, "stepBigMonths") :
+								-$.datepicker._get(inst, "stepMonths")), "M");
+						}
+						// next month/year on alt +left on Mac
+						break;
+				case 38: if (event.ctrlKey || event.metaKey) {
+							$.datepicker._adjustDate(event.target, -7, "D");
+						}
+						handled = event.ctrlKey || event.metaKey;
+						break; // -1 week on ctrl or command +up
+				case 39: if (event.ctrlKey || event.metaKey) {
+							$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
+						}
+						handled = event.ctrlKey || event.metaKey;
+						// +1 day on ctrl or command +right
+						if (event.originalEvent.altKey) {
+							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
+								+$.datepicker._get(inst, "stepBigMonths") :
+								+$.datepicker._get(inst, "stepMonths")), "M");
+						}
+						// next month/year on alt +right
+						break;
+				case 40: if (event.ctrlKey || event.metaKey) {
+							$.datepicker._adjustDate(event.target, +7, "D");
+						}
+						handled = event.ctrlKey || event.metaKey;
+						break; // +1 week on ctrl or command +down
+				default: handled = false;
+			}
+		} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
+			$.datepicker._showDatepicker(this);
+		} else {
+			handled = false;
+		}
+
+		if (handled) {
+			event.preventDefault();
+			event.stopPropagation();
+		}
+	},
+
+	/* Filter entered characters - based on date format. */
+	_doKeyPress: function(event) {
+		var chars, chr,
+			inst = $.datepicker._getInst(event.target);
+
+		if ($.datepicker._get(inst, "constrainInput")) {
+			chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
+			chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
+			return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
+		}
+	},
+
+	/* Synchronise manual entry and field/alternate field. */
+	_doKeyUp: function(event) {
+		var date,
+			inst = $.datepicker._getInst(event.target);
+
+		if (inst.input.val() !== inst.lastVal) {
+			try {
+				date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
+					(inst.input ? inst.input.val() : null),
+					$.datepicker._getFormatConfig(inst));
+
+				if (date) { // only if valid
+					$.datepicker._setDateFromField(inst);
+					$.datepicker._updateAlternate(inst);
+					$.datepicker._updateDatepicker(inst);
+				}
+			}
+			catch (err) {
+			}
+		}
+		return true;
+	},
+
+	/* Pop-up the date picker for a given input field.
+	 * If false returned from beforeShow event handler do not show.
+	 * @param  input  element - the input field attached to the date picker or
+	 *					event - if triggered by focus
+	 */
+	_showDatepicker: function(input) {
+		input = input.target || input;
+		if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
+			input = $("input", input.parentNode)[0];
+		}
+
+		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
+			return;
+		}
+
+		var inst, beforeShow, beforeShowSettings, isFixed,
+			offset, showAnim, duration;
+
+		inst = $.datepicker._getInst(input);
+		if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
+			$.datepicker._curInst.dpDiv.stop(true, true);
+			if ( inst && $.datepicker._datepickerShowing ) {
+				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
+			}
+		}
+
+		beforeShow = $.datepicker._get(inst, "beforeShow");
+		beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
+		if(beforeShowSettings === false){
+			return;
+		}
+		datepicker_extendRemove(inst.settings, beforeShowSettings);
+
+		inst.lastVal = null;
+		$.datepicker._lastInput = input;
+		$.datepicker._setDateFromField(inst);
+
+		if ($.datepicker._inDialog) { // hide cursor
+			input.value = "";
+		}
+		if (!$.datepicker._pos) { // position below input
+			$.datepicker._pos = $.datepicker._findPos(input);
+			$.datepicker._pos[1] += input.offsetHeight; // add the height
+		}
+
+		isFixed = false;
+		$(input).parents().each(function() {
+			isFixed |= $(this).css("position") === "fixed";
+			return !isFixed;
+		});
+
+		offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
+		$.datepicker._pos = null;
+		//to avoid flashes on Firefox
+		inst.dpDiv.empty();
+		// determine sizing offscreen
+		inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
+		$.datepicker._updateDatepicker(inst);
+		// fix width for dynamic number of date pickers
+		// and adjust position before showing
+		offset = $.datepicker._checkOffset(inst, offset, isFixed);
+		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
+			"static" : (isFixed ? "fixed" : "absolute")), display: "none",
+			left: offset.left + "px", top: offset.top + "px"});
+
+		if (!inst.inline) {
+			showAnim = $.datepicker._get(inst, "showAnim");
+			duration = $.datepicker._get(inst, "duration");
+			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
+			$.datepicker._datepickerShowing = true;
+
+			if ( $.effects && $.effects.effect[ showAnim ] ) {
+				inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
+			} else {
+				inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
+			}
+
+			if ( $.datepicker._shouldFocusInput( inst ) ) {
+				inst.input.focus();
+			}
+
+			$.datepicker._curInst = inst;
+		}
+	},
+
+	/* Generate the date picker content. */
+	_updateDatepicker: function(inst) {
+		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
+		datepicker_instActive = inst; // for delegate hover events
+		inst.dpDiv.empty().append(this._generateHTML(inst));
+		this._attachHandlers(inst);
+
+		var origyearshtml,
+			numMonths = this._getNumberOfMonths(inst),
+			cols = numMonths[1],
+			width = 17,
+			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
+
+		if ( activeCell.length > 0 ) {
+			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
+		}
+
+		inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
+		if (cols > 1) {
+			inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
+		}
+		inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
+			"Class"]("ui-datepicker-multi");
+		inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
+			"Class"]("ui-datepicker-rtl");
+
+		if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
+			inst.input.focus();
+		}
+
+		// deffered render of the years select (to avoid flashes on Firefox)
+		if( inst.yearshtml ){
+			origyearshtml = inst.yearshtml;
+			setTimeout(function(){
+				//assure that inst.yearshtml didn't change.
+				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
+					inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
+				}
+				origyearshtml = inst.yearshtml = null;
+			}, 0);
+		}
+	},
+
+	// #6694 - don't focus the input if it's already focused
+	// this breaks the change event in IE
+	// Support: IE and jQuery <1.9
+	_shouldFocusInput: function( inst ) {
+		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
+	},
+
+	/* Check positioning to remain on screen. */
+	_checkOffset: function(inst, offset, isFixed) {
+		var dpWidth = inst.dpDiv.outerWidth(),
+			dpHeight = inst.dpDiv.outerHeight(),
+			inputWidth = inst.input ? inst.input.outerWidth() : 0,
+			inputHeight = inst.input ? inst.input.outerHeight() : 0,
+			viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
+			viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
+
+		offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
+		offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
+		offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
+
+		// now check if datepicker is showing outside window viewport - move to a better place if so.
+		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
+			Math.abs(offset.left + dpWidth - viewWidth) : 0);
+		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
+			Math.abs(dpHeight + inputHeight) : 0);
+
+		return offset;
+	},
+
+	/* Find an object's position on the screen. */
+	_findPos: function(obj) {
+		var position,
+			inst = this._getInst(obj),
+			isRTL = this._get(inst, "isRTL");
+
+		while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
+			obj = obj[isRTL ? "previousSibling" : "nextSibling"];
+		}
+
+		position = $(obj).offset();
+		return [position.left, position.top];
+	},
+
+	/* Hide the date picker from view.
+	 * @param  input  element - the input field attached to the date picker
+	 */
+	_hideDatepicker: function(input) {
+		var showAnim, duration, postProcess, onClose,
+			inst = this._curInst;
+
+		if (!inst || (input && inst !== $.data(input, "datepicker"))) {
+			return;
+		}
+
+		if (this._datepickerShowing) {
+			showAnim = this._get(inst, "showAnim");
+			duration = this._get(inst, "duration");
+			postProcess = function() {
+				$.datepicker._tidyDialog(inst);
+			};
+
+			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
+			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
+				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
+			} else {
+				inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
+					(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
+			}
+
+			if (!showAnim) {
+				postProcess();
+			}
+			this._datepickerShowing = false;
+
+			onClose = this._get(inst, "onClose");
+			if (onClose) {
+				onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
+			}
+
+			this._lastInput = null;
+			if (this._inDialog) {
+				this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
+				if ($.blockUI) {
+					$.unblockUI();
+					$("body").append(this.dpDiv);
+				}
+			}
+			this._inDialog = false;
+		}
+	},
+
+	/* Tidy up after a dialog display. */
+	_tidyDialog: function(inst) {
+		inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
+	},
+
+	/* Close date picker if clicked elsewhere. */
+	_checkExternalClick: function(event) {
+		if (!$.datepicker._curInst) {
+			return;
+		}
+
+		var $target = $(event.target),
+			inst = $.datepicker._getInst($target[0]);
+
+		if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
+				$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
+				!$target.hasClass($.datepicker.markerClassName) &&
+				!$target.closest("." + $.datepicker._triggerClass).length &&
+				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
+			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
+				$.datepicker._hideDatepicker();
+		}
+	},
+
+	/* Adjust one of the date sub-fields. */
+	_adjustDate: function(id, offset, period) {
+		var target = $(id),
+			inst = this._getInst(target[0]);
+
+		if (this._isDisabledDatepicker(target[0])) {
+			return;
+		}
+		this._adjustInstDate(inst, offset +
+			(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
+			period);
+		this._updateDatepicker(inst);
+	},
+
+	/* Action for current link. */
+	_gotoToday: function(id) {
+		var date,
+			target = $(id),
+			inst = this._getInst(target[0]);
+
+		if (this._get(inst, "gotoCurrent") && inst.currentDay) {
+			inst.selectedDay = inst.currentDay;
+			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
+			inst.drawYear = inst.selectedYear = inst.currentYear;
+		} else {
+			date = new Date();
+			inst.selectedDay = date.getDate();
+			inst.drawMonth = inst.selectedMonth = date.getMonth();
+			inst.drawYear = inst.selectedYear = date.getFullYear();
+		}
+		this._notifyChange(inst);
+		this._adjustDate(target);
+	},
+
+	/* Action for selecting a new month/year. */
+	_selectMonthYear: function(id, select, period) {
+		var target = $(id),
+			inst = this._getInst(target[0]);
+
+		inst["selected" + (period === "M" ? "Month" : "Year")] =
+		inst["draw" + (period === "M" ? "Month" : "Year")] =
+			parseInt(select.options[select.selectedIndex].value,10);
+
+		this._notifyChange(inst);
+		this._adjustDate(target);
+	},
+
+	/* Action for selecting a day. */
+	_selectDay: function(id, month, year, td) {
+		var inst,
+			target = $(id);
+
+		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
+			return;
+		}
+
+		inst = this._getInst(target[0]);
+		inst.selectedDay = inst.currentDay = $("a", td).html();
+		inst.selectedMonth = inst.currentMonth = month;
+		inst.selectedYear = inst.currentYear = year;
+		this._selectDate(id, this._formatDate(inst,
+			inst.currentDay, inst.currentMonth, inst.currentYear));
+	},
+
+	/* Erase the input field and hide the date picker. */
+	_clearDate: function(id) {
+		var target = $(id);
+		this._selectDate(target, "");
+	},
+
+	/* Update the input field with the selected date. */
+	_selectDate: function(id, dateStr) {
+		var onSelect,
+			target = $(id),
+			inst = this._getInst(target[0]);
+
+		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
+		if (inst.input) {
+			inst.input.val(dateStr);
+		}
+		this._updateAlternate(inst);
+
+		onSelect = this._get(inst, "onSelect");
+		if (onSelect) {
+			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
+		} else if (inst.input) {
+			inst.input.trigger("change"); // fire the change event
+		}
+
+		if (inst.inline){
+			this._updateDatepicker(inst);
+		} else {
+			this._hideDatepicker();
+			this._lastInput = inst.input[0];
+			if (typeof(inst.input[0]) !== "object") {
+				inst.input.focus(); // restore focus
+			}
+			this._lastInput = null;
+		}
+	},
+
+	/* Update any alternate field to synchronise with the main field. */
+	_updateAlternate: function(inst) {
+		var altFormat, date, dateStr,
+			altField = this._get(inst, "altField");
+
+		if (altField) { // update alternate field too
+			altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
+			date = this._getDate(inst);
+			dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
+			$(altField).each(function() { $(this).val(dateStr); });
+		}
+	},
+
+	/* Set as beforeShowDay function to prevent selection of weekends.
+	 * @param  date  Date - the date to customise
+	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
+	 */
+	noWeekends: function(date) {
+		var day = date.getDay();
+		return [(day > 0 && day < 6), ""];
+	},
+
+	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
+	 * @param  date  Date - the date to get the week for
+	 * @return  number - the number of the week within the year that contains this date
+	 */
+	iso8601Week: function(date) {
+		var time,
+			checkDate = new Date(date.getTime());
+
+		// Find Thursday of this week starting on Monday
+		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+
+		time = checkDate.getTime();
+		checkDate.setMonth(0); // Compare with Jan 1
+		checkDate.setDate(1);
+		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+	},
+
+	/* Parse a string value into a date object.
+	 * See formatDate below for the possible formats.
+	 *
+	 * @param  format string - the expected format of the date
+	 * @param  value string - the date in the above format
+	 * @param  settings Object - attributes include:
+	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
+	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
+	 *					dayNames		string[7] - names of the days from Sunday (optional)
+	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
+	 *					monthNames		string[12] - names of the months (optional)
+	 * @return  Date - the extracted date value or null if value is blank
+	 */
+	parseDate: function (format, value, settings) {
+		if (format == null || value == null) {
+			throw "Invalid arguments";
+		}
+
+		value = (typeof value === "object" ? value.toString() : value + "");
+		if (value === "") {
+			return null;
+		}
+
+		var iFormat, dim, extra,
+			iValue = 0,
+			shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
+			shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
+				new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
+			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
+			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
+			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
+			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
+			year = -1,
+			month = -1,
+			day = -1,
+			doy = -1,
+			literal = false,
+			date,
+			// Check whether a format character is doubled
+			lookAhead = function(match) {
+				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
+				if (matches) {
+					iFormat++;
+				}
+				return matches;
+			},
+			// Extract a number from the string value
+			getNumber = function(match) {
+				var isDoubled = lookAhead(match),
+					size = (match === "@" ? 14 : (match === "!" ? 20 :
+					(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
+					minSize = (match === "y" ? size : 1),
+					digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
+					num = value.substring(iValue).match(digits);
+				if (!num) {
+					throw "Missing number at position " + iValue;
+				}
+				iValue += num[0].length;
+				return parseInt(num[0], 10);
+			},
+			// Extract a name from the string value and convert to an index
+			getName = function(match, shortNames, longNames) {
+				var index = -1,
+					names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
+						return [ [k, v] ];
+					}).sort(function (a, b) {
+						return -(a[1].length - b[1].length);
+					});
+
+				$.each(names, function (i, pair) {
+					var name = pair[1];
+					if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
+						index = pair[0];
+						iValue += name.length;
+						return false;
+					}
+				});
+				if (index !== -1) {
+					return index + 1;
+				} else {
+					throw "Unknown name at position " + iValue;
+				}
+			},
+			// Confirm that a literal character matches the string value
+			checkLiteral = function() {
+				if (value.charAt(iValue) !== format.charAt(iFormat)) {
+					throw "Unexpected literal at position " + iValue;
+				}
+				iValue++;
+			};
+
+		for (iFormat = 0; iFormat < format.length; iFormat++) {
+			if (literal) {
+				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
+					literal = false;
+				} else {
+					checkLiteral();
+				}
+			} else {
+				switch (format.charAt(iFormat)) {
+					case "d":
+						day = getNumber("d");
+						break;
+					case "D":
+						getName("D", dayNamesShort, dayNames);
+						break;
+					case "o":
+						doy = getNumber("o");
+						break;
+					case "m":
+						month = getNumber("m");
+						break;
+					case "M":
+						month = getName("M", monthNamesShort, monthNames);
+						break;
+					case "y":
+						year = getNumber("y");
+						break;
+					case "@":
+						date = new Date(getNumber("@"));
+						year = date.getFullYear();
+						month = date.getMonth() + 1;
+						day = date.getDate();
+						break;
+					case "!":
+						date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
+						year = date.getFullYear();
+						month = date.getMonth() + 1;
+						day = date.getDate();
+						break;
+					case "'":
+						if (lookAhead("'")){
+							checkLiteral();
+						} else {
+							literal = true;
+						}
+						break;
+					default:
+						checkLiteral();
+				}
+			}
+		}
+
+		if (iValue < value.length){
+			extra = value.substr(iValue);
+			if (!/^\s+/.test(extra)) {
+				throw "Extra/unparsed characters found in date: " + extra;
+			}
+		}
+
+		if (year === -1) {
+			year = new Date().getFullYear();
+		} else if (year < 100) {
+			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
+				(year <= shortYearCutoff ? 0 : -100);
+		}
+
+		if (doy > -1) {
+			month = 1;
+			day = doy;
+			do {
+				dim = this._getDaysInMonth(year, month - 1);
+				if (day <= dim) {
+					break;
+				}
+				month++;
+				day -= dim;
+			} while (true);
+		}
+
+		date = this._daylightSavingAdjust(new Date(year, month - 1, day));
+		if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
+			throw "Invalid date"; // E.g. 31/02/00
+		}
+		return date;
+	},
+
+	/* Standard date formats. */
+	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
+	COOKIE: "D, dd M yy",
+	ISO_8601: "yy-mm-dd",
+	RFC_822: "D, d M y",
+	RFC_850: "DD, dd-M-y",
+	RFC_1036: "D, d M y",
+	RFC_1123: "D, d M yy",
+	RFC_2822: "D, d M yy",
+	RSS: "D, d M y", // RFC 822
+	TICKS: "!",
+	TIMESTAMP: "@",
+	W3C: "yy-mm-dd", // ISO 8601
+
+	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
+		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
+
+	/* Format a date object into a string value.
+	 * The format can be combinations of the following:
+	 * d  - day of month (no leading zero)
+	 * dd - day of month (two digit)
+	 * o  - day of year (no leading zeros)
+	 * oo - day of year (three digit)
+	 * D  - day name short
+	 * DD - day name long
+	 * m  - month of year (no leading zero)
+	 * mm - month of year (two digit)
+	 * M  - month name short
+	 * MM - month name long
+	 * y  - year (two digit)
+	 * yy - year (four digit)
+	 * @ - Unix timestamp (ms since 01/01/1970)
+	 * ! - Windows ticks (100ns since 01/01/0001)
+	 * "..." - literal text
+	 * '' - single quote
+	 *
+	 * @param  format string - the desired format of the date
+	 * @param  date Date - the date value to format
+	 * @param  settings Object - attributes include:
+	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
+	 *					dayNames		string[7] - names of the days from Sunday (optional)
+	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
+	 *					monthNames		string[12] - names of the months (optional)
+	 * @return  string - the date in the above format
+	 */
+	formatDate: function (format, date, settings) {
+		if (!date) {
+			return "";
+		}
+
+		var iFormat,
+			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
+			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
+			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
+			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
+			// Check whether a format character is doubled
+			lookAhead = function(match) {
+				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
+				if (matches) {
+					iFormat++;
+				}
+				return matches;
+			},
+			// Format a number, with leading zero if necessary
+			formatNumber = function(match, value, len) {
+				var num = "" + value;
+				if (lookAhead(match)) {
+					while (num.length < len) {
+						num = "0" + num;
+					}
+				}
+				return num;
+			},
+			// Format a name, short or long as requested
+			formatName = function(match, value, shortNames, longNames) {
+				return (lookAhead(match) ? longNames[value] : shortNames[value]);
+			},
+			output = "",
+			literal = false;
+
+		if (date) {
+			for (iFormat = 0; iFormat < format.length; iFormat++) {
+				if (literal) {
+					if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
+						literal = false;
+					} else {
+						output += format.charAt(iFormat);
+					}
+				} else {
+					switch (format.charAt(iFormat)) {
+						case "d":
+							output += formatNumber("d", date.getDate(), 2);
+							break;
+						case "D":
+							output += formatName("D", date.getDay(), dayNamesShort, dayNames);
+							break;
+						case "o":
+							output += formatNumber("o",
+								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
+							break;
+						case "m":
+							output += formatNumber("m", date.getMonth() + 1, 2);
+							break;
+						case "M":
+							output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
+							break;
+						case "y":
+							output += (lookAhead("y") ? date.getFullYear() :
+								(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
+							break;
+						case "@":
+							output += date.getTime();
+							break;
+						case "!":
+							output += date.getTime() * 10000 + this._ticksTo1970;
+							break;
+						case "'":
+							if (lookAhead("'")) {
+								output += "'";
+							} else {
+								literal = true;
+							}
+							break;
+						default:
+							output += format.charAt(iFormat);
+					}
+				}
+			}
+		}
+		return output;
+	},
+
+	/* Extract all possible characters from the date format. */
+	_possibleChars: function (format) {
+		var iFormat,
+			chars = "",
+			literal = false,
+			// Check whether a format character is doubled
+			lookAhead = function(match) {
+				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
+				if (matches) {
+					iFormat++;
+				}
+				return matches;
+			};
+
+		for (iFormat = 0; iFormat < format.length; iFormat++) {
+			if (literal) {
+				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
+					literal = false;
+				} else {
+					chars += format.charAt(iFormat);
+				}
+			} else {
+				switch (format.charAt(iFormat)) {
+					case "d": case "m": case "y": case "@":
+						chars += "0123456789";
+						break;
+					case "D": case "M":
+						return null; // Accept anything
+					case "'":
+						if (lookAhead("'")) {
+							chars += "'";
+						} else {
+							literal = true;
+						}
+						break;
+					default:
+						chars += format.charAt(iFormat);
+				}
+			}
+		}
+		return chars;
+	},
+
+	/* Get a setting value, defaulting if necessary. */
+	_get: function(inst, name) {
+		return inst.settings[name] !== undefined ?
+			inst.settings[name] : this._defaults[name];
+	},
+
+	/* Parse existing date and initialise date picker. */
+	_setDateFromField: function(inst, noDefault) {
+		if (inst.input.val() === inst.lastVal) {
+			return;
+		}
+
+		var dateFormat = this._get(inst, "dateFormat"),
+			dates = inst.lastVal = inst.input ? inst.input.val() : null,
+			defaultDate = this._getDefaultDate(inst),
+			date = defaultDate,
+			settings = this._getFormatConfig(inst);
+
+		try {
+			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+		} catch (event) {
+			dates = (noDefault ? "" : dates);
+		}
+		inst.selectedDay = date.getDate();
+		inst.drawMonth = inst.selectedMonth = date.getMonth();
+		inst.drawYear = inst.selectedYear = date.getFullYear();
+		inst.currentDay = (dates ? date.getDate() : 0);
+		inst.currentMonth = (dates ? date.getMonth() : 0);
+		inst.currentYear = (dates ? date.getFullYear() : 0);
+		this._adjustInstDate(inst);
+	},
+
+	/* Retrieve the default date shown on opening. */
+	_getDefaultDate: function(inst) {
+		return this._restrictMinMax(inst,
+			this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
+	},
+
+	/* A date may be specified as an exact value or a relative one. */
+	_determineDate: function(inst, date, defaultDate) {
+		var offsetNumeric = function(offset) {
+				var date = new Date();
+				date.setDate(date.getDate() + offset);
+				return date;
+			},
+			offsetString = function(offset) {
+				try {
+					return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
+						offset, $.datepicker._getFormatConfig(inst));
+				}
+				catch (e) {
+					// Ignore
+				}
+
+				var date = (offset.toLowerCase().match(/^c/) ?
+					$.datepicker._getDate(inst) : null) || new Date(),
+					year = date.getFullYear(),
+					month = date.getMonth(),
+					day = date.getDate(),
+					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
+					matches = pattern.exec(offset);
+
+				while (matches) {
+					switch (matches[2] || "d") {
+						case "d" : case "D" :
+							day += parseInt(matches[1],10); break;
+						case "w" : case "W" :
+							day += parseInt(matches[1],10) * 7; break;
+						case "m" : case "M" :
+							month += parseInt(matches[1],10);
+							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+							break;
+						case "y": case "Y" :
+							year += parseInt(matches[1],10);
+							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+							break;
+					}
+					matches = pattern.exec(offset);
+				}
+				return new Date(year, month, day);
+			},
+			newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
+				(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
+
+		newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
+		if (newDate) {
+			newDate.setHours(0);
+			newDate.setMinutes(0);
+			newDate.setSeconds(0);
+			newDate.setMilliseconds(0);
+		}
+		return this._daylightSavingAdjust(newDate);
+	},
+
+	/* Handle switch to/from daylight saving.
+	 * Hours may be non-zero on daylight saving cut-over:
+	 * > 12 when midnight changeover, but then cannot generate
+	 * midnight datetime, so jump to 1AM, otherwise reset.
+	 * @param  date  (Date) the date to check
+	 * @return  (Date) the corrected date
+	 */
+	_daylightSavingAdjust: function(date) {
+		if (!date) {
+			return null;
+		}
+		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+		return date;
+	},
+
+	/* Set the date(s) directly. */
+	_setDate: function(inst, date, noChange) {
+		var clear = !date,
+			origMonth = inst.selectedMonth,
+			origYear = inst.selectedYear,
+			newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
+
+		inst.selectedDay = inst.currentDay = newDate.getDate();
+		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
+		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
+		if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
+			this._notifyChange(inst);
+		}
+		this._adjustInstDate(inst);
+		if (inst.input) {
+			inst.input.val(clear ? "" : this._formatDate(inst));
+		}
+	},
+
+	/* Retrieve the date(s) directly. */
+	_getDate: function(inst) {
+		var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
+			this._daylightSavingAdjust(new Date(
+			inst.currentYear, inst.currentMonth, inst.currentDay)));
+			return startDate;
+	},
+
+	/* Attach the onxxx handlers.  These are declared statically so
+	 * they work with static code transformers like Caja.
+	 */
+	_attachHandlers: function(inst) {
+		var stepMonths = this._get(inst, "stepMonths"),
+			id = "#" + inst.id.replace( /\\\\/g, "\\" );
+		inst.dpDiv.find("[data-handler]").map(function () {
+			var handler = {
+				prev: function () {
+					$.datepicker._adjustDate(id, -stepMonths, "M");
+				},
+				next: function () {
+					$.datepicker._adjustDate(id, +stepMonths, "M");
+				},
+				hide: function () {
+					$.datepicker._hideDatepicker();
+				},
+				today: function () {
+					$.datepicker._gotoToday(id);
+				},
+				selectDay: function () {
+					$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
+					return false;
+				},
+				selectMonth: function () {
+					$.datepicker._selectMonthYear(id, this, "M");
+					return false;
+				},
+				selectYear: function () {
+					$.datepicker._selectMonthYear(id, this, "Y");
+					return false;
+				}
+			};
+			$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
+		});
+	},
+
+	/* Generate the HTML for the current state of the date picker. */
+	_generateHTML: function(inst) {
+		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
+			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
+			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
+			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
+			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
+			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
+			tempDate = new Date(),
+			today = this._daylightSavingAdjust(
+				new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
+			isRTL = this._get(inst, "isRTL"),
+			showButtonPanel = this._get(inst, "showButtonPanel"),
+			hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
+			navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
+			numMonths = this._getNumberOfMonths(inst),
+			showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
+			stepMonths = this._get(inst, "stepMonths"),
+			isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
+			currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
+				new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
+			minDate = this._getMinMaxDate(inst, "min"),
+			maxDate = this._getMinMaxDate(inst, "max"),
+			drawMonth = inst.drawMonth - showCurrentAtPos,
+			drawYear = inst.drawYear;
+
+		if (drawMonth < 0) {
+			drawMonth += 12;
+			drawYear--;
+		}
+		if (maxDate) {
+			maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
+				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
+			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
+			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
+				drawMonth--;
+				if (drawMonth < 0) {
+					drawMonth = 11;
+					drawYear--;
+				}
+			}
+		}
+		inst.drawMonth = drawMonth;
+		inst.drawYear = drawYear;
+
+		prevText = this._get(inst, "prevText");
+		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
+			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
+			this._getFormatConfig(inst)));
+
+		prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
+			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
+			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
+			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
+
+		nextText = this._get(inst, "nextText");
+		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
+			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
+			this._getFormatConfig(inst)));
+
+		next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
+			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
+			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
+			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
+
+		currentText = this._get(inst, "currentText");
+		gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
+		currentText = (!navigationAsDateFormat ? currentText :
+			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
+
+		controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
+			this._get(inst, "closeText") + "</button>" : "");
+
+		buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
+			(this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
+			">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
+
+		firstDay = parseInt(this._get(inst, "firstDay"),10);
+		firstDay = (isNaN(firstDay) ? 0 : firstDay);
+
+		showWeek = this._get(inst, "showWeek");
+		dayNames = this._get(inst, "dayNames");
+		dayNamesMin = this._get(inst, "dayNamesMin");
+		monthNames = this._get(inst, "monthNames");
+		monthNamesShort = this._get(inst, "monthNamesShort");
+		beforeShowDay = this._get(inst, "beforeShowDay");
+		showOtherMonths = this._get(inst, "showOtherMonths");
+		selectOtherMonths = this._get(inst, "selectOtherMonths");
+		defaultDate = this._getDefaultDate(inst);
+		html = "";
+		dow;
+		for (row = 0; row < numMonths[0]; row++) {
+			group = "";
+			this.maxRows = 4;
+			for (col = 0; col < numMonths[1]; col++) {
+				selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
+				cornerClass = " ui-corner-all";
+				calender = "";
+				if (isMultiMonth) {
+					calender += "<div class='ui-datepicker-group";
+					if (numMonths[1] > 1) {
+						switch (col) {
+							case 0: calender += " ui-datepicker-group-first";
+								cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
+							case numMonths[1]-1: calender += " ui-datepicker-group-last";
+								cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
+							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
+						}
+					}
+					calender += "'>";
+				}
+				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
+					(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
+					(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
+					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
+					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+					"</div><table class='ui-datepicker-calendar'><thead>" +
+					"<tr>";
+				thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
+				for (dow = 0; dow < 7; dow++) { // days of the week
+					day = (dow + firstDay) % 7;
+					thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
+						"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
+				}
+				calender += thead + "</tr></thead><tbody>";
+				daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
+				if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
+					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
+				}
+				leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
+				curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
+				numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
+				this.maxRows = numRows;
+				printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
+				for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
+					calender += "<tr>";
+					tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
+						this._get(inst, "calculateWeek")(printDate) + "</td>");
+					for (dow = 0; dow < 7; dow++) { // create date picker days
+						daySettings = (beforeShowDay ?
+							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
+						otherMonth = (printDate.getMonth() !== drawMonth);
+						unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
+							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
+						tbody += "<td class='" +
+							((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
+							(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
+							((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
+							(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
+							// or defaultDate is current printedDate and defaultDate is selectedDate
+							" " + this._dayOverClass : "") + // highlight selected day
+							(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
+							(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
+							(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
+							(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
+							((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
+							(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
+							(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
+							(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
+							(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
+							(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
+							(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
+							"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
+						printDate.setDate(printDate.getDate() + 1);
+						printDate = this._daylightSavingAdjust(printDate);
+					}
+					calender += tbody + "</tr>";
+				}
+				drawMonth++;
+				if (drawMonth > 11) {
+					drawMonth = 0;
+					drawYear++;
+				}
+				calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
+							((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
+				group += calender;
+			}
+			html += group;
+		}
+		html += buttonPanel;
+		inst._keyEvent = false;
+		return html;
+	},
+
+	/* Generate the month and year header. */
+	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
+			secondary, monthNames, monthNamesShort) {
+
+		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
+			changeMonth = this._get(inst, "changeMonth"),
+			changeYear = this._get(inst, "changeYear"),
+			showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
+			html = "<div class='ui-datepicker-title'>",
+			monthHtml = "";
+
+		// month selection
+		if (secondary || !changeMonth) {
+			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
+		} else {
+			inMinYear = (minDate && minDate.getFullYear() === drawYear);
+			inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
+			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
+			for ( month = 0; month < 12; month++) {
+				if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
+					monthHtml += "<option value='" + month + "'" +
+						(month === drawMonth ? " selected='selected'" : "") +
+						">" + monthNamesShort[month] + "</option>";
+				}
+			}
+			monthHtml += "</select>";
+		}
+
+		if (!showMonthAfterYear) {
+			html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
+		}
+
+		// year selection
+		if ( !inst.yearshtml ) {
+			inst.yearshtml = "";
+			if (secondary || !changeYear) {
+				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
+			} else {
+				// determine range of years to display
+				years = this._get(inst, "yearRange").split(":");
+				thisYear = new Date().getFullYear();
+				determineYear = function(value) {
+					var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
+						(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
+						parseInt(value, 10)));
+					return (isNaN(year) ? thisYear : year);
+				};
+				year = determineYear(years[0]);
+				endYear = Math.max(year, determineYear(years[1] || ""));
+				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
+				for (; year <= endYear; year++) {
+					inst.yearshtml += "<option value='" + year + "'" +
+						(year === drawYear ? " selected='selected'" : "") +
+						">" + year + "</option>";
+				}
+				inst.yearshtml += "</select>";
+
+				html += inst.yearshtml;
+				inst.yearshtml = null;
+			}
+		}
+
+		html += this._get(inst, "yearSuffix");
+		if (showMonthAfterYear) {
+			html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
+		}
+		html += "</div>"; // Close datepicker_header
+		return html;
+	},
+
+	/* Adjust one of the date sub-fields. */
+	_adjustInstDate: function(inst, offset, period) {
+		var year = inst.drawYear + (period === "Y" ? offset : 0),
+			month = inst.drawMonth + (period === "M" ? offset : 0),
+			day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
+			date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
+
+		inst.selectedDay = date.getDate();
+		inst.drawMonth = inst.selectedMonth = date.getMonth();
+		inst.drawYear = inst.selectedYear = date.getFullYear();
+		if (period === "M" || period === "Y") {
+			this._notifyChange(inst);
+		}
+	},
+
+	/* Ensure a date is within any min/max bounds. */
+	_restrictMinMax: function(inst, date) {
+		var minDate = this._getMinMaxDate(inst, "min"),
+			maxDate = this._getMinMaxDate(inst, "max"),
+			newDate = (minDate && date < minDate ? minDate : date);
+		return (maxDate && newDate > maxDate ? maxDate : newDate);
+	},
+
+	/* Notify change of month/year. */
+	_notifyChange: function(inst) {
+		var onChange = this._get(inst, "onChangeMonthYear");
+		if (onChange) {
+			onChange.apply((inst.input ? inst.input[0] : null),
+				[inst.selectedYear, inst.selectedMonth + 1, inst]);
+		}
+	},
+
+	/* Determine the number of months to show. */
+	_getNumberOfMonths: function(inst) {
+		var numMonths = this._get(inst, "numberOfMonths");
+		return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
+	},
+
+	/* Determine the current maximum date - ensure no time components are set. */
+	_getMinMaxDate: function(inst, minMax) {
+		return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
+	},
+
+	/* Find the number of days in a given month. */
+	_getDaysInMonth: function(year, month) {
+		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
+	},
+
+	/* Find the day of the week of the first of a month. */
+	_getFirstDayOfMonth: function(year, month) {
+		return new Date(year, month, 1).getDay();
+	},
+
+	/* Determines if we should allow a "next/prev" month display change. */
+	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
+		var numMonths = this._getNumberOfMonths(inst),
+			date = this._daylightSavingAdjust(new Date(curYear,
+			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
+
+		if (offset < 0) {
+			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
+		}
+		return this._isInRange(inst, date);
+	},
+
+	/* Is the given date in the accepted range? */
+	_isInRange: function(inst, date) {
+		var yearSplit, currentYear,
+			minDate = this._getMinMaxDate(inst, "min"),
+			maxDate = this._getMinMaxDate(inst, "max"),
+			minYear = null,
+			maxYear = null,
+			years = this._get(inst, "yearRange");
+			if (years){
+				yearSplit = years.split(":");
+				currentYear = new Date().getFullYear();
+				minYear = parseInt(yearSplit[0], 10);
+				maxYear = parseInt(yearSplit[1], 10);
+				if ( yearSplit[0].match(/[+\-].*/) ) {
+					minYear += currentYear;
+				}
+				if ( yearSplit[1].match(/[+\-].*/) ) {
+					maxYear += currentYear;
+				}
+			}
+
+		return ((!minDate || date.getTime() >= minDate.getTime()) &&
+			(!maxDate || date.getTime() <= maxDate.getTime()) &&
+			(!minYear || date.getFullYear() >= minYear) &&
+			(!maxYear || date.getFullYear() <= maxYear));
+	},
+
+	/* Provide the configuration settings for formatting/parsing. */
+	_getFormatConfig: function(inst) {
+		var shortYearCutoff = this._get(inst, "shortYearCutoff");
+		shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
+			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+		return {shortYearCutoff: shortYearCutoff,
+			dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
+			monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
+	},
+
+	/* Format the given date for display. */
+	_formatDate: function(inst, day, month, year) {
+		if (!day) {
+			inst.currentDay = inst.selectedDay;
+			inst.currentMonth = inst.selectedMonth;
+			inst.currentYear = inst.selectedYear;
+		}
+		var date = (day ? (typeof day === "object" ? day :
+			this._daylightSavingAdjust(new Date(year, month, day))) :
+			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+		return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
+	}
+});
+
+/*
+ * Bind hover events for datepicker elements.
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
+ * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
+ */
+function datepicker_bindHover(dpDiv) {
+	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
+	return dpDiv.delegate(selector, "mouseout", function() {
+			$(this).removeClass("ui-state-hover");
+			if (this.className.indexOf("ui-datepicker-prev") !== -1) {
+				$(this).removeClass("ui-datepicker-prev-hover");
+			}
+			if (this.className.indexOf("ui-datepicker-next") !== -1) {
+				$(this).removeClass("ui-datepicker-next-hover");
+			}
+		})
+		.delegate( selector, "mouseover", datepicker_handleMouseover );
+}
+
+function datepicker_handleMouseover() {
+	if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
+		$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
+		$(this).addClass("ui-state-hover");
+		if (this.className.indexOf("ui-datepicker-prev") !== -1) {
+			$(this).addClass("ui-datepicker-prev-hover");
+		}
+		if (this.className.indexOf("ui-datepicker-next") !== -1) {
+			$(this).addClass("ui-datepicker-next-hover");
+		}
+	}
+}
+
+/* jQuery extend now ignores nulls! */
+function datepicker_extendRemove(target, props) {
+	$.extend(target, props);
+	for (var name in props) {
+		if (props[name] == null) {
+			target[name] = props[name];
+		}
+	}
+	return target;
+}
+
+/* Invoke the datepicker functionality.
+   @param  options  string - a command, optionally followed by additional parameters or
+					Object - settings for attaching new datepicker functionality
+   @return  jQuery object */
+$.fn.datepicker = function(options){
+
+	/* Verify an empty collection wasn't passed - Fixes #6976 */
+	if ( !this.length ) {
+		return this;
+	}
+
+	/* Initialise the date picker. */
+	if (!$.datepicker.initialized) {
+		$(document).mousedown($.datepicker._checkExternalClick);
+		$.datepicker.initialized = true;
+	}
+
+	/* Append datepicker main container to body if not exist. */
+	if ($("#"+$.datepicker._mainDivId).length === 0) {
+		$("body").append($.datepicker.dpDiv);
+	}
+
+	var otherArgs = Array.prototype.slice.call(arguments, 1);
+	if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
+		return $.datepicker["_" + options + "Datepicker"].
+			apply($.datepicker, [this[0]].concat(otherArgs));
+	}
+	if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
+		return $.datepicker["_" + options + "Datepicker"].
+			apply($.datepicker, [this[0]].concat(otherArgs));
+	}
+	return this.each(function() {
+		typeof options === "string" ?
+			$.datepicker["_" + options + "Datepicker"].
+				apply($.datepicker, [this].concat(otherArgs)) :
+			$.datepicker._attachDatepicker(this, options);
+	});
+};
+
+$.datepicker = new Datepicker(); // singleton instance
+$.datepicker.initialized = false;
+$.datepicker.uuid = new Date().getTime();
+$.datepicker.version = "1.11.4";
+
+var datepicker = $.datepicker;
+
+
+/*!
+ * jQuery UI Draggable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/draggable/
+ */
+
+
+$.widget("ui.draggable", $.ui.mouse, {
+	version: "1.11.4",
+	widgetEventPrefix: "drag",
+	options: {
+		addClasses: true,
+		appendTo: "parent",
+		axis: false,
+		connectToSortable: false,
+		containment: false,
+		cursor: "auto",
+		cursorAt: false,
+		grid: false,
+		handle: false,
+		helper: "original",
+		iframeFix: false,
+		opacity: false,
+		refreshPositions: false,
+		revert: false,
+		revertDuration: 500,
+		scope: "default",
+		scroll: true,
+		scrollSensitivity: 20,
+		scrollSpeed: 20,
+		snap: false,
+		snapMode: "both",
+		snapTolerance: 20,
+		stack: false,
+		zIndex: false,
+
+		// callbacks
+		drag: null,
+		start: null,
+		stop: null
+	},
+	_create: function() {
+
+		if ( this.options.helper === "original" ) {
+			this._setPositionRelative();
+		}
+		if (this.options.addClasses){
+			this.element.addClass("ui-draggable");
+		}
+		if (this.options.disabled){
+			this.element.addClass("ui-draggable-disabled");
+		}
+		this._setHandleClassName();
+
+		this._mouseInit();
+	},
+
+	_setOption: function( key, value ) {
+		this._super( key, value );
+		if ( key === "handle" ) {
+			this._removeHandleClassName();
+			this._setHandleClassName();
+		}
+	},
+
+	_destroy: function() {
+		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
+			this.destroyOnClear = true;
+			return;
+		}
+		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
+		this._removeHandleClassName();
+		this._mouseDestroy();
+	},
+
+	_mouseCapture: function(event) {
+		var o = this.options;
+
+		this._blurActiveElement( event );
+
+		// among others, prevent a drag on a resizable-handle
+		if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
+			return false;
+		}
+
+		//Quit if we're not on a valid handle
+		this.handle = this._getHandle(event);
+		if (!this.handle) {
+			return false;
+		}
+
+		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
+
+		return true;
+
+	},
+
+	_blockFrames: function( selector ) {
+		this.iframeBlocks = this.document.find( selector ).map(function() {
+			var iframe = $( this );
+
+			return $( "<div>" )
+				.css( "position", "absolute" )
+				.appendTo( iframe.parent() )
+				.outerWidth( iframe.outerWidth() )
+				.outerHeight( iframe.outerHeight() )
+				.offset( iframe.offset() )[ 0 ];
+		});
+	},
+
+	_unblockFrames: function() {
+		if ( this.iframeBlocks ) {
+			this.iframeBlocks.remove();
+			delete this.iframeBlocks;
+		}
+	},
+
+	_blurActiveElement: function( event ) {
+		var document = this.document[ 0 ];
+
+		// Only need to blur if the event occurred on the draggable itself, see #10527
+		if ( !this.handleElement.is( event.target ) ) {
+			return;
+		}
+
+		// support: IE9
+		// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
+		try {
+
+			// Support: IE9, IE10
+			// If the <body> is blurred, IE will switch windows, see #9520
+			if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
+
+				// Blur any element that currently has focus, see #4261
+				$( document.activeElement ).blur();
+			}
+		} catch ( error ) {}
+	},
+
+	_mouseStart: function(event) {
+
+		var o = this.options;
+
+		//Create and append the visible helper
+		this.helper = this._createHelper(event);
+
+		this.helper.addClass("ui-draggable-dragging");
+
+		//Cache the helper size
+		this._cacheHelperProportions();
+
+		//If ddmanager is used for droppables, set the global draggable
+		if ($.ui.ddmanager) {
+			$.ui.ddmanager.current = this;
+		}
+
+		/*
+		 * - Position generation -
+		 * This block generates everything position related - it's the core of draggables.
+		 */
+
+		//Cache the margins of the original element
+		this._cacheMargins();
+
+		//Store the helper's css position
+		this.cssPosition = this.helper.css( "position" );
+		this.scrollParent = this.helper.scrollParent( true );
+		this.offsetParent = this.helper.offsetParent();
+		this.hasFixedAncestor = this.helper.parents().filter(function() {
+				return $( this ).css( "position" ) === "fixed";
+			}).length > 0;
+
+		//The element's absolute position on the page minus margins
+		this.positionAbs = this.element.offset();
+		this._refreshOffsets( event );
+
+		//Generate the original position
+		this.originalPosition = this.position = this._generatePosition( event, false );
+		this.originalPageX = event.pageX;
+		this.originalPageY = event.pageY;
+
+		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
+		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+		//Set a containment if given in the options
+		this._setContainment();
+
+		//Trigger event + callbacks
+		if (this._trigger("start", event) === false) {
+			this._clear();
+			return false;
+		}
+
+		//Recache the helper size
+		this._cacheHelperProportions();
+
+		//Prepare the droppable offsets
+		if ($.ui.ddmanager && !o.dropBehaviour) {
+			$.ui.ddmanager.prepareOffsets(this, event);
+		}
+
+		// Reset helper's right/bottom css if they're set and set explicit width/height instead
+		// as this prevents resizing of elements with right/bottom set (see #7772)
+		this._normalizeRightBottom();
+
+		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+
+		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
+		if ( $.ui.ddmanager ) {
+			$.ui.ddmanager.dragStart(this, event);
+		}
+
+		return true;
+	},
+
+	_refreshOffsets: function( event ) {
+		this.offset = {
+			top: this.positionAbs.top - this.margins.top,
+			left: this.positionAbs.left - this.margins.left,
+			scroll: false,
+			parent: this._getParentOffset(),
+			relative: this._getRelativeOffset()
+		};
+
+		this.offset.click = {
+			left: event.pageX - this.offset.left,
+			top: event.pageY - this.offset.top
+		};
+	},
+
+	_mouseDrag: function(event, noPropagation) {
+		// reset any necessary cached properties (see #5009)
+		if ( this.hasFixedAncestor ) {
+			this.offset.parent = this._getParentOffset();
+		}
+
+		//Compute the helpers position
+		this.position = this._generatePosition( event, true );
+		this.positionAbs = this._convertPositionTo("absolute");
+
+		//Call plugins and callbacks and use the resulting position if something is returned
+		if (!noPropagation) {
+			var ui = this._uiHash();
+			if (this._trigger("drag", event, ui) === false) {
+				this._mouseUp({});
+				return false;
+			}
+			this.position = ui.position;
+		}
+
+		this.helper[ 0 ].style.left = this.position.left + "px";
+		this.helper[ 0 ].style.top = this.position.top + "px";
+
+		if ($.ui.ddmanager) {
+			$.ui.ddmanager.drag(this, event);
+		}
+
+		return false;
+	},
+
+	_mouseStop: function(event) {
+
+		//If we are using droppables, inform the manager about the drop
+		var that = this,
+			dropped = false;
+		if ($.ui.ddmanager && !this.options.dropBehaviour) {
+			dropped = $.ui.ddmanager.drop(this, event);
+		}
+
+		//if a drop comes from outside (a sortable)
+		if (this.dropped) {
+			dropped = this.dropped;
+			this.dropped = false;
+		}
+
+		if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
+			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
+				if (that._trigger("stop", event) !== false) {
+					that._clear();
+				}
+			});
+		} else {
+			if (this._trigger("stop", event) !== false) {
+				this._clear();
+			}
+		}
+
+		return false;
+	},
+
+	_mouseUp: function( event ) {
+		this._unblockFrames();
+
+		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
+		if ( $.ui.ddmanager ) {
+			$.ui.ddmanager.dragStop(this, event);
+		}
+
+		// Only need to focus if the event occurred on the draggable itself, see #10527
+		if ( this.handleElement.is( event.target ) ) {
+			// The interaction is over; whether or not the click resulted in a drag, focus the element
+			this.element.focus();
+		}
+
+		return $.ui.mouse.prototype._mouseUp.call(this, event);
+	},
+
+	cancel: function() {
+
+		if (this.helper.is(".ui-draggable-dragging")) {
+			this._mouseUp({});
+		} else {
+			this._clear();
+		}
+
+		return this;
+
+	},
+
+	_getHandle: function(event) {
+		return this.options.handle ?
+			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
+			true;
+	},
+
+	_setHandleClassName: function() {
+		this.handleElement = this.options.handle ?
+			this.element.find( this.options.handle ) : this.element;
+		this.handleElement.addClass( "ui-draggable-handle" );
+	},
+
+	_removeHandleClassName: function() {
+		this.handleElement.removeClass( "ui-draggable-handle" );
+	},
+
+	_createHelper: function(event) {
+
+		var o = this.options,
+			helperIsFunction = $.isFunction( o.helper ),
+			helper = helperIsFunction ?
+				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
+				( o.helper === "clone" ?
+					this.element.clone().removeAttr( "id" ) :
+					this.element );
+
+		if (!helper.parents("body").length) {
+			helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
+		}
+
+		// http://bugs.jqueryui.com/ticket/9446
+		// a helper function can return the original element
+		// which wouldn't have been set to relative in _create
+		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
+			this._setPositionRelative();
+		}
+
+		if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
+			helper.css("position", "absolute");
+		}
+
+		return helper;
+
+	},
+
+	_setPositionRelative: function() {
+		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
+			this.element[ 0 ].style.position = "relative";
+		}
+	},
+
+	_adjustOffsetFromHelper: function(obj) {
+		if (typeof obj === "string") {
+			obj = obj.split(" ");
+		}
+		if ($.isArray(obj)) {
+			obj = { left: +obj[0], top: +obj[1] || 0 };
+		}
+		if ("left" in obj) {
+			this.offset.click.left = obj.left + this.margins.left;
+		}
+		if ("right" in obj) {
+			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+		}
+		if ("top" in obj) {
+			this.offset.click.top = obj.top + this.margins.top;
+		}
+		if ("bottom" in obj) {
+			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+		}
+	},
+
+	_isRootNode: function( element ) {
+		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
+	},
+
+	_getParentOffset: function() {
+
+		//Get the offsetParent and cache its position
+		var po = this.offsetParent.offset(),
+			document = this.document[ 0 ];
+
+		// This is a special case where we need to modify a offset calculated on start, since the following happened:
+		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+		if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
+			po.left += this.scrollParent.scrollLeft();
+			po.top += this.scrollParent.scrollTop();
+		}
+
+		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
+			po = { top: 0, left: 0 };
+		}
+
+		return {
+			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
+			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
+		};
+
+	},
+
+	_getRelativeOffset: function() {
+		if ( this.cssPosition !== "relative" ) {
+			return { top: 0, left: 0 };
+		}
+
+		var p = this.element.position(),
+			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
+
+		return {
+			top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
+			left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
+		};
+
+	},
+
+	_cacheMargins: function() {
+		this.margins = {
+			left: (parseInt(this.element.css("marginLeft"), 10) || 0),
+			top: (parseInt(this.element.css("marginTop"), 10) || 0),
+			right: (parseInt(this.element.css("marginRight"), 10) || 0),
+			bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
+		};
+	},
+
+	_cacheHelperProportions: function() {
+		this.helperProportions = {
+			width: this.helper.outerWidth(),
+			height: this.helper.outerHeight()
+		};
+	},
+
+	_setContainment: function() {
+
+		var isUserScrollable, c, ce,
+			o = this.options,
+			document = this.document[ 0 ];
+
+		this.relativeContainer = null;
+
+		if ( !o.containment ) {
+			this.containment = null;
+			return;
+		}
+
+		if ( o.containment === "window" ) {
+			this.containment = [
+				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
+				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
+				$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
+				$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
+			];
+			return;
+		}
+
+		if ( o.containment === "document") {
+			this.containment = [
+				0,
+				0,
+				$( document ).width() - this.helperProportions.width - this.margins.left,
+				( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
+			];
+			return;
+		}
+
+		if ( o.containment.constructor === Array ) {
+			this.containment = o.containment;
+			return;
+		}
+
+		if ( o.containment === "parent" ) {
+			o.containment = this.helper[ 0 ].parentNode;
+		}
+
+		c = $( o.containment );
+		ce = c[ 0 ];
+
+		if ( !ce ) {
+			return;
+		}
+
+		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
+
+		this.containment = [
+			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
+			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
+			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
+				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
+				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
+				this.helperProportions.width -
+				this.margins.left -
+				this.margins.right,
+			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
+				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
+				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
+				this.helperProportions.height -
+				this.margins.top -
+				this.margins.bottom
+		];
+		this.relativeContainer = c;
+	},
+
+	_convertPositionTo: function(d, pos) {
+
+		if (!pos) {
+			pos = this.position;
+		}
+
+		var mod = d === "absolute" ? 1 : -1,
+			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
+
+		return {
+			top: (
+				pos.top	+																// The absolute mouse position
+				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.top * mod -										// The offsetParent's offset without borders (offset + border)
+				( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
+			),
+			left: (
+				pos.left +																// The absolute mouse position
+				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
+				( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
+			)
+		};
+
+	},
+
+	_generatePosition: function( event, constrainPosition ) {
+
+		var containment, co, top, left,
+			o = this.options,
+			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
+			pageX = event.pageX,
+			pageY = event.pageY;
+
+		// Cache the scroll
+		if ( !scrollIsRootNode || !this.offset.scroll ) {
+			this.offset.scroll = {
+				top: this.scrollParent.scrollTop(),
+				left: this.scrollParent.scrollLeft()
+			};
+		}
+
+		/*
+		 * - Position constraining -
+		 * Constrain the position to a mix of grid, containment.
+		 */
+
+		// If we are not dragging yet, we won't check for options
+		if ( constrainPosition ) {
+			if ( this.containment ) {
+				if ( this.relativeContainer ){
+					co = this.relativeContainer.offset();
+					containment = [
+						this.containment[ 0 ] + co.left,
+						this.containment[ 1 ] + co.top,
+						this.containment[ 2 ] + co.left,
+						this.containment[ 3 ] + co.top
+					];
+				} else {
+					containment = this.containment;
+				}
+
+				if (event.pageX - this.offset.click.left < containment[0]) {
+					pageX = containment[0] + this.offset.click.left;
+				}
+				if (event.pageY - this.offset.click.top < containment[1]) {
+					pageY = containment[1] + this.offset.click.top;
+				}
+				if (event.pageX - this.offset.click.left > containment[2]) {
+					pageX = containment[2] + this.offset.click.left;
+				}
+				if (event.pageY - this.offset.click.top > containment[3]) {
+					pageY = containment[3] + this.offset.click.top;
+				}
+			}
+
+			if (o.grid) {
+				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
+				top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
+				pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+				left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
+				pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+			}
+
+			if ( o.axis === "y" ) {
+				pageX = this.originalPageX;
+			}
+
+			if ( o.axis === "x" ) {
+				pageY = this.originalPageY;
+			}
+		}
+
+		return {
+			top: (
+				pageY -																	// The absolute mouse position
+				this.offset.click.top	-												// Click offset (relative to the element)
+				this.offset.relative.top -												// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
+				( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
+			),
+			left: (
+				pageX -																	// The absolute mouse position
+				this.offset.click.left -												// Click offset (relative to the element)
+				this.offset.relative.left -												// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
+				( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
+			)
+		};
+
+	},
+
+	_clear: function() {
+		this.helper.removeClass("ui-draggable-dragging");
+		if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
+			this.helper.remove();
+		}
+		this.helper = null;
+		this.cancelHelperRemoval = false;
+		if ( this.destroyOnClear ) {
+			this.destroy();
+		}
+	},
+
+	_normalizeRightBottom: function() {
+		if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) {
+			this.helper.width( this.helper.width() );
+			this.helper.css( "right", "auto" );
+		}
+		if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) {
+			this.helper.height( this.helper.height() );
+			this.helper.css( "bottom", "auto" );
+		}
+	},
+
+	// From now on bulk stuff - mainly helpers
+
+	_trigger: function( type, event, ui ) {
+		ui = ui || this._uiHash();
+		$.ui.plugin.call( this, type, [ event, ui, this ], true );
+
+		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
+		if ( /^(drag|start|stop)/.test( type ) ) {
+			this.positionAbs = this._convertPositionTo( "absolute" );
+			ui.offset = this.positionAbs;
+		}
+		return $.Widget.prototype._trigger.call( this, type, event, ui );
+	},
+
+	plugins: {},
+
+	_uiHash: function() {
+		return {
+			helper: this.helper,
+			position: this.position,
+			originalPosition: this.originalPosition,
+			offset: this.positionAbs
+		};
+	}
+
+});
+
+$.ui.plugin.add( "draggable", "connectToSortable", {
+	start: function( event, ui, draggable ) {
+		var uiSortable = $.extend( {}, ui, {
+			item: draggable.element
+		});
+
+		draggable.sortables = [];
+		$( draggable.options.connectToSortable ).each(function() {
+			var sortable = $( this ).sortable( "instance" );
+
+			if ( sortable && !sortable.options.disabled ) {
+				draggable.sortables.push( sortable );
+
+				// refreshPositions is called at drag start to refresh the containerCache
+				// which is used in drag. This ensures it's initialized and synchronized
+				// with any changes that might have happened on the page since initialization.
+				sortable.refreshPositions();
+				sortable._trigger("activate", event, uiSortable);
+			}
+		});
+	},
+	stop: function( event, ui, draggable ) {
+		var uiSortable = $.extend( {}, ui, {
+			item: draggable.element
+		});
+
+		draggable.cancelHelperRemoval = false;
+
+		$.each( draggable.sortables, function() {
+			var sortable = this;
+
+			if ( sortable.isOver ) {
+				sortable.isOver = 0;
+
+				// Allow this sortable to handle removing the helper
+				draggable.cancelHelperRemoval = true;
+				sortable.cancelHelperRemoval = false;
+
+				// Use _storedCSS To restore properties in the sortable,
+				// as this also handles revert (#9675) since the draggable
+				// may have modified them in unexpected ways (#8809)
+				sortable._storedCSS = {
+					position: sortable.placeholder.css( "position" ),
+					top: sortable.placeholder.css( "top" ),
+					left: sortable.placeholder.css( "left" )
+				};
+
+				sortable._mouseStop(event);
+
+				// Once drag has ended, the sortable should return to using
+				// its original helper, not the shared helper from draggable
+				sortable.options.helper = sortable.options._helper;
+			} else {
+				// Prevent this Sortable from removing the helper.
+				// However, don't set the draggable to remove the helper
+				// either as another connected Sortable may yet handle the removal.
+				sortable.cancelHelperRemoval = true;
+
+				sortable._trigger( "deactivate", event, uiSortable );
+			}
+		});
+	},
+	drag: function( event, ui, draggable ) {
+		$.each( draggable.sortables, function() {
+			var innermostIntersecting = false,
+				sortable = this;
+
+			// Copy over variables that sortable's _intersectsWith uses
+			sortable.positionAbs = draggable.positionAbs;
+			sortable.helperProportions = draggable.helperProportions;
+			sortable.offset.click = draggable.offset.click;
+
+			if ( sortable._intersectsWith( sortable.containerCache ) ) {
+				innermostIntersecting = true;
+
+				$.each( draggable.sortables, function() {
+					// Copy over variables that sortable's _intersectsWith uses
+					this.positionAbs = draggable.positionAbs;
+					this.helperProportions = draggable.helperProportions;
+					this.offset.click = draggable.offset.click;
+
+					if ( this !== sortable &&
+							this._intersectsWith( this.containerCache ) &&
+							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
+						innermostIntersecting = false;
+					}
+
+					return innermostIntersecting;
+				});
+			}
+
+			if ( innermostIntersecting ) {
+				// If it intersects, we use a little isOver variable and set it once,
+				// so that the move-in stuff gets fired only once.
+				if ( !sortable.isOver ) {
+					sortable.isOver = 1;
+
+					// Store draggable's parent in case we need to reappend to it later.
+					draggable._parent = ui.helper.parent();
+
+					sortable.currentItem = ui.helper
+						.appendTo( sortable.element )
+						.data( "ui-sortable-item", true );
+
+					// Store helper option to later restore it
+					sortable.options._helper = sortable.options.helper;
+
+					sortable.options.helper = function() {
+						return ui.helper[ 0 ];
+					};
+
+					// Fire the start events of the sortable with our passed browser event,
+					// and our own helper (so it doesn't create a new one)
+					event.target = sortable.currentItem[ 0 ];
+					sortable._mouseCapture( event, true );
+					sortable._mouseStart( event, true, true );
+
+					// Because the browser event is way off the new appended portlet,
+					// modify necessary variables to reflect the changes
+					sortable.offset.click.top = draggable.offset.click.top;
+					sortable.offset.click.left = draggable.offset.click.left;
+					sortable.offset.parent.left -= draggable.offset.parent.left -
+						sortable.offset.parent.left;
+					sortable.offset.parent.top -= draggable.offset.parent.top -
+						sortable.offset.parent.top;
+
+					draggable._trigger( "toSortable", event );
+
+					// Inform draggable that the helper is in a valid drop zone,
+					// used solely in the revert option to handle "valid/invalid".
+					draggable.dropped = sortable.element;
+
+					// Need to refreshPositions of all sortables in the case that
+					// adding to one sortable changes the location of the other sortables (#9675)
+					$.each( draggable.sortables, function() {
+						this.refreshPositions();
+					});
+
+					// hack so receive/update callbacks work (mostly)
+					draggable.currentItem = draggable.element;
+					sortable.fromOutside = draggable;
+				}
+
+				if ( sortable.currentItem ) {
+					sortable._mouseDrag( event );
+					// Copy the sortable's position because the draggable's can potentially reflect
+					// a relative position, while sortable is always absolute, which the dragged
+					// element has now become. (#8809)
+					ui.position = sortable.position;
+				}
+			} else {
+				// If it doesn't intersect with the sortable, and it intersected before,
+				// we fake the drag stop of the sortable, but make sure it doesn't remove
+				// the helper by using cancelHelperRemoval.
+				if ( sortable.isOver ) {
+
+					sortable.isOver = 0;
+					sortable.cancelHelperRemoval = true;
+
+					// Calling sortable's mouseStop would trigger a revert,
+					// so revert must be temporarily false until after mouseStop is called.
+					sortable.options._revert = sortable.options.revert;
+					sortable.options.revert = false;
+
+					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
+					sortable._mouseStop( event, true );
+
+					// restore sortable behaviors that were modfied
+					// when the draggable entered the sortable area (#9481)
+					sortable.options.revert = sortable.options._revert;
+					sortable.options.helper = sortable.options._helper;
+
+					if ( sortable.placeholder ) {
+						sortable.placeholder.remove();
+					}
+
+					// Restore and recalculate the draggable's offset considering the sortable
+					// may have modified them in unexpected ways. (#8809, #10669)
+					ui.helper.appendTo( draggable._parent );
+					draggable._refreshOffsets( event );
+					ui.position = draggable._generatePosition( event, true );
+
+					draggable._trigger( "fromSortable", event );
+
+					// Inform draggable that the helper is no longer in a valid drop zone
+					draggable.dropped = false;
+
+					// Need to refreshPositions of all sortables just in case removing
+					// from one sortable changes the location of other sortables (#9675)
+					$.each( draggable.sortables, function() {
+						this.refreshPositions();
+					});
+				}
+			}
+		});
+	}
+});
+
+$.ui.plugin.add("draggable", "cursor", {
+	start: function( event, ui, instance ) {
+		var t = $( "body" ),
+			o = instance.options;
+
+		if (t.css("cursor")) {
+			o._cursor = t.css("cursor");
+		}
+		t.css("cursor", o.cursor);
+	},
+	stop: function( event, ui, instance ) {
+		var o = instance.options;
+		if (o._cursor) {
+			$("body").css("cursor", o._cursor);
+		}
+	}
+});
+
+$.ui.plugin.add("draggable", "opacity", {
+	start: function( event, ui, instance ) {
+		var t = $( ui.helper ),
+			o = instance.options;
+		if (t.css("opacity")) {
+			o._opacity = t.css("opacity");
+		}
+		t.css("opacity", o.opacity);
+	},
+	stop: function( event, ui, instance ) {
+		var o = instance.options;
+		if (o._opacity) {
+			$(ui.helper).css("opacity", o._opacity);
+		}
+	}
+});
+
+$.ui.plugin.add("draggable", "scroll", {
+	start: function( event, ui, i ) {
+		if ( !i.scrollParentNotHidden ) {
+			i.scrollParentNotHidden = i.helper.scrollParent( false );
+		}
+
+		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
+			i.overflowOffset = i.scrollParentNotHidden.offset();
+		}
+	},
+	drag: function( event, ui, i  ) {
+
+		var o = i.options,
+			scrolled = false,
+			scrollParent = i.scrollParentNotHidden[ 0 ],
+			document = i.document[ 0 ];
+
+		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
+			if ( !o.axis || o.axis !== "x" ) {
+				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) {
+					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
+				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
+					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
+				}
+			}
+
+			if ( !o.axis || o.axis !== "y" ) {
+				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) {
+					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
+				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
+					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
+				}
+			}
+
+		} else {
+
+			if (!o.axis || o.axis !== "x") {
+				if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
+					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+				} else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
+					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+				}
+			}
+
+			if (!o.axis || o.axis !== "y") {
+				if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
+					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+				} else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
+					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+				}
+			}
+
+		}
+
+		if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
+			$.ui.ddmanager.prepareOffsets(i, event);
+		}
+
+	}
+});
+
+$.ui.plugin.add("draggable", "snap", {
+	start: function( event, ui, i ) {
+
+		var o = i.options;
+
+		i.snapElements = [];
+
+		$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
+			var $t = $(this),
+				$o = $t.offset();
+			if (this !== i.element[0]) {
+				i.snapElements.push({
+					item: this,
+					width: $t.outerWidth(), height: $t.outerHeight(),
+					top: $o.top, left: $o.left
+				});
+			}
+		});
+
+	},
+	drag: function( event, ui, inst ) {
+
+		var ts, bs, ls, rs, l, r, t, b, i, first,
+			o = inst.options,
+			d = o.snapTolerance,
+			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
+			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
+
+		for (i = inst.snapElements.length - 1; i >= 0; i--){
+
+			l = inst.snapElements[i].left - inst.margins.left;
+			r = l + inst.snapElements[i].width;
+			t = inst.snapElements[i].top - inst.margins.top;
+			b = t + inst.snapElements[i].height;
+
+			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
+				if (inst.snapElements[i].snapping) {
+					(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+				}
+				inst.snapElements[i].snapping = false;
+				continue;
+			}
+
+			if (o.snapMode !== "inner") {
+				ts = Math.abs(t - y2) <= d;
+				bs = Math.abs(b - y1) <= d;
+				ls = Math.abs(l - x2) <= d;
+				rs = Math.abs(r - x1) <= d;
+				if (ts) {
+					ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
+				}
+				if (bs) {
+					ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top;
+				}
+				if (ls) {
+					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
+				}
+				if (rs) {
+					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left;
+				}
+			}
+
+			first = (ts || bs || ls || rs);
+
+			if (o.snapMode !== "outer") {
+				ts = Math.abs(t - y1) <= d;
+				bs = Math.abs(b - y2) <= d;
+				ls = Math.abs(l - x1) <= d;
+				rs = Math.abs(r - x2) <= d;
+				if (ts) {
+					ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top;
+				}
+				if (bs) {
+					ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
+				}
+				if (ls) {
+					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left;
+				}
+				if (rs) {
+					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
+				}
+			}
+
+			if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
+				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+			}
+			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
+
+		}
+
+	}
+});
+
+$.ui.plugin.add("draggable", "stack", {
+	start: function( event, ui, instance ) {
+		var min,
+			o = instance.options,
+			group = $.makeArray($(o.stack)).sort(function(a, b) {
+				return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
+			});
+
+		if (!group.length) { return; }
+
+		min = parseInt($(group[0]).css("zIndex"), 10) || 0;
+		$(group).each(function(i) {
+			$(this).css("zIndex", min + i);
+		});
+		this.css("zIndex", (min + group.length));
+	}
+});
+
+$.ui.plugin.add("draggable", "zIndex", {
+	start: function( event, ui, instance ) {
+		var t = $( ui.helper ),
+			o = instance.options;
+
+		if (t.css("zIndex")) {
+			o._zIndex = t.css("zIndex");
+		}
+		t.css("zIndex", o.zIndex);
+	},
+	stop: function( event, ui, instance ) {
+		var o = instance.options;
+
+		if (o._zIndex) {
+			$(ui.helper).css("zIndex", o._zIndex);
+		}
+	}
+});
+
+var draggable = $.ui.draggable;
+
+
+/*!
+ * jQuery UI Resizable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/resizable/
+ */
+
+
+$.widget("ui.resizable", $.ui.mouse, {
+	version: "1.11.4",
+	widgetEventPrefix: "resize",
+	options: {
+		alsoResize: false,
+		animate: false,
+		animateDuration: "slow",
+		animateEasing: "swing",
+		aspectRatio: false,
+		autoHide: false,
+		containment: false,
+		ghost: false,
+		grid: false,
+		handles: "e,s,se",
+		helper: false,
+		maxHeight: null,
+		maxWidth: null,
+		minHeight: 10,
+		minWidth: 10,
+		// See #7960
+		zIndex: 90,
+
+		// callbacks
+		resize: null,
+		start: null,
+		stop: null
+	},
+
+	_num: function( value ) {
+		return parseInt( value, 10 ) || 0;
+	},
+
+	_isNumber: function( value ) {
+		return !isNaN( parseInt( value, 10 ) );
+	},
+
+	_hasScroll: function( el, a ) {
+
+		if ( $( el ).css( "overflow" ) === "hidden") {
+			return false;
+		}
+
+		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
+			has = false;
+
+		if ( el[ scroll ] > 0 ) {
+			return true;
+		}
+
+		// TODO: determine which cases actually cause this to happen
+		// if the element doesn't have the scroll set, see if it's possible to
+		// set the scroll
+		el[ scroll ] = 1;
+		has = ( el[ scroll ] > 0 );
+		el[ scroll ] = 0;
+		return has;
+	},
+
+	_create: function() {
+
+		var n, i, handle, axis, hname,
+			that = this,
+			o = this.options;
+		this.element.addClass("ui-resizable");
+
+		$.extend(this, {
+			_aspectRatio: !!(o.aspectRatio),
+			aspectRatio: o.aspectRatio,
+			originalElement: this.element,
+			_proportionallyResizeElements: [],
+			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
+		});
+
+		// Wrap the element if it cannot hold child nodes
+		if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
+
+			this.element.wrap(
+				$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
+					position: this.element.css("position"),
+					width: this.element.outerWidth(),
+					height: this.element.outerHeight(),
+					top: this.element.css("top"),
+					left: this.element.css("left")
+				})
+			);
+
+			this.element = this.element.parent().data(
+				"ui-resizable", this.element.resizable( "instance" )
+			);
+
+			this.elementIsWrapper = true;
+
+			this.element.css({
+				marginLeft: this.originalElement.css("marginLeft"),
+				marginTop: this.originalElement.css("marginTop"),
+				marginRight: this.originalElement.css("marginRight"),
+				marginBottom: this.originalElement.css("marginBottom")
+			});
+			this.originalElement.css({
+				marginLeft: 0,
+				marginTop: 0,
+				marginRight: 0,
+				marginBottom: 0
+			});
+			// support: Safari
+			// Prevent Safari textarea resize
+			this.originalResizeStyle = this.originalElement.css("resize");
+			this.originalElement.css("resize", "none");
+
+			this._proportionallyResizeElements.push( this.originalElement.css({
+				position: "static",
+				zoom: 1,
+				display: "block"
+			}) );
+
+			// support: IE9
+			// avoid IE jump (hard set the margin)
+			this.originalElement.css({ margin: this.originalElement.css("margin") });
+
+			this._proportionallyResize();
+		}
+
+		this.handles = o.handles ||
+			( !$(".ui-resizable-handle", this.element).length ?
+				"e,s,se" : {
+					n: ".ui-resizable-n",
+					e: ".ui-resizable-e",
+					s: ".ui-resizable-s",
+					w: ".ui-resizable-w",
+					se: ".ui-resizable-se",
+					sw: ".ui-resizable-sw",
+					ne: ".ui-resizable-ne",
+					nw: ".ui-resizable-nw"
+				} );
+
+		this._handles = $();
+		if ( this.handles.constructor === String ) {
+
+			if ( this.handles === "all") {
+				this.handles = "n,e,s,w,se,sw,ne,nw";
+			}
+
+			n = this.handles.split(",");
+			this.handles = {};
+
+			for (i = 0; i < n.length; i++) {
+
+				handle = $.trim(n[i]);
+				hname = "ui-resizable-" + handle;
+				axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
+
+				axis.css({ zIndex: o.zIndex });
+
+				// TODO : What's going on here?
+				if ("se" === handle) {
+					axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
+				}
+
+				this.handles[handle] = ".ui-resizable-" + handle;
+				this.element.append(axis);
+			}
+
+		}
+
+		this._renderAxis = function(target) {
+
+			var i, axis, padPos, padWrapper;
+
+			target = target || this.element;
+
+			for (i in this.handles) {
+
+				if (this.handles[i].constructor === String) {
+					this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
+				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
+					this.handles[ i ] = $( this.handles[ i ] );
+					this._on( this.handles[ i ], { "mousedown": that._mouseDown });
+				}
+
+				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) {
+
+					axis = $(this.handles[i], this.element);
+
+					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+
+					padPos = [ "padding",
+						/ne|nw|n/.test(i) ? "Top" :
+						/se|sw|s/.test(i) ? "Bottom" :
+						/^e$/.test(i) ? "Right" : "Left" ].join("");
+
+					target.css(padPos, padWrapper);
+
+					this._proportionallyResize();
+				}
+
+				this._handles = this._handles.add( this.handles[ i ] );
+			}
+		};
+
+		// TODO: make renderAxis a prototype function
+		this._renderAxis(this.element);
+
+		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
+		this._handles.disableSelection();
+
+		this._handles.mouseover(function() {
+			if (!that.resizing) {
+				if (this.className) {
+					axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+				}
+				that.axis = axis && axis[1] ? axis[1] : "se";
+			}
+		});
+
+		if (o.autoHide) {
+			this._handles.hide();
+			$(this.element)
+				.addClass("ui-resizable-autohide")
+				.mouseenter(function() {
+					if (o.disabled) {
+						return;
+					}
+					$(this).removeClass("ui-resizable-autohide");
+					that._handles.show();
+				})
+				.mouseleave(function() {
+					if (o.disabled) {
+						return;
+					}
+					if (!that.resizing) {
+						$(this).addClass("ui-resizable-autohide");
+						that._handles.hide();
+					}
+				});
+		}
+
+		this._mouseInit();
+	},
+
+	_destroy: function() {
+
+		this._mouseDestroy();
+
+		var wrapper,
+			_destroy = function(exp) {
+				$(exp)
+					.removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
+					.removeData("resizable")
+					.removeData("ui-resizable")
+					.unbind(".resizable")
+					.find(".ui-resizable-handle")
+						.remove();
+			};
+
+		// TODO: Unwrap at same DOM position
+		if (this.elementIsWrapper) {
+			_destroy(this.element);
+			wrapper = this.element;
+			this.originalElement.css({
+				position: wrapper.css("position"),
+				width: wrapper.outerWidth(),
+				height: wrapper.outerHeight(),
+				top: wrapper.css("top"),
+				left: wrapper.css("left")
+			}).insertAfter( wrapper );
+			wrapper.remove();
+		}
+
+		this.originalElement.css("resize", this.originalResizeStyle);
+		_destroy(this.originalElement);
+
+		return this;
+	},
+
+	_mouseCapture: function(event) {
+		var i, handle,
+			capture = false;
+
+		for (i in this.handles) {
+			handle = $(this.handles[i])[0];
+			if (handle === event.target || $.contains(handle, event.target)) {
+				capture = true;
+			}
+		}
+
+		return !this.options.disabled && capture;
+	},
+
+	_mouseStart: function(event) {
+
+		var curleft, curtop, cursor,
+			o = this.options,
+			el = this.element;
+
+		this.resizing = true;
+
+		this._renderProxy();
+
+		curleft = this._num(this.helper.css("left"));
+		curtop = this._num(this.helper.css("top"));
+
+		if (o.containment) {
+			curleft += $(o.containment).scrollLeft() || 0;
+			curtop += $(o.containment).scrollTop() || 0;
+		}
+
+		this.offset = this.helper.offset();
+		this.position = { left: curleft, top: curtop };
+
+		this.size = this._helper ? {
+				width: this.helper.width(),
+				height: this.helper.height()
+			} : {
+				width: el.width(),
+				height: el.height()
+			};
+
+		this.originalSize = this._helper ? {
+				width: el.outerWidth(),
+				height: el.outerHeight()
+			} : {
+				width: el.width(),
+				height: el.height()
+			};
+
+		this.sizeDiff = {
+			width: el.outerWidth() - el.width(),
+			height: el.outerHeight() - el.height()
+		};
+
+		this.originalPosition = { left: curleft, top: curtop };
+		this.originalMousePosition = { left: event.pageX, top: event.pageY };
+
+		this.aspectRatio = (typeof o.aspectRatio === "number") ?
+			o.aspectRatio :
+			((this.originalSize.width / this.originalSize.height) || 1);
+
+		cursor = $(".ui-resizable-" + this.axis).css("cursor");
+		$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
+
+		el.addClass("ui-resizable-resizing");
+		this._propagate("start", event);
+		return true;
+	},
+
+	_mouseDrag: function(event) {
+
+		var data, props,
+			smp = this.originalMousePosition,
+			a = this.axis,
+			dx = (event.pageX - smp.left) || 0,
+			dy = (event.pageY - smp.top) || 0,
+			trigger = this._change[a];
+
+		this._updatePrevProperties();
+
+		if (!trigger) {
+			return false;
+		}
+
+		data = trigger.apply(this, [ event, dx, dy ]);
+
+		this._updateVirtualBoundaries(event.shiftKey);
+		if (this._aspectRatio || event.shiftKey) {
+			data = this._updateRatio(data, event);
+		}
+
+		data = this._respectSize(data, event);
+
+		this._updateCache(data);
+
+		this._propagate("resize", event);
+
+		props = this._applyChanges();
+
+		if ( !this._helper && this._proportionallyResizeElements.length ) {
+			this._proportionallyResize();
+		}
+
+		if ( !$.isEmptyObject( props ) ) {
+			this._updatePrevProperties();
+			this._trigger( "resize", event, this.ui() );
+			this._applyChanges();
+		}
+
+		return false;
+	},
+
+	_mouseStop: function(event) {
+
+		this.resizing = false;
+		var pr, ista, soffseth, soffsetw, s, left, top,
+			o = this.options, that = this;
+
+		if (this._helper) {
+
+			pr = this._proportionallyResizeElements;
+			ista = pr.length && (/textarea/i).test(pr[0].nodeName);
+			soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
+			soffsetw = ista ? 0 : that.sizeDiff.width;
+
+			s = {
+				width: (that.helper.width()  - soffsetw),
+				height: (that.helper.height() - soffseth)
+			};
+			left = (parseInt(that.element.css("left"), 10) +
+				(that.position.left - that.originalPosition.left)) || null;
+			top = (parseInt(that.element.css("top"), 10) +
+				(that.position.top - that.originalPosition.top)) || null;
+
+			if (!o.animate) {
+				this.element.css($.extend(s, { top: top, left: left }));
+			}
+
+			that.helper.height(that.size.height);
+			that.helper.width(that.size.width);
+
+			if (this._helper && !o.animate) {
+				this._proportionallyResize();
+			}
+		}
+
+		$("body").css("cursor", "auto");
+
+		this.element.removeClass("ui-resizable-resizing");
+
+		this._propagate("stop", event);
+
+		if (this._helper) {
+			this.helper.remove();
+		}
+
+		return false;
+
+	},
+
+	_updatePrevProperties: function() {
+		this.prevPosition = {
+			top: this.position.top,
+			left: this.position.left
+		};
+		this.prevSize = {
+			width: this.size.width,
+			height: this.size.height
+		};
+	},
+
+	_applyChanges: function() {
+		var props = {};
+
+		if ( this.position.top !== this.prevPosition.top ) {
+			props.top = this.position.top + "px";
+		}
+		if ( this.position.left !== this.prevPosition.left ) {
+			props.left = this.position.left + "px";
+		}
+		if ( this.size.width !== this.prevSize.width ) {
+			props.width = this.size.width + "px";
+		}
+		if ( this.size.height !== this.prevSize.height ) {
+			props.height = this.size.height + "px";
+		}
+
+		this.helper.css( props );
+
+		return props;
+	},
+
+	_updateVirtualBoundaries: function(forceAspectRatio) {
+		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
+			o = this.options;
+
+		b = {
+			minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
+			maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
+			minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
+			maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
+		};
+
+		if (this._aspectRatio || forceAspectRatio) {
+			pMinWidth = b.minHeight * this.aspectRatio;
+			pMinHeight = b.minWidth / this.aspectRatio;
+			pMaxWidth = b.maxHeight * this.aspectRatio;
+			pMaxHeight = b.maxWidth / this.aspectRatio;
+
+			if (pMinWidth > b.minWidth) {
+				b.minWidth = pMinWidth;
+			}
+			if (pMinHeight > b.minHeight) {
+				b.minHeight = pMinHeight;
+			}
+			if (pMaxWidth < b.maxWidth) {
+				b.maxWidth = pMaxWidth;
+			}
+			if (pMaxHeight < b.maxHeight) {
+				b.maxHeight = pMaxHeight;
+			}
+		}
+		this._vBoundaries = b;
+	},
+
+	_updateCache: function(data) {
+		this.offset = this.helper.offset();
+		if (this._isNumber(data.left)) {
+			this.position.left = data.left;
+		}
+		if (this._isNumber(data.top)) {
+			this.position.top = data.top;
+		}
+		if (this._isNumber(data.height)) {
+			this.size.height = data.height;
+		}
+		if (this._isNumber(data.width)) {
+			this.size.width = data.width;
+		}
+	},
+
+	_updateRatio: function( data ) {
+
+		var cpos = this.position,
+			csize = this.size,
+			a = this.axis;
+
+		if (this._isNumber(data.height)) {
+			data.width = (data.height * this.aspectRatio);
+		} else if (this._isNumber(data.width)) {
+			data.height = (data.width / this.aspectRatio);
+		}
+
+		if (a === "sw") {
+			data.left = cpos.left + (csize.width - data.width);
+			data.top = null;
+		}
+		if (a === "nw") {
+			data.top = cpos.top + (csize.height - data.height);
+			data.left = cpos.left + (csize.width - data.width);
+		}
+
+		return data;
+	},
+
+	_respectSize: function( data ) {
+
+		var o = this._vBoundaries,
+			a = this.axis,
+			ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
+			ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
+			isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
+			isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
+			dw = this.originalPosition.left + this.originalSize.width,
+			dh = this.position.top + this.size.height,
+			cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+		if (isminw) {
+			data.width = o.minWidth;
+		}
+		if (isminh) {
+			data.height = o.minHeight;
+		}
+		if (ismaxw) {
+			data.width = o.maxWidth;
+		}
+		if (ismaxh) {
+			data.height = o.maxHeight;
+		}
+
+		if (isminw && cw) {
+			data.left = dw - o.minWidth;
+		}
+		if (ismaxw && cw) {
+			data.left = dw - o.maxWidth;
+		}
+		if (isminh && ch) {
+			data.top = dh - o.minHeight;
+		}
+		if (ismaxh && ch) {
+			data.top = dh - o.maxHeight;
+		}
+
+		// Fixing jump error on top/left - bug #2330
+		if (!data.width && !data.height && !data.left && data.top) {
+			data.top = null;
+		} else if (!data.width && !data.height && !data.top && data.left) {
+			data.left = null;
+		}
+
+		return data;
+	},
+
+	_getPaddingPlusBorderDimensions: function( element ) {
+		var i = 0,
+			widths = [],
+			borders = [
+				element.css( "borderTopWidth" ),
+				element.css( "borderRightWidth" ),
+				element.css( "borderBottomWidth" ),
+				element.css( "borderLeftWidth" )
+			],
+			paddings = [
+				element.css( "paddingTop" ),
+				element.css( "paddingRight" ),
+				element.css( "paddingBottom" ),
+				element.css( "paddingLeft" )
+			];
+
+		for ( ; i < 4; i++ ) {
+			widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
+			widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
+		}
+
+		return {
+			height: widths[ 0 ] + widths[ 2 ],
+			width: widths[ 1 ] + widths[ 3 ]
+		};
+	},
+
+	_proportionallyResize: function() {
+
+		if (!this._proportionallyResizeElements.length) {
+			return;
+		}
+
+		var prel,
+			i = 0,
+			element = this.helper || this.element;
+
+		for ( ; i < this._proportionallyResizeElements.length; i++) {
+
+			prel = this._proportionallyResizeElements[i];
+
+			// TODO: Seems like a bug to cache this.outerDimensions
+			// considering that we are in a loop.
+			if (!this.outerDimensions) {
+				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
+			}
+
+			prel.css({
+				height: (element.height() - this.outerDimensions.height) || 0,
+				width: (element.width() - this.outerDimensions.width) || 0
+			});
+
+		}
+
+	},
+
+	_renderProxy: function() {
+
+		var el = this.element, o = this.options;
+		this.elementOffset = el.offset();
+
+		if (this._helper) {
+
+			this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
+
+			this.helper.addClass(this._helper).css({
+				width: this.element.outerWidth() - 1,
+				height: this.element.outerHeight() - 1,
+				position: "absolute",
+				left: this.elementOffset.left + "px",
+				top: this.elementOffset.top + "px",
+				zIndex: ++o.zIndex //TODO: Don't modify option
+			});
+
+			this.helper
+				.appendTo("body")
+				.disableSelection();
+
+		} else {
+			this.helper = this.element;
+		}
+
+	},
+
+	_change: {
+		e: function(event, dx) {
+			return { width: this.originalSize.width + dx };
+		},
+		w: function(event, dx) {
+			var cs = this.originalSize, sp = this.originalPosition;
+			return { left: sp.left + dx, width: cs.width - dx };
+		},
+		n: function(event, dx, dy) {
+			var cs = this.originalSize, sp = this.originalPosition;
+			return { top: sp.top + dy, height: cs.height - dy };
+		},
+		s: function(event, dx, dy) {
+			return { height: this.originalSize.height + dy };
+		},
+		se: function(event, dx, dy) {
+			return $.extend(this._change.s.apply(this, arguments),
+				this._change.e.apply(this, [ event, dx, dy ]));
+		},
+		sw: function(event, dx, dy) {
+			return $.extend(this._change.s.apply(this, arguments),
+				this._change.w.apply(this, [ event, dx, dy ]));
+		},
+		ne: function(event, dx, dy) {
+			return $.extend(this._change.n.apply(this, arguments),
+				this._change.e.apply(this, [ event, dx, dy ]));
+		},
+		nw: function(event, dx, dy) {
+			return $.extend(this._change.n.apply(this, arguments),
+				this._change.w.apply(this, [ event, dx, dy ]));
+		}
+	},
+
+	_propagate: function(n, event) {
+		$.ui.plugin.call(this, n, [ event, this.ui() ]);
+		(n !== "resize" && this._trigger(n, event, this.ui()));
+	},
+
+	plugins: {},
+
+	ui: function() {
+		return {
+			originalElement: this.originalElement,
+			element: this.element,
+			helper: this.helper,
+			position: this.position,
+			size: this.size,
+			originalSize: this.originalSize,
+			originalPosition: this.originalPosition
+		};
+	}
+
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "animate", {
+
+	stop: function( event ) {
+		var that = $(this).resizable( "instance" ),
+			o = that.options,
+			pr = that._proportionallyResizeElements,
+			ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+			soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
+			soffsetw = ista ? 0 : that.sizeDiff.width,
+			style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
+			left = (parseInt(that.element.css("left"), 10) +
+				(that.position.left - that.originalPosition.left)) || null,
+			top = (parseInt(that.element.css("top"), 10) +
+				(that.position.top - that.originalPosition.top)) || null;
+
+		that.element.animate(
+			$.extend(style, top && left ? { top: top, left: left } : {}), {
+				duration: o.animateDuration,
+				easing: o.animateEasing,
+				step: function() {
+
+					var data = {
+						width: parseInt(that.element.css("width"), 10),
+						height: parseInt(that.element.css("height"), 10),
+						top: parseInt(that.element.css("top"), 10),
+						left: parseInt(that.element.css("left"), 10)
+					};
+
+					if (pr && pr.length) {
+						$(pr[0]).css({ width: data.width, height: data.height });
+					}
+
+					// propagating resize, and updating values for each animation step
+					that._updateCache(data);
+					that._propagate("resize", event);
+
+				}
+			}
+		);
+	}
+
+});
+
+$.ui.plugin.add( "resizable", "containment", {
+
+	start: function() {
+		var element, p, co, ch, cw, width, height,
+			that = $( this ).resizable( "instance" ),
+			o = that.options,
+			el = that.element,
+			oc = o.containment,
+			ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
+
+		if ( !ce ) {
+			return;
+		}
+
+		that.containerElement = $( ce );
+
+		if ( /document/.test( oc ) || oc === document ) {
+			that.containerOffset = {
+				left: 0,
+				top: 0
+			};
+			that.containerPosition = {
+				left: 0,
+				top: 0
+			};
+
+			that.parentData = {
+				element: $( document ),
+				left: 0,
+				top: 0,
+				width: $( document ).width(),
+				height: $( document ).height() || document.body.parentNode.scrollHeight
+			};
+		} else {
+			element = $( ce );
+			p = [];
+			$([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
+				p[ i ] = that._num( element.css( "padding" + name ) );
+			});
+
+			that.containerOffset = element.offset();
+			that.containerPosition = element.position();
+			that.containerSize = {
+				height: ( element.innerHeight() - p[ 3 ] ),
+				width: ( element.innerWidth() - p[ 1 ] )
+			};
+
+			co = that.containerOffset;
+			ch = that.containerSize.height;
+			cw = that.containerSize.width;
+			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
+			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
+
+			that.parentData = {
+				element: ce,
+				left: co.left,
+				top: co.top,
+				width: width,
+				height: height
+			};
+		}
+	},
+
+	resize: function( event ) {
+		var woset, hoset, isParent, isOffsetRelative,
+			that = $( this ).resizable( "instance" ),
+			o = that.options,
+			co = that.containerOffset,
+			cp = that.position,
+			pRatio = that._aspectRatio || event.shiftKey,
+			cop = {
+				top: 0,
+				left: 0
+			},
+			ce = that.containerElement,
+			continueResize = true;
+
+		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
+			cop = co;
+		}
+
+		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
+			that.size.width = that.size.width +
+				( that._helper ?
+					( that.position.left - co.left ) :
+					( that.position.left - cop.left ) );
+
+			if ( pRatio ) {
+				that.size.height = that.size.width / that.aspectRatio;
+				continueResize = false;
+			}
+			that.position.left = o.helper ? co.left : 0;
+		}
+
+		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
+			that.size.height = that.size.height +
+				( that._helper ?
+					( that.position.top - co.top ) :
+					that.position.top );
+
+			if ( pRatio ) {
+				that.size.width = that.size.height * that.aspectRatio;
+				continueResize = false;
+			}
+			that.position.top = that._helper ? co.top : 0;
+		}
+
+		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
+		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
+
+		if ( isParent && isOffsetRelative ) {
+			that.offset.left = that.parentData.left + that.position.left;
+			that.offset.top = that.parentData.top + that.position.top;
+		} else {
+			that.offset.left = that.element.offset().left;
+			that.offset.top = that.element.offset().top;
+		}
+
+		woset = Math.abs( that.sizeDiff.width +
+			(that._helper ?
+				that.offset.left - cop.left :
+				(that.offset.left - co.left)) );
+
+		hoset = Math.abs( that.sizeDiff.height +
+			(that._helper ?
+				that.offset.top - cop.top :
+				(that.offset.top - co.top)) );
+
+		if ( woset + that.size.width >= that.parentData.width ) {
+			that.size.width = that.parentData.width - woset;
+			if ( pRatio ) {
+				that.size.height = that.size.width / that.aspectRatio;
+				continueResize = false;
+			}
+		}
+
+		if ( hoset + that.size.height >= that.parentData.height ) {
+			that.size.height = that.parentData.height - hoset;
+			if ( pRatio ) {
+				that.size.width = that.size.height * that.aspectRatio;
+				continueResize = false;
+			}
+		}
+
+		if ( !continueResize ) {
+			that.position.left = that.prevPosition.left;
+			that.position.top = that.prevPosition.top;
+			that.size.width = that.prevSize.width;
+			that.size.height = that.prevSize.height;
+		}
+	},
+
+	stop: function() {
+		var that = $( this ).resizable( "instance" ),
+			o = that.options,
+			co = that.containerOffset,
+			cop = that.containerPosition,
+			ce = that.containerElement,
+			helper = $( that.helper ),
+			ho = helper.offset(),
+			w = helper.outerWidth() - that.sizeDiff.width,
+			h = helper.outerHeight() - that.sizeDiff.height;
+
+		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
+			$( this ).css({
+				left: ho.left - cop.left - co.left,
+				width: w,
+				height: h
+			});
+		}
+
+		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
+			$( this ).css({
+				left: ho.left - cop.left - co.left,
+				width: w,
+				height: h
+			});
+		}
+	}
+});
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+	start: function() {
+		var that = $(this).resizable( "instance" ),
+			o = that.options;
+
+		$(o.alsoResize).each(function() {
+			var el = $(this);
+			el.data("ui-resizable-alsoresize", {
+				width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
+				left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
+			});
+		});
+	},
+
+	resize: function(event, ui) {
+		var that = $(this).resizable( "instance" ),
+			o = that.options,
+			os = that.originalSize,
+			op = that.originalPosition,
+			delta = {
+				height: (that.size.height - os.height) || 0,
+				width: (that.size.width - os.width) || 0,
+				top: (that.position.top - op.top) || 0,
+				left: (that.position.left - op.left) || 0
+			};
+
+			$(o.alsoResize).each(function() {
+				var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
+					css = el.parents(ui.originalElement[0]).length ?
+							[ "width", "height" ] :
+							[ "width", "height", "top", "left" ];
+
+				$.each(css, function(i, prop) {
+					var sum = (start[prop] || 0) + (delta[prop] || 0);
+					if (sum && sum >= 0) {
+						style[prop] = sum || null;
+					}
+				});
+
+				el.css(style);
+			});
+	},
+
+	stop: function() {
+		$(this).removeData("resizable-alsoresize");
+	}
+});
+
+$.ui.plugin.add("resizable", "ghost", {
+
+	start: function() {
+
+		var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
+
+		that.ghost = that.originalElement.clone();
+		that.ghost
+			.css({
+				opacity: 0.25,
+				display: "block",
+				position: "relative",
+				height: cs.height,
+				width: cs.width,
+				margin: 0,
+				left: 0,
+				top: 0
+			})
+			.addClass("ui-resizable-ghost")
+			.addClass(typeof o.ghost === "string" ? o.ghost : "");
+
+		that.ghost.appendTo(that.helper);
+
+	},
+
+	resize: function() {
+		var that = $(this).resizable( "instance" );
+		if (that.ghost) {
+			that.ghost.css({
+				position: "relative",
+				height: that.size.height,
+				width: that.size.width
+			});
+		}
+	},
+
+	stop: function() {
+		var that = $(this).resizable( "instance" );
+		if (that.ghost && that.helper) {
+			that.helper.get(0).removeChild(that.ghost.get(0));
+		}
+	}
+
+});
+
+$.ui.plugin.add("resizable", "grid", {
+
+	resize: function() {
+		var outerDimensions,
+			that = $(this).resizable( "instance" ),
+			o = that.options,
+			cs = that.size,
+			os = that.originalSize,
+			op = that.originalPosition,
+			a = that.axis,
+			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
+			gridX = (grid[0] || 1),
+			gridY = (grid[1] || 1),
+			ox = Math.round((cs.width - os.width) / gridX) * gridX,
+			oy = Math.round((cs.height - os.height) / gridY) * gridY,
+			newWidth = os.width + ox,
+			newHeight = os.height + oy,
+			isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
+			isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
+			isMinWidth = o.minWidth && (o.minWidth > newWidth),
+			isMinHeight = o.minHeight && (o.minHeight > newHeight);
+
+		o.grid = grid;
+
+		if (isMinWidth) {
+			newWidth += gridX;
+		}
+		if (isMinHeight) {
+			newHeight += gridY;
+		}
+		if (isMaxWidth) {
+			newWidth -= gridX;
+		}
+		if (isMaxHeight) {
+			newHeight -= gridY;
+		}
+
+		if (/^(se|s|e)$/.test(a)) {
+			that.size.width = newWidth;
+			that.size.height = newHeight;
+		} else if (/^(ne)$/.test(a)) {
+			that.size.width = newWidth;
+			that.size.height = newHeight;
+			that.position.top = op.top - oy;
+		} else if (/^(sw)$/.test(a)) {
+			that.size.width = newWidth;
+			that.size.height = newHeight;
+			that.position.left = op.left - ox;
+		} else {
+			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
+				outerDimensions = that._getPaddingPlusBorderDimensions( this );
+			}
+
+			if ( newHeight - gridY > 0 ) {
+				that.size.height = newHeight;
+				that.position.top = op.top - oy;
+			} else {
+				newHeight = gridY - outerDimensions.height;
+				that.size.height = newHeight;
+				that.position.top = op.top + os.height - newHeight;
+			}
+			if ( newWidth - gridX > 0 ) {
+				that.size.width = newWidth;
+				that.position.left = op.left - ox;
+			} else {
+				newWidth = gridX - outerDimensions.width;
+				that.size.width = newWidth;
+				that.position.left = op.left + os.width - newWidth;
+			}
+		}
+	}
+
+});
+
+var resizable = $.ui.resizable;
+
+
+/*!
+ * jQuery UI Dialog 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/dialog/
+ */
+
+
+var dialog = $.widget( "ui.dialog", {
+	version: "1.11.4",
+	options: {
+		appendTo: "body",
+		autoOpen: true,
+		buttons: [],
+		closeOnEscape: true,
+		closeText: "Close",
+		dialogClass: "",
+		draggable: true,
+		hide: null,
+		height: "auto",
+		maxHeight: null,
+		maxWidth: null,
+		minHeight: 150,
+		minWidth: 150,
+		modal: false,
+		position: {
+			my: "center",
+			at: "center",
+			of: window,
+			collision: "fit",
+			// Ensure the titlebar is always visible
+			using: function( pos ) {
+				var topOffset = $( this ).css( pos ).offset().top;
+				if ( topOffset < 0 ) {
+					$( this ).css( "top", pos.top - topOffset );
+				}
+			}
+		},
+		resizable: true,
+		show: null,
+		title: null,
+		width: 300,
+
+		// callbacks
+		beforeClose: null,
+		close: null,
+		drag: null,
+		dragStart: null,
+		dragStop: null,
+		focus: null,
+		open: null,
+		resize: null,
+		resizeStart: null,
+		resizeStop: null
+	},
+
+	sizeRelatedOptions: {
+		buttons: true,
+		height: true,
+		maxHeight: true,
+		maxWidth: true,
+		minHeight: true,
+		minWidth: true,
+		width: true
+	},
+
+	resizableRelatedOptions: {
+		maxHeight: true,
+		maxWidth: true,
+		minHeight: true,
+		minWidth: true
+	},
+
+	_create: function() {
+		this.originalCss = {
+			display: this.element[ 0 ].style.display,
+			width: this.element[ 0 ].style.width,
+			minHeight: this.element[ 0 ].style.minHeight,
+			maxHeight: this.element[ 0 ].style.maxHeight,
+			height: this.element[ 0 ].style.height
+		};
+		this.originalPosition = {
+			parent: this.element.parent(),
+			index: this.element.parent().children().index( this.element )
+		};
+		this.originalTitle = this.element.attr( "title" );
+		this.options.title = this.options.title || this.originalTitle;
+
+		this._createWrapper();
+
+		this.element
+			.show()
+			.removeAttr( "title" )
+			.addClass( "ui-dialog-content ui-widget-content" )
+			.appendTo( this.uiDialog );
+
+		this._createTitlebar();
+		this._createButtonPane();
+
+		if ( this.options.draggable && $.fn.draggable ) {
+			this._makeDraggable();
+		}
+		if ( this.options.resizable && $.fn.resizable ) {
+			this._makeResizable();
+		}
+
+		this._isOpen = false;
+
+		this._trackFocus();
+	},
+
+	_init: function() {
+		if ( this.options.autoOpen ) {
+			this.open();
+		}
+	},
+
+	_appendTo: function() {
+		var element = this.options.appendTo;
+		if ( element && (element.jquery || element.nodeType) ) {
+			return $( element );
+		}
+		return this.document.find( element || "body" ).eq( 0 );
+	},
+
+	_destroy: function() {
+		var next,
+			originalPosition = this.originalPosition;
+
+		this._untrackInstance();
+		this._destroyOverlay();
+
+		this.element
+			.removeUniqueId()
+			.removeClass( "ui-dialog-content ui-widget-content" )
+			.css( this.originalCss )
+			// Without detaching first, the following becomes really slow
+			.detach();
+
+		this.uiDialog.stop( true, true ).remove();
+
+		if ( this.originalTitle ) {
+			this.element.attr( "title", this.originalTitle );
+		}
+
+		next = originalPosition.parent.children().eq( originalPosition.index );
+		// Don't try to place the dialog next to itself (#8613)
+		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
+			next.before( this.element );
+		} else {
+			originalPosition.parent.append( this.element );
+		}
+	},
+
+	widget: function() {
+		return this.uiDialog;
+	},
+
+	disable: $.noop,
+	enable: $.noop,
+
+	close: function( event ) {
+		var activeElement,
+			that = this;
+
+		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
+			return;
+		}
+
+		this._isOpen = false;
+		this._focusedElement = null;
+		this._destroyOverlay();
+		this._untrackInstance();
+
+		if ( !this.opener.filter( ":focusable" ).focus().length ) {
+
+			// support: IE9
+			// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
+			try {
+				activeElement = this.document[ 0 ].activeElement;
+
+				// Support: IE9, IE10
+				// If the <body> is blurred, IE will switch windows, see #4520
+				if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
+
+					// Hiding a focused element doesn't trigger blur in WebKit
+					// so in case we have nothing to focus on, explicitly blur the active element
+					// https://bugs.webkit.org/show_bug.cgi?id=47182
+					$( activeElement ).blur();
+				}
+			} catch ( error ) {}
+		}
+
+		this._hide( this.uiDialog, this.options.hide, function() {
+			that._trigger( "close", event );
+		});
+	},
+
+	isOpen: function() {
+		return this._isOpen;
+	},
+
+	moveToTop: function() {
+		this._moveToTop();
+	},
+
+	_moveToTop: function( event, silent ) {
+		var moved = false,
+			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
+				return +$( this ).css( "z-index" );
+			}).get(),
+			zIndexMax = Math.max.apply( null, zIndices );
+
+		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
+			this.uiDialog.css( "z-index", zIndexMax + 1 );
+			moved = true;
+		}
+
+		if ( moved && !silent ) {
+			this._trigger( "focus", event );
+		}
+		return moved;
+	},
+
+	open: function() {
+		var that = this;
+		if ( this._isOpen ) {
+			if ( this._moveToTop() ) {
+				this._focusTabbable();
+			}
+			return;
+		}
+
+		this._isOpen = true;
+		this.opener = $( this.document[ 0 ].activeElement );
+
+		this._size();
+		this._position();
+		this._createOverlay();
+		this._moveToTop( null, true );
+
+		// Ensure the overlay is moved to the top with the dialog, but only when
+		// opening. The overlay shouldn't move after the dialog is open so that
+		// modeless dialogs opened after the modal dialog stack properly.
+		if ( this.overlay ) {
+			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
+		}
+
+		this._show( this.uiDialog, this.options.show, function() {
+			that._focusTabbable();
+			that._trigger( "focus" );
+		});
+
+		// Track the dialog immediately upon openening in case a focus event
+		// somehow occurs outside of the dialog before an element inside the
+		// dialog is focused (#10152)
+		this._makeFocusTarget();
+
+		this._trigger( "open" );
+	},
+
+	_focusTabbable: function() {
+		// Set focus to the first match:
+		// 1. An element that was focused previously
+		// 2. First element inside the dialog matching [autofocus]
+		// 3. Tabbable element inside the content element
+		// 4. Tabbable element inside the buttonpane
+		// 5. The close button
+		// 6. The dialog itself
+		var hasFocus = this._focusedElement;
+		if ( !hasFocus ) {
+			hasFocus = this.element.find( "[autofocus]" );
+		}
+		if ( !hasFocus.length ) {
+			hasFocus = this.element.find( ":tabbable" );
+		}
+		if ( !hasFocus.length ) {
+			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
+		}
+		if ( !hasFocus.length ) {
+			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
+		}
+		if ( !hasFocus.length ) {
+			hasFocus = this.uiDialog;
+		}
+		hasFocus.eq( 0 ).focus();
+	},
+
+	_keepFocus: function( event ) {
+		function checkFocus() {
+			var activeElement = this.document[0].activeElement,
+				isActive = this.uiDialog[0] === activeElement ||
+					$.contains( this.uiDialog[0], activeElement );
+			if ( !isActive ) {
+				this._focusTabbable();
+			}
+		}
+		event.preventDefault();
+		checkFocus.call( this );
+		// support: IE
+		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
+		// so we check again later
+		this._delay( checkFocus );
+	},
+
+	_createWrapper: function() {
+		this.uiDialog = $("<div>")
+			.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
+				this.options.dialogClass )
+			.hide()
+			.attr({
+				// Setting tabIndex makes the div focusable
+				tabIndex: -1,
+				role: "dialog"
+			})
+			.appendTo( this._appendTo() );
+
+		this._on( this.uiDialog, {
+			keydown: function( event ) {
+				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
+						event.keyCode === $.ui.keyCode.ESCAPE ) {
+					event.preventDefault();
+					this.close( event );
+					return;
+				}
+
+				// prevent tabbing out of dialogs
+				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
+					return;
+				}
+				var tabbables = this.uiDialog.find( ":tabbable" ),
+					first = tabbables.filter( ":first" ),
+					last = tabbables.filter( ":last" );
+
+				if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
+					this._delay(function() {
+						first.focus();
+					});
+					event.preventDefault();
+				} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
+					this._delay(function() {
+						last.focus();
+					});
+					event.preventDefault();
+				}
+			},
+			mousedown: function( event ) {
+				if ( this._moveToTop( event ) ) {
+					this._focusTabbable();
+				}
+			}
+		});
+
+		// We assume that any existing aria-describedby attribute means
+		// that the dialog content is marked up properly
+		// otherwise we brute force the content as the description
+		if ( !this.element.find( "[aria-describedby]" ).length ) {
+			this.uiDialog.attr({
+				"aria-describedby": this.element.uniqueId().attr( "id" )
+			});
+		}
+	},
+
+	_createTitlebar: function() {
+		var uiDialogTitle;
+
+		this.uiDialogTitlebar = $( "<div>" )
+			.addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
+			.prependTo( this.uiDialog );
+		this._on( this.uiDialogTitlebar, {
+			mousedown: function( event ) {
+				// Don't prevent click on close button (#8838)
+				// Focusing a dialog that is partially scrolled out of view
+				// causes the browser to scroll it into view, preventing the click event
+				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
+					// Dialog isn't getting focus when dragging (#8063)
+					this.uiDialog.focus();
+				}
+			}
+		});
+
+		// support: IE
+		// Use type="button" to prevent enter keypresses in textboxes from closing the
+		// dialog in IE (#9312)
+		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
+			.button({
+				label: this.options.closeText,
+				icons: {
+					primary: "ui-icon-closethick"
+				},
+				text: false
+			})
+			.addClass( "ui-dialog-titlebar-close" )
+			.appendTo( this.uiDialogTitlebar );
+		this._on( this.uiDialogTitlebarClose, {
+			click: function( event ) {
+				event.preventDefault();
+				this.close( event );
+			}
+		});
+
+		uiDialogTitle = $( "<span>" )
+			.uniqueId()
+			.addClass( "ui-dialog-title" )
+			.prependTo( this.uiDialogTitlebar );
+		this._title( uiDialogTitle );
+
+		this.uiDialog.attr({
+			"aria-labelledby": uiDialogTitle.attr( "id" )
+		});
+	},
+
+	_title: function( title ) {
+		if ( !this.options.title ) {
+			title.html( "&#160;" );
+		}
+		title.text( this.options.title );
+	},
+
+	_createButtonPane: function() {
+		this.uiDialogButtonPane = $( "<div>" )
+			.addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
+
+		this.uiButtonSet = $( "<div>" )
+			.addClass( "ui-dialog-buttonset" )
+			.appendTo( this.uiDialogButtonPane );
+
+		this._createButtons();
+	},
+
+	_createButtons: function() {
+		var that = this,
+			buttons = this.options.buttons;
+
+		// if we already have a button pane, remove it
+		this.uiDialogButtonPane.remove();
+		this.uiButtonSet.empty();
+
+		if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
+			this.uiDialog.removeClass( "ui-dialog-buttons" );
+			return;
+		}
+
+		$.each( buttons, function( name, props ) {
+			var click, buttonOptions;
+			props = $.isFunction( props ) ?
+				{ click: props, text: name } :
+				props;
+			// Default to a non-submitting button
+			props = $.extend( { type: "button" }, props );
+			// Change the context for the click callback to be the main element
+			click = props.click;
+			props.click = function() {
+				click.apply( that.element[ 0 ], arguments );
+			};
+			buttonOptions = {
+				icons: props.icons,
+				text: props.showText
+			};
+			delete props.icons;
+			delete props.showText;
+			$( "<button></button>", props )
+				.button( buttonOptions )
+				.appendTo( that.uiButtonSet );
+		});
+		this.uiDialog.addClass( "ui-dialog-buttons" );
+		this.uiDialogButtonPane.appendTo( this.uiDialog );
+	},
+
+	_makeDraggable: function() {
+		var that = this,
+			options = this.options;
+
+		function filteredUi( ui ) {
+			return {
+				position: ui.position,
+				offset: ui.offset
+			};
+		}
+
+		this.uiDialog.draggable({
+			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
+			handle: ".ui-dialog-titlebar",
+			containment: "document",
+			start: function( event, ui ) {
+				$( this ).addClass( "ui-dialog-dragging" );
+				that._blockFrames();
+				that._trigger( "dragStart", event, filteredUi( ui ) );
+			},
+			drag: function( event, ui ) {
+				that._trigger( "drag", event, filteredUi( ui ) );
+			},
+			stop: function( event, ui ) {
+				var left = ui.offset.left - that.document.scrollLeft(),
+					top = ui.offset.top - that.document.scrollTop();
+
+				options.position = {
+					my: "left top",
+					at: "left" + (left >= 0 ? "+" : "") + left + " " +
+						"top" + (top >= 0 ? "+" : "") + top,
+					of: that.window
+				};
+				$( this ).removeClass( "ui-dialog-dragging" );
+				that._unblockFrames();
+				that._trigger( "dragStop", event, filteredUi( ui ) );
+			}
+		});
+	},
+
+	_makeResizable: function() {
+		var that = this,
+			options = this.options,
+			handles = options.resizable,
+			// .ui-resizable has position: relative defined in the stylesheet
+			// but dialogs have to use absolute or fixed positioning
+			position = this.uiDialog.css("position"),
+			resizeHandles = typeof handles === "string" ?
+				handles	:
+				"n,e,s,w,se,sw,ne,nw";
+
+		function filteredUi( ui ) {
+			return {
+				originalPosition: ui.originalPosition,
+				originalSize: ui.originalSize,
+				position: ui.position,
+				size: ui.size
+			};
+		}
+
+		this.uiDialog.resizable({
+			cancel: ".ui-dialog-content",
+			containment: "document",
+			alsoResize: this.element,
+			maxWidth: options.maxWidth,
+			maxHeight: options.maxHeight,
+			minWidth: options.minWidth,
+			minHeight: this._minHeight(),
+			handles: resizeHandles,
+			start: function( event, ui ) {
+				$( this ).addClass( "ui-dialog-resizing" );
+				that._blockFrames();
+				that._trigger( "resizeStart", event, filteredUi( ui ) );
+			},
+			resize: function( event, ui ) {
+				that._trigger( "resize", event, filteredUi( ui ) );
+			},
+			stop: function( event, ui ) {
+				var offset = that.uiDialog.offset(),
+					left = offset.left - that.document.scrollLeft(),
+					top = offset.top - that.document.scrollTop();
+
+				options.height = that.uiDialog.height();
+				options.width = that.uiDialog.width();
+				options.position = {
+					my: "left top",
+					at: "left" + (left >= 0 ? "+" : "") + left + " " +
+						"top" + (top >= 0 ? "+" : "") + top,
+					of: that.window
+				};
+				$( this ).removeClass( "ui-dialog-resizing" );
+				that._unblockFrames();
+				that._trigger( "resizeStop", event, filteredUi( ui ) );
+			}
+		})
+		.css( "position", position );
+	},
+
+	_trackFocus: function() {
+		this._on( this.widget(), {
+			focusin: function( event ) {
+				this._makeFocusTarget();
+				this._focusedElement = $( event.target );
+			}
+		});
+	},
+
+	_makeFocusTarget: function() {
+		this._untrackInstance();
+		this._trackingInstances().unshift( this );
+	},
+
+	_untrackInstance: function() {
+		var instances = this._trackingInstances(),
+			exists = $.inArray( this, instances );
+		if ( exists !== -1 ) {
+			instances.splice( exists, 1 );
+		}
+	},
+
+	_trackingInstances: function() {
+		var instances = this.document.data( "ui-dialog-instances" );
+		if ( !instances ) {
+			instances = [];
+			this.document.data( "ui-dialog-instances", instances );
+		}
+		return instances;
+	},
+
+	_minHeight: function() {
+		var options = this.options;
+
+		return options.height === "auto" ?
+			options.minHeight :
+			Math.min( options.minHeight, options.height );
+	},
+
+	_position: function() {
+		// Need to show the dialog to get the actual offset in the position plugin
+		var isVisible = this.uiDialog.is( ":visible" );
+		if ( !isVisible ) {
+			this.uiDialog.show();
+		}
+		this.uiDialog.position( this.options.position );
+		if ( !isVisible ) {
+			this.uiDialog.hide();
+		}
+	},
+
+	_setOptions: function( options ) {
+		var that = this,
+			resize = false,
+			resizableOptions = {};
+
+		$.each( options, function( key, value ) {
+			that._setOption( key, value );
+
+			if ( key in that.sizeRelatedOptions ) {
+				resize = true;
+			}
+			if ( key in that.resizableRelatedOptions ) {
+				resizableOptions[ key ] = value;
+			}
+		});
+
+		if ( resize ) {
+			this._size();
+			this._position();
+		}
+		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
+			this.uiDialog.resizable( "option", resizableOptions );
+		}
+	},
+
+	_setOption: function( key, value ) {
+		var isDraggable, isResizable,
+			uiDialog = this.uiDialog;
+
+		if ( key === "dialogClass" ) {
+			uiDialog
+				.removeClass( this.options.dialogClass )
+				.addClass( value );
+		}
+
+		if ( key === "disabled" ) {
+			return;
+		}
+
+		this._super( key, value );
+
+		if ( key === "appendTo" ) {
+			this.uiDialog.appendTo( this._appendTo() );
+		}
+
+		if ( key === "buttons" ) {
+			this._createButtons();
+		}
+
+		if ( key === "closeText" ) {
+			this.uiDialogTitlebarClose.button({
+				// Ensure that we always pass a string
+				label: "" + value
+			});
+		}
+
+		if ( key === "draggable" ) {
+			isDraggable = uiDialog.is( ":data(ui-draggable)" );
+			if ( isDraggable && !value ) {
+				uiDialog.draggable( "destroy" );
+			}
+
+			if ( !isDraggable && value ) {
+				this._makeDraggable();
+			}
+		}
+
+		if ( key === "position" ) {
+			this._position();
+		}
+
+		if ( key === "resizable" ) {
+			// currently resizable, becoming non-resizable
+			isResizable = uiDialog.is( ":data(ui-resizable)" );
+			if ( isResizable && !value ) {
+				uiDialog.resizable( "destroy" );
+			}
+
+			// currently resizable, changing handles
+			if ( isResizable && typeof value === "string" ) {
+				uiDialog.resizable( "option", "handles", value );
+			}
+
+			// currently non-resizable, becoming resizable
+			if ( !isResizable && value !== false ) {
+				this._makeResizable();
+			}
+		}
+
+		if ( key === "title" ) {
+			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
+		}
+	},
+
+	_size: function() {
+		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
+		// divs will both have width and height set, so we need to reset them
+		var nonContentHeight, minContentHeight, maxContentHeight,
+			options = this.options;
+
+		// Reset content sizing
+		this.element.show().css({
+			width: "auto",
+			minHeight: 0,
+			maxHeight: "none",
+			height: 0
+		});
+
+		if ( options.minWidth > options.width ) {
+			options.width = options.minWidth;
+		}
+
+		// reset wrapper sizing
+		// determine the height of all the non-content elements
+		nonContentHeight = this.uiDialog.css({
+				height: "auto",
+				width: options.width
+			})
+			.outerHeight();
+		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
+		maxContentHeight = typeof options.maxHeight === "number" ?
+			Math.max( 0, options.maxHeight - nonContentHeight ) :
+			"none";
+
+		if ( options.height === "auto" ) {
+			this.element.css({
+				minHeight: minContentHeight,
+				maxHeight: maxContentHeight,
+				height: "auto"
+			});
+		} else {
+			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
+		}
+
+		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
+			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
+		}
+	},
+
+	_blockFrames: function() {
+		this.iframeBlocks = this.document.find( "iframe" ).map(function() {
+			var iframe = $( this );
+
+			return $( "<div>" )
+				.css({
+					position: "absolute",
+					width: iframe.outerWidth(),
+					height: iframe.outerHeight()
+				})
+				.appendTo( iframe.parent() )
+				.offset( iframe.offset() )[0];
+		});
+	},
+
+	_unblockFrames: function() {
+		if ( this.iframeBlocks ) {
+			this.iframeBlocks.remove();
+			delete this.iframeBlocks;
+		}
+	},
+
+	_allowInteraction: function( event ) {
+		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
+			return true;
+		}
+
+		// TODO: Remove hack when datepicker implements
+		// the .ui-front logic (#8989)
+		return !!$( event.target ).closest( ".ui-datepicker" ).length;
+	},
+
+	_createOverlay: function() {
+		if ( !this.options.modal ) {
+			return;
+		}
+
+		// We use a delay in case the overlay is created from an
+		// event that we're going to be cancelling (#2804)
+		var isOpening = true;
+		this._delay(function() {
+			isOpening = false;
+		});
+
+		if ( !this.document.data( "ui-dialog-overlays" ) ) {
+
+			// Prevent use of anchors and inputs
+			// Using _on() for an event handler shared across many instances is
+			// safe because the dialogs stack and must be closed in reverse order
+			this._on( this.document, {
+				focusin: function( event ) {
+					if ( isOpening ) {
+						return;
+					}
+
+					if ( !this._allowInteraction( event ) ) {
+						event.preventDefault();
+						this._trackingInstances()[ 0 ]._focusTabbable();
+					}
+				}
+			});
+		}
+
+		this.overlay = $( "<div>" )
+			.addClass( "ui-widget-overlay ui-front" )
+			.appendTo( this._appendTo() );
+		this._on( this.overlay, {
+			mousedown: "_keepFocus"
+		});
+		this.document.data( "ui-dialog-overlays",
+			(this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
+	},
+
+	_destroyOverlay: function() {
+		if ( !this.options.modal ) {
+			return;
+		}
+
+		if ( this.overlay ) {
+			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
+
+			if ( !overlays ) {
+				this.document
+					.unbind( "focusin" )
+					.removeData( "ui-dialog-overlays" );
+			} else {
+				this.document.data( "ui-dialog-overlays", overlays );
+			}
+
+			this.overlay.remove();
+			this.overlay = null;
+		}
+	}
+});
+
+
+/*!
+ * jQuery UI Droppable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/droppable/
+ */
+
+
+$.widget( "ui.droppable", {
+	version: "1.11.4",
+	widgetEventPrefix: "drop",
+	options: {
+		accept: "*",
+		activeClass: false,
+		addClasses: true,
+		greedy: false,
+		hoverClass: false,
+		scope: "default",
+		tolerance: "intersect",
+
+		// callbacks
+		activate: null,
+		deactivate: null,
+		drop: null,
+		out: null,
+		over: null
+	},
+	_create: function() {
+
+		var proportions,
+			o = this.options,
+			accept = o.accept;
+
+		this.isover = false;
+		this.isout = true;
+
+		this.accept = $.isFunction( accept ) ? accept : function( d ) {
+			return d.is( accept );
+		};
+
+		this.proportions = function( /* valueToWrite */ ) {
+			if ( arguments.length ) {
+				// Store the droppable's proportions
+				proportions = arguments[ 0 ];
+			} else {
+				// Retrieve or derive the droppable's proportions
+				return proportions ?
+					proportions :
+					proportions = {
+						width: this.element[ 0 ].offsetWidth,
+						height: this.element[ 0 ].offsetHeight
+					};
+			}
+		};
+
+		this._addToManager( o.scope );
+
+		o.addClasses && this.element.addClass( "ui-droppable" );
+
+	},
+
+	_addToManager: function( scope ) {
+		// Add the reference and positions to the manager
+		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
+		$.ui.ddmanager.droppables[ scope ].push( this );
+	},
+
+	_splice: function( drop ) {
+		var i = 0;
+		for ( ; i < drop.length; i++ ) {
+			if ( drop[ i ] === this ) {
+				drop.splice( i, 1 );
+			}
+		}
+	},
+
+	_destroy: function() {
+		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
+
+		this._splice( drop );
+
+		this.element.removeClass( "ui-droppable ui-droppable-disabled" );
+	},
+
+	_setOption: function( key, value ) {
+
+		if ( key === "accept" ) {
+			this.accept = $.isFunction( value ) ? value : function( d ) {
+				return d.is( value );
+			};
+		} else if ( key === "scope" ) {
+			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
+
+			this._splice( drop );
+			this._addToManager( value );
+		}
+
+		this._super( key, value );
+	},
+
+	_activate: function( event ) {
+		var draggable = $.ui.ddmanager.current;
+		if ( this.options.activeClass ) {
+			this.element.addClass( this.options.activeClass );
+		}
+		if ( draggable ){
+			this._trigger( "activate", event, this.ui( draggable ) );
+		}
+	},
+
+	_deactivate: function( event ) {
+		var draggable = $.ui.ddmanager.current;
+		if ( this.options.activeClass ) {
+			this.element.removeClass( this.options.activeClass );
+		}
+		if ( draggable ){
+			this._trigger( "deactivate", event, this.ui( draggable ) );
+		}
+	},
+
+	_over: function( event ) {
+
+		var draggable = $.ui.ddmanager.current;
+
+		// Bail if draggable and droppable are same element
+		if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
+			return;
+		}
+
+		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
+			if ( this.options.hoverClass ) {
+				this.element.addClass( this.options.hoverClass );
+			}
+			this._trigger( "over", event, this.ui( draggable ) );
+		}
+
+	},
+
+	_out: function( event ) {
+
+		var draggable = $.ui.ddmanager.current;
+
+		// Bail if draggable and droppable are same element
+		if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
+			return;
+		}
+
+		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
+			if ( this.options.hoverClass ) {
+				this.element.removeClass( this.options.hoverClass );
+			}
+			this._trigger( "out", event, this.ui( draggable ) );
+		}
+
+	},
+
+	_drop: function( event, custom ) {
+
+		var draggable = custom || $.ui.ddmanager.current,
+			childrenIntersection = false;
+
+		// Bail if draggable and droppable are same element
+		if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
+			return false;
+		}
+
+		this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
+			var inst = $( this ).droppable( "instance" );
+			if (
+				inst.options.greedy &&
+				!inst.options.disabled &&
+				inst.options.scope === draggable.options.scope &&
+				inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
+				$.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event )
+			) { childrenIntersection = true; return false; }
+		});
+		if ( childrenIntersection ) {
+			return false;
+		}
+
+		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
+			if ( this.options.activeClass ) {
+				this.element.removeClass( this.options.activeClass );
+			}
+			if ( this.options.hoverClass ) {
+				this.element.removeClass( this.options.hoverClass );
+			}
+			this._trigger( "drop", event, this.ui( draggable ) );
+			return this.element;
+		}
+
+		return false;
+
+	},
+
+	ui: function( c ) {
+		return {
+			draggable: ( c.currentItem || c.element ),
+			helper: c.helper,
+			position: c.position,
+			offset: c.positionAbs
+		};
+	}
+
+});
+
+$.ui.intersect = (function() {
+	function isOverAxis( x, reference, size ) {
+		return ( x >= reference ) && ( x < ( reference + size ) );
+	}
+
+	return function( draggable, droppable, toleranceMode, event ) {
+
+		if ( !droppable.offset ) {
+			return false;
+		}
+
+		var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left,
+			y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top,
+			x2 = x1 + draggable.helperProportions.width,
+			y2 = y1 + draggable.helperProportions.height,
+			l = droppable.offset.left,
+			t = droppable.offset.top,
+			r = l + droppable.proportions().width,
+			b = t + droppable.proportions().height;
+
+		switch ( toleranceMode ) {
+		case "fit":
+			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
+		case "intersect":
+			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
+				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
+				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
+				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
+		case "pointer":
+			return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width );
+		case "touch":
+			return (
+				( y1 >= t && y1 <= b ) || // Top edge touching
+				( y2 >= t && y2 <= b ) || // Bottom edge touching
+				( y1 < t && y2 > b ) // Surrounded vertically
+			) && (
+				( x1 >= l && x1 <= r ) || // Left edge touching
+				( x2 >= l && x2 <= r ) || // Right edge touching
+				( x1 < l && x2 > r ) // Surrounded horizontally
+			);
+		default:
+			return false;
+		}
+	};
+})();
+
+/*
+	This manager tracks offsets of draggables and droppables
+*/
+$.ui.ddmanager = {
+	current: null,
+	droppables: { "default": [] },
+	prepareOffsets: function( t, event ) {
+
+		var i, j,
+			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
+			type = event ? event.type : null, // workaround for #2317
+			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
+
+		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
+
+			// No disabled and non-accepted
+			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
+				continue;
+			}
+
+			// Filter out elements in the current dragged item
+			for ( j = 0; j < list.length; j++ ) {
+				if ( list[ j ] === m[ i ].element[ 0 ] ) {
+					m[ i ].proportions().height = 0;
+					continue droppablesLoop;
+				}
+			}
+
+			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
+			if ( !m[ i ].visible ) {
+				continue;
+			}
+
+			// Activate the droppable if used directly from draggables
+			if ( type === "mousedown" ) {
+				m[ i ]._activate.call( m[ i ], event );
+			}
+
+			m[ i ].offset = m[ i ].element.offset();
+			m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
+
+		}
+
+	},
+	drop: function( draggable, event ) {
+
+		var dropped = false;
+		// Create a copy of the droppables in case the list changes during the drop (#9116)
+		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
+
+			if ( !this.options ) {
+				return;
+			}
+			if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
+				dropped = this._drop.call( this, event ) || dropped;
+			}
+
+			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
+				this.isout = true;
+				this.isover = false;
+				this._deactivate.call( this, event );
+			}
+
+		});
+		return dropped;
+
+	},
+	dragStart: function( draggable, event ) {
+		// Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
+		draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
+			if ( !draggable.options.refreshPositions ) {
+				$.ui.ddmanager.prepareOffsets( draggable, event );
+			}
+		});
+	},
+	drag: function( draggable, event ) {
+
+		// If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
+		if ( draggable.options.refreshPositions ) {
+			$.ui.ddmanager.prepareOffsets( draggable, event );
+		}
+
+		// Run through all droppables and check their positions based on specific tolerance options
+		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
+
+			if ( this.options.disabled || this.greedyChild || !this.visible ) {
+				return;
+			}
+
+			var parentInstance, scope, parent,
+				intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
+				c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
+			if ( !c ) {
+				return;
+			}
+
+			if ( this.options.greedy ) {
+				// find droppable parents with same scope
+				scope = this.options.scope;
+				parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
+					return $( this ).droppable( "instance" ).options.scope === scope;
+				});
+
+				if ( parent.length ) {
+					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
+					parentInstance.greedyChild = ( c === "isover" );
+				}
+			}
+
+			// we just moved into a greedy child
+			if ( parentInstance && c === "isover" ) {
+				parentInstance.isover = false;
+				parentInstance.isout = true;
+				parentInstance._out.call( parentInstance, event );
+			}
+
+			this[ c ] = true;
+			this[c === "isout" ? "isover" : "isout"] = false;
+			this[c === "isover" ? "_over" : "_out"].call( this, event );
+
+			// we just moved out of a greedy child
+			if ( parentInstance && c === "isout" ) {
+				parentInstance.isout = false;
+				parentInstance.isover = true;
+				parentInstance._over.call( parentInstance, event );
+			}
+		});
+
+	},
+	dragStop: function( draggable, event ) {
+		draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
+		// Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
+		if ( !draggable.options.refreshPositions ) {
+			$.ui.ddmanager.prepareOffsets( draggable, event );
+		}
+	}
+};
+
+var droppable = $.ui.droppable;
+
+
+/*!
+ * jQuery UI Effects 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/effects-core/
+ */
+
+
+var dataSpace = "ui-effects-",
+
+	// Create a local jQuery because jQuery Color relies on it and the
+	// global may not exist with AMD and a custom build (#10199)
+	jQuery = $;
+
+$.effects = {
+	effect: {}
+};
+
+/*!
+ * jQuery Color Animations v2.1.2
+ * https://github.com/jquery/jquery-color
+ *
+ * Copyright 2014 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * Date: Wed Jan 16 08:47:09 2013 -0600
+ */
+(function( jQuery, undefined ) {
+
+	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
+
+	// plusequals test for += 100 -= 100
+	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
+	// a set of RE's that can match strings and generate color tuples.
+	stringParsers = [ {
+			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
+			parse: function( execResult ) {
+				return [
+					execResult[ 1 ],
+					execResult[ 2 ],
+					execResult[ 3 ],
+					execResult[ 4 ]
+				];
+			}
+		}, {
+			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
+			parse: function( execResult ) {
+				return [
+					execResult[ 1 ] * 2.55,
+					execResult[ 2 ] * 2.55,
+					execResult[ 3 ] * 2.55,
+					execResult[ 4 ]
+				];
+			}
+		}, {
+			// this regex ignores A-F because it's compared against an already lowercased string
+			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
+			parse: function( execResult ) {
+				return [
+					parseInt( execResult[ 1 ], 16 ),
+					parseInt( execResult[ 2 ], 16 ),
+					parseInt( execResult[ 3 ], 16 )
+				];
+			}
+		}, {
+			// this regex ignores A-F because it's compared against an already lowercased string
+			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
+			parse: function( execResult ) {
+				return [
+					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
+					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
+					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
+				];
+			}
+		}, {
+			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
+			space: "hsla",
+			parse: function( execResult ) {
+				return [
+					execResult[ 1 ],
+					execResult[ 2 ] / 100,
+					execResult[ 3 ] / 100,
+					execResult[ 4 ]
+				];
+			}
+		} ],
+
+	// jQuery.Color( )
+	color = jQuery.Color = function( color, green, blue, alpha ) {
+		return new jQuery.Color.fn.parse( color, green, blue, alpha );
+	},
+	spaces = {
+		rgba: {
+			props: {
+				red: {
+					idx: 0,
+					type: "byte"
+				},
+				green: {
+					idx: 1,
+					type: "byte"
+				},
+				blue: {
+					idx: 2,
+					type: "byte"
+				}
+			}
+		},
+
+		hsla: {
+			props: {
+				hue: {
+					idx: 0,
+					type: "degrees"
+				},
+				saturation: {
+					idx: 1,
+					type: "percent"
+				},
+				lightness: {
+					idx: 2,
+					type: "percent"
+				}
+			}
+		}
+	},
+	propTypes = {
+		"byte": {
+			floor: true,
+			max: 255
+		},
+		"percent": {
+			max: 1
+		},
+		"degrees": {
+			mod: 360,
+			floor: true
+		}
+	},
+	support = color.support = {},
+
+	// element for support tests
+	supportElem = jQuery( "<p>" )[ 0 ],
+
+	// colors = jQuery.Color.names
+	colors,
+
+	// local aliases of functions called often
+	each = jQuery.each;
+
+// determine rgba support immediately
+supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
+support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
+
+// define cache name and alpha properties
+// for rgba and hsla spaces
+each( spaces, function( spaceName, space ) {
+	space.cache = "_" + spaceName;
+	space.props.alpha = {
+		idx: 3,
+		type: "percent",
+		def: 1
+	};
+});
+
+function clamp( value, prop, allowEmpty ) {
+	var type = propTypes[ prop.type ] || {};
+
+	if ( value == null ) {
+		return (allowEmpty || !prop.def) ? null : prop.def;
+	}
+
+	// ~~ is an short way of doing floor for positive numbers
+	value = type.floor ? ~~value : parseFloat( value );
+
+	// IE will pass in empty strings as value for alpha,
+	// which will hit this case
+	if ( isNaN( value ) ) {
+		return prop.def;
+	}
+
+	if ( type.mod ) {
+		// we add mod before modding to make sure that negatives values
+		// get converted properly: -10 -> 350
+		return (value + type.mod) % type.mod;
+	}
+
+	// for now all property types without mod have min and max
+	return 0 > value ? 0 : type.max < value ? type.max : value;
+}
+
+function stringParse( string ) {
+	var inst = color(),
+		rgba = inst._rgba = [];
+
+	string = string.toLowerCase();
+
+	each( stringParsers, function( i, parser ) {
+		var parsed,
+			match = parser.re.exec( string ),
+			values = match && parser.parse( match ),
+			spaceName = parser.space || "rgba";
+
+		if ( values ) {
+			parsed = inst[ spaceName ]( values );
+
+			// if this was an rgba parse the assignment might happen twice
+			// oh well....
+			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
+			rgba = inst._rgba = parsed._rgba;
+
+			// exit each( stringParsers ) here because we matched
+			return false;
+		}
+	});
+
+	// Found a stringParser that handled it
+	if ( rgba.length ) {
+
+		// if this came from a parsed string, force "transparent" when alpha is 0
+		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
+		if ( rgba.join() === "0,0,0,0" ) {
+			jQuery.extend( rgba, colors.transparent );
+		}
+		return inst;
+	}
+
+	// named colors
+	return colors[ string ];
+}
+
+color.fn = jQuery.extend( color.prototype, {
+	parse: function( red, green, blue, alpha ) {
+		if ( red === undefined ) {
+			this._rgba = [ null, null, null, null ];
+			return this;
+		}
+		if ( red.jquery || red.nodeType ) {
+			red = jQuery( red ).css( green );
+			green = undefined;
+		}
+
+		var inst = this,
+			type = jQuery.type( red ),
+			rgba = this._rgba = [];
+
+		// more than 1 argument specified - assume ( red, green, blue, alpha )
+		if ( green !== undefined ) {
+			red = [ red, green, blue, alpha ];
+			type = "array";
+		}
+
+		if ( type === "string" ) {
+			return this.parse( stringParse( red ) || colors._default );
+		}
+
+		if ( type === "array" ) {
+			each( spaces.rgba.props, function( key, prop ) {
+				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
+			});
+			return this;
+		}
+
+		if ( type === "object" ) {
+			if ( red instanceof color ) {
+				each( spaces, function( spaceName, space ) {
+					if ( red[ space.cache ] ) {
+						inst[ space.cache ] = red[ space.cache ].slice();
+					}
+				});
+			} else {
+				each( spaces, function( spaceName, space ) {
+					var cache = space.cache;
+					each( space.props, function( key, prop ) {
+
+						// if the cache doesn't exist, and we know how to convert
+						if ( !inst[ cache ] && space.to ) {
+
+							// if the value was null, we don't need to copy it
+							// if the key was alpha, we don't need to copy it either
+							if ( key === "alpha" || red[ key ] == null ) {
+								return;
+							}
+							inst[ cache ] = space.to( inst._rgba );
+						}
+
+						// this is the only case where we allow nulls for ALL properties.
+						// call clamp with alwaysAllowEmpty
+						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
+					});
+
+					// everything defined but alpha?
+					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
+						// use the default of 1
+						inst[ cache ][ 3 ] = 1;
+						if ( space.from ) {
+							inst._rgba = space.from( inst[ cache ] );
+						}
+					}
+				});
+			}
+			return this;
+		}
+	},
+	is: function( compare ) {
+		var is = color( compare ),
+			same = true,
+			inst = this;
+
+		each( spaces, function( _, space ) {
+			var localCache,
+				isCache = is[ space.cache ];
+			if (isCache) {
+				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
+				each( space.props, function( _, prop ) {
+					if ( isCache[ prop.idx ] != null ) {
+						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
+						return same;
+					}
+				});
+			}
+			return same;
+		});
+		return same;
+	},
+	_space: function() {
+		var used = [],
+			inst = this;
+		each( spaces, function( spaceName, space ) {
+			if ( inst[ space.cache ] ) {
+				used.push( spaceName );
+			}
+		});
+		return used.pop();
+	},
+	transition: function( other, distance ) {
+		var end = color( other ),
+			spaceName = end._space(),
+			space = spaces[ spaceName ],
+			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
+			start = startColor[ space.cache ] || space.to( startColor._rgba ),
+			result = start.slice();
+
+		end = end[ space.cache ];
+		each( space.props, function( key, prop ) {
+			var index = prop.idx,
+				startValue = start[ index ],
+				endValue = end[ index ],
+				type = propTypes[ prop.type ] || {};
+
+			// if null, don't override start value
+			if ( endValue === null ) {
+				return;
+			}
+			// if null - use end
+			if ( startValue === null ) {
+				result[ index ] = endValue;
+			} else {
+				if ( type.mod ) {
+					if ( endValue - startValue > type.mod / 2 ) {
+						startValue += type.mod;
+					} else if ( startValue - endValue > type.mod / 2 ) {
+						startValue -= type.mod;
+					}
+				}
+				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
+			}
+		});
+		return this[ spaceName ]( result );
+	},
+	blend: function( opaque ) {
+		// if we are already opaque - return ourself
+		if ( this._rgba[ 3 ] === 1 ) {
+			return this;
+		}
+
+		var rgb = this._rgba.slice(),
+			a = rgb.pop(),
+			blend = color( opaque )._rgba;
+
+		return color( jQuery.map( rgb, function( v, i ) {
+			return ( 1 - a ) * blend[ i ] + a * v;
+		}));
+	},
+	toRgbaString: function() {
+		var prefix = "rgba(",
+			rgba = jQuery.map( this._rgba, function( v, i ) {
+				return v == null ? ( i > 2 ? 1 : 0 ) : v;
+			});
+
+		if ( rgba[ 3 ] === 1 ) {
+			rgba.pop();
+			prefix = "rgb(";
+		}
+
+		return prefix + rgba.join() + ")";
+	},
+	toHslaString: function() {
+		var prefix = "hsla(",
+			hsla = jQuery.map( this.hsla(), function( v, i ) {
+				if ( v == null ) {
+					v = i > 2 ? 1 : 0;
+				}
+
+				// catch 1 and 2
+				if ( i && i < 3 ) {
+					v = Math.round( v * 100 ) + "%";
+				}
+				return v;
+			});
+
+		if ( hsla[ 3 ] === 1 ) {
+			hsla.pop();
+			prefix = "hsl(";
+		}
+		return prefix + hsla.join() + ")";
+	},
+	toHexString: function( includeAlpha ) {
+		var rgba = this._rgba.slice(),
+			alpha = rgba.pop();
+
+		if ( includeAlpha ) {
+			rgba.push( ~~( alpha * 255 ) );
+		}
+
+		return "#" + jQuery.map( rgba, function( v ) {
+
+			// default to 0 when nulls exist
+			v = ( v || 0 ).toString( 16 );
+			return v.length === 1 ? "0" + v : v;
+		}).join("");
+	},
+	toString: function() {
+		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
+	}
+});
+color.fn.parse.prototype = color.fn;
+
+// hsla conversions adapted from:
+// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
+
+function hue2rgb( p, q, h ) {
+	h = ( h + 1 ) % 1;
+	if ( h * 6 < 1 ) {
+		return p + ( q - p ) * h * 6;
+	}
+	if ( h * 2 < 1) {
+		return q;
+	}
+	if ( h * 3 < 2 ) {
+		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
+	}
+	return p;
+}
+
+spaces.hsla.to = function( rgba ) {
+	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
+		return [ null, null, null, rgba[ 3 ] ];
+	}
+	var r = rgba[ 0 ] / 255,
+		g = rgba[ 1 ] / 255,
+		b = rgba[ 2 ] / 255,
+		a = rgba[ 3 ],
+		max = Math.max( r, g, b ),
+		min = Math.min( r, g, b ),
+		diff = max - min,
+		add = max + min,
+		l = add * 0.5,
+		h, s;
+
+	if ( min === max ) {
+		h = 0;
+	} else if ( r === max ) {
+		h = ( 60 * ( g - b ) / diff ) + 360;
+	} else if ( g === max ) {
+		h = ( 60 * ( b - r ) / diff ) + 120;
+	} else {
+		h = ( 60 * ( r - g ) / diff ) + 240;
+	}
+
+	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
+	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
+	if ( diff === 0 ) {
+		s = 0;
+	} else if ( l <= 0.5 ) {
+		s = diff / add;
+	} else {
+		s = diff / ( 2 - add );
+	}
+	return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
+};
+
+spaces.hsla.from = function( hsla ) {
+	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
+		return [ null, null, null, hsla[ 3 ] ];
+	}
+	var h = hsla[ 0 ] / 360,
+		s = hsla[ 1 ],
+		l = hsla[ 2 ],
+		a = hsla[ 3 ],
+		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
+		p = 2 * l - q;
+
+	return [
+		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
+		Math.round( hue2rgb( p, q, h ) * 255 ),
+		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
+		a
+	];
+};
+
+each( spaces, function( spaceName, space ) {
+	var props = space.props,
+		cache = space.cache,
+		to = space.to,
+		from = space.from;
+
+	// makes rgba() and hsla()
+	color.fn[ spaceName ] = function( value ) {
+
+		// generate a cache for this space if it doesn't exist
+		if ( to && !this[ cache ] ) {
+			this[ cache ] = to( this._rgba );
+		}
+		if ( value === undefined ) {
+			return this[ cache ].slice();
+		}
+
+		var ret,
+			type = jQuery.type( value ),
+			arr = ( type === "array" || type === "object" ) ? value : arguments,
+			local = this[ cache ].slice();
+
+		each( props, function( key, prop ) {
+			var val = arr[ type === "object" ? key : prop.idx ];
+			if ( val == null ) {
+				val = local[ prop.idx ];
+			}
+			local[ prop.idx ] = clamp( val, prop );
+		});
+
+		if ( from ) {
+			ret = color( from( local ) );
+			ret[ cache ] = local;
+			return ret;
+		} else {
+			return color( local );
+		}
+	};
+
+	// makes red() green() blue() alpha() hue() saturation() lightness()
+	each( props, function( key, prop ) {
+		// alpha is included in more than one space
+		if ( color.fn[ key ] ) {
+			return;
+		}
+		color.fn[ key ] = function( value ) {
+			var vtype = jQuery.type( value ),
+				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
+				local = this[ fn ](),
+				cur = local[ prop.idx ],
+				match;
+
+			if ( vtype === "undefined" ) {
+				return cur;
+			}
+
+			if ( vtype === "function" ) {
+				value = value.call( this, cur );
+				vtype = jQuery.type( value );
+			}
+			if ( value == null && prop.empty ) {
+				return this;
+			}
+			if ( vtype === "string" ) {
+				match = rplusequals.exec( value );
+				if ( match ) {
+					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
+				}
+			}
+			local[ prop.idx ] = value;
+			return this[ fn ]( local );
+		};
+	});
+});
+
+// add cssHook and .fx.step function for each named hook.
+// accept a space separated string of properties
+color.hook = function( hook ) {
+	var hooks = hook.split( " " );
+	each( hooks, function( i, hook ) {
+		jQuery.cssHooks[ hook ] = {
+			set: function( elem, value ) {
+				var parsed, curElem,
+					backgroundColor = "";
+
+				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
+					value = color( parsed || value );
+					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
+						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
+						while (
+							(backgroundColor === "" || backgroundColor === "transparent") &&
+							curElem && curElem.style
+						) {
+							try {
+								backgroundColor = jQuery.css( curElem, "backgroundColor" );
+								curElem = curElem.parentNode;
+							} catch ( e ) {
+							}
+						}
+
+						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
+							backgroundColor :
+							"_default" );
+					}
+
+					value = value.toRgbaString();
+				}
+				try {
+					elem.style[ hook ] = value;
+				} catch ( e ) {
+					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
+				}
+			}
+		};
+		jQuery.fx.step[ hook ] = function( fx ) {
+			if ( !fx.colorInit ) {
+				fx.start = color( fx.elem, hook );
+				fx.end = color( fx.end );
+				fx.colorInit = true;
+			}
+			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
+		};
+	});
+
+};
+
+color.hook( stepHooks );
+
+jQuery.cssHooks.borderColor = {
+	expand: function( value ) {
+		var expanded = {};
+
+		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
+			expanded[ "border" + part + "Color" ] = value;
+		});
+		return expanded;
+	}
+};
+
+// Basic color names only.
+// Usage of any of the other color names requires adding yourself or including
+// jquery.color.svg-names.js.
+colors = jQuery.Color.names = {
+	// 4.1. Basic color keywords
+	aqua: "#00ffff",
+	black: "#000000",
+	blue: "#0000ff",
+	fuchsia: "#ff00ff",
+	gray: "#808080",
+	green: "#008000",
+	lime: "#00ff00",
+	maroon: "#800000",
+	navy: "#000080",
+	olive: "#808000",
+	purple: "#800080",
+	red: "#ff0000",
+	silver: "#c0c0c0",
+	teal: "#008080",
+	white: "#ffffff",
+	yellow: "#ffff00",
+
+	// 4.2.3. "transparent" color keyword
+	transparent: [ null, null, null, 0 ],
+
+	_default: "#ffffff"
+};
+
+})( jQuery );
+
+/******************************************************************************/
+/****************************** CLASS ANIMATIONS ******************************/
+/******************************************************************************/
+(function() {
+
+var classAnimationActions = [ "add", "remove", "toggle" ],
+	shorthandStyles = {
+		border: 1,
+		borderBottom: 1,
+		borderColor: 1,
+		borderLeft: 1,
+		borderRight: 1,
+		borderTop: 1,
+		borderWidth: 1,
+		margin: 1,
+		padding: 1
+	};
+
+$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
+	$.fx.step[ prop ] = function( fx ) {
+		if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
+			jQuery.style( fx.elem, prop, fx.end );
+			fx.setAttr = true;
+		}
+	};
+});
+
+function getElementStyles( elem ) {
+	var key, len,
+		style = elem.ownerDocument.defaultView ?
+			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
+			elem.currentStyle,
+		styles = {};
+
+	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
+		len = style.length;
+		while ( len-- ) {
+			key = style[ len ];
+			if ( typeof style[ key ] === "string" ) {
+				styles[ $.camelCase( key ) ] = style[ key ];
+			}
+		}
+	// support: Opera, IE <9
+	} else {
+		for ( key in style ) {
+			if ( typeof style[ key ] === "string" ) {
+				styles[ key ] = style[ key ];
+			}
+		}
+	}
+
+	return styles;
+}
+
+function styleDifference( oldStyle, newStyle ) {
+	var diff = {},
+		name, value;
+
+	for ( name in newStyle ) {
+		value = newStyle[ name ];
+		if ( oldStyle[ name ] !== value ) {
+			if ( !shorthandStyles[ name ] ) {
+				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
+					diff[ name ] = value;
+				}
+			}
+		}
+	}
+
+	return diff;
+}
+
+// support: jQuery <1.8
+if ( !$.fn.addBack ) {
+	$.fn.addBack = function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter( selector )
+		);
+	};
+}
+
+$.effects.animateClass = function( value, duration, easing, callback ) {
+	var o = $.speed( duration, easing, callback );
+
+	return this.queue( function() {
+		var animated = $( this ),
+			baseClass = animated.attr( "class" ) || "",
+			applyClassChange,
+			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
+
+		// map the animated objects to store the original styles.
+		allAnimations = allAnimations.map(function() {
+			var el = $( this );
+			return {
+				el: el,
+				start: getElementStyles( this )
+			};
+		});
+
+		// apply class change
+		applyClassChange = function() {
+			$.each( classAnimationActions, function(i, action) {
+				if ( value[ action ] ) {
+					animated[ action + "Class" ]( value[ action ] );
+				}
+			});
+		};
+		applyClassChange();
+
+		// map all animated objects again - calculate new styles and diff
+		allAnimations = allAnimations.map(function() {
+			this.end = getElementStyles( this.el[ 0 ] );
+			this.diff = styleDifference( this.start, this.end );
+			return this;
+		});
+
+		// apply original class
+		animated.attr( "class", baseClass );
+
+		// map all animated objects again - this time collecting a promise
+		allAnimations = allAnimations.map(function() {
+			var styleInfo = this,
+				dfd = $.Deferred(),
+				opts = $.extend({}, o, {
+					queue: false,
+					complete: function() {
+						dfd.resolve( styleInfo );
+					}
+				});
+
+			this.el.animate( this.diff, opts );
+			return dfd.promise();
+		});
+
+		// once all animations have completed:
+		$.when.apply( $, allAnimations.get() ).done(function() {
+
+			// set the final class
+			applyClassChange();
+
+			// for each animated element,
+			// clear all css properties that were animated
+			$.each( arguments, function() {
+				var el = this.el;
+				$.each( this.diff, function(key) {
+					el.css( key, "" );
+				});
+			});
+
+			// this is guarnteed to be there if you use jQuery.speed()
+			// it also handles dequeuing the next anim...
+			o.complete.call( animated[ 0 ] );
+		});
+	});
+};
+
+$.fn.extend({
+	addClass: (function( orig ) {
+		return function( classNames, speed, easing, callback ) {
+			return speed ?
+				$.effects.animateClass.call( this,
+					{ add: classNames }, speed, easing, callback ) :
+				orig.apply( this, arguments );
+		};
+	})( $.fn.addClass ),
+
+	removeClass: (function( orig ) {
+		return function( classNames, speed, easing, callback ) {
+			return arguments.length > 1 ?
+				$.effects.animateClass.call( this,
+					{ remove: classNames }, speed, easing, callback ) :
+				orig.apply( this, arguments );
+		};
+	})( $.fn.removeClass ),
+
+	toggleClass: (function( orig ) {
+		return function( classNames, force, speed, easing, callback ) {
+			if ( typeof force === "boolean" || force === undefined ) {
+				if ( !speed ) {
+					// without speed parameter
+					return orig.apply( this, arguments );
+				} else {
+					return $.effects.animateClass.call( this,
+						(force ? { add: classNames } : { remove: classNames }),
+						speed, easing, callback );
+				}
+			} else {
+				// without force parameter
+				return $.effects.animateClass.call( this,
+					{ toggle: classNames }, force, speed, easing );
+			}
+		};
+	})( $.fn.toggleClass ),
+
+	switchClass: function( remove, add, speed, easing, callback) {
+		return $.effects.animateClass.call( this, {
+			add: add,
+			remove: remove
+		}, speed, easing, callback );
+	}
+});
+
+})();
+
+/******************************************************************************/
+/*********************************** EFFECTS **********************************/
+/******************************************************************************/
+
+(function() {
+
+$.extend( $.effects, {
+	version: "1.11.4",
+
+	// Saves a set of properties in a data storage
+	save: function( element, set ) {
+		for ( var i = 0; i < set.length; i++ ) {
+			if ( set[ i ] !== null ) {
+				element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
+			}
+		}
+	},
+
+	// Restores a set of previously saved properties from a data storage
+	restore: function( element, set ) {
+		var val, i;
+		for ( i = 0; i < set.length; i++ ) {
+			if ( set[ i ] !== null ) {
+				val = element.data( dataSpace + set[ i ] );
+				// support: jQuery 1.6.2
+				// http://bugs.jquery.com/ticket/9917
+				// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
+				// We can't differentiate between "" and 0 here, so we just assume
+				// empty string since it's likely to be a more common value...
+				if ( val === undefined ) {
+					val = "";
+				}
+				element.css( set[ i ], val );
+			}
+		}
+	},
+
+	setMode: function( el, mode ) {
+		if (mode === "toggle") {
+			mode = el.is( ":hidden" ) ? "show" : "hide";
+		}
+		return mode;
+	},
+
+	// Translates a [top,left] array into a baseline value
+	// this should be a little more flexible in the future to handle a string & hash
+	getBaseline: function( origin, original ) {
+		var y, x;
+		switch ( origin[ 0 ] ) {
+			case "top": y = 0; break;
+			case "middle": y = 0.5; break;
+			case "bottom": y = 1; break;
+			default: y = origin[ 0 ] / original.height;
+		}
+		switch ( origin[ 1 ] ) {
+			case "left": x = 0; break;
+			case "center": x = 0.5; break;
+			case "right": x = 1; break;
+			default: x = origin[ 1 ] / original.width;
+		}
+		return {
+			x: x,
+			y: y
+		};
+	},
+
+	// Wraps the element around a wrapper that copies position properties
+	createWrapper: function( element ) {
+
+		// if the element is already wrapped, return it
+		if ( element.parent().is( ".ui-effects-wrapper" )) {
+			return element.parent();
+		}
+
+		// wrap the element
+		var props = {
+				width: element.outerWidth(true),
+				height: element.outerHeight(true),
+				"float": element.css( "float" )
+			},
+			wrapper = $( "<div></div>" )
+				.addClass( "ui-effects-wrapper" )
+				.css({
+					fontSize: "100%",
+					background: "transparent",
+					border: "none",
+					margin: 0,
+					padding: 0
+				}),
+			// Store the size in case width/height are defined in % - Fixes #5245
+			size = {
+				width: element.width(),
+				height: element.height()
+			},
+			active = document.activeElement;
+
+		// support: Firefox
+		// Firefox incorrectly exposes anonymous content
+		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
+		try {
+			active.id;
+		} catch ( e ) {
+			active = document.body;
+		}
+
+		element.wrap( wrapper );
+
+		// Fixes #7595 - Elements lose focus when wrapped.
+		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+			$( active ).focus();
+		}
+
+		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
+
+		// transfer positioning properties to the wrapper
+		if ( element.css( "position" ) === "static" ) {
+			wrapper.css({ position: "relative" });
+			element.css({ position: "relative" });
+		} else {
+			$.extend( props, {
+				position: element.css( "position" ),
+				zIndex: element.css( "z-index" )
+			});
+			$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
+				props[ pos ] = element.css( pos );
+				if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
+					props[ pos ] = "auto";
+				}
+			});
+			element.css({
+				position: "relative",
+				top: 0,
+				left: 0,
+				right: "auto",
+				bottom: "auto"
+			});
+		}
+		element.css(size);
+
+		return wrapper.css( props ).show();
+	},
+
+	removeWrapper: function( element ) {
+		var active = document.activeElement;
+
+		if ( element.parent().is( ".ui-effects-wrapper" ) ) {
+			element.parent().replaceWith( element );
+
+			// Fixes #7595 - Elements lose focus when wrapped.
+			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+				$( active ).focus();
+			}
+		}
+
+		return element;
+	},
+
+	setTransition: function( element, list, factor, value ) {
+		value = value || {};
+		$.each( list, function( i, x ) {
+			var unit = element.cssUnit( x );
+			if ( unit[ 0 ] > 0 ) {
+				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
+			}
+		});
+		return value;
+	}
+});
+
+// return an effect options object for the given parameters:
+function _normalizeArguments( effect, options, speed, callback ) {
+
+	// allow passing all options as the first parameter
+	if ( $.isPlainObject( effect ) ) {
+		options = effect;
+		effect = effect.effect;
+	}
+
+	// convert to an object
+	effect = { effect: effect };
+
+	// catch (effect, null, ...)
+	if ( options == null ) {
+		options = {};
+	}
+
+	// catch (effect, callback)
+	if ( $.isFunction( options ) ) {
+		callback = options;
+		speed = null;
+		options = {};
+	}
+
+	// catch (effect, speed, ?)
+	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
+		callback = speed;
+		speed = options;
+		options = {};
+	}
+
+	// catch (effect, options, callback)
+	if ( $.isFunction( speed ) ) {
+		callback = speed;
+		speed = null;
+	}
+
+	// add options to effect
+	if ( options ) {
+		$.extend( effect, options );
+	}
+
+	speed = speed || options.duration;
+	effect.duration = $.fx.off ? 0 :
+		typeof speed === "number" ? speed :
+		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
+		$.fx.speeds._default;
+
+	effect.complete = callback || options.complete;
+
+	return effect;
+}
+
+function standardAnimationOption( option ) {
+	// Valid standard speeds (nothing, number, named speed)
+	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
+		return true;
+	}
+
+	// Invalid strings - treat as "normal" speed
+	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
+		return true;
+	}
+
+	// Complete callback
+	if ( $.isFunction( option ) ) {
+		return true;
+	}
+
+	// Options hash (but not naming an effect)
+	if ( typeof option === "object" && !option.effect ) {
+		return true;
+	}
+
+	// Didn't match any standard API
+	return false;
+}
+
+$.fn.extend({
+	effect: function( /* effect, options, speed, callback */ ) {
+		var args = _normalizeArguments.apply( this, arguments ),
+			mode = args.mode,
+			queue = args.queue,
+			effectMethod = $.effects.effect[ args.effect ];
+
+		if ( $.fx.off || !effectMethod ) {
+			// delegate to the original method (e.g., .show()) if possible
+			if ( mode ) {
+				return this[ mode ]( args.duration, args.complete );
+			} else {
+				return this.each( function() {
+					if ( args.complete ) {
+						args.complete.call( this );
+					}
+				});
+			}
+		}
+
+		function run( next ) {
+			var elem = $( this ),
+				complete = args.complete,
+				mode = args.mode;
+
+			function done() {
+				if ( $.isFunction( complete ) ) {
+					complete.call( elem[0] );
+				}
+				if ( $.isFunction( next ) ) {
+					next();
+				}
+			}
+
+			// If the element already has the correct final state, delegate to
+			// the core methods so the internal tracking of "olddisplay" works.
+			if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
+				elem[ mode ]();
+				done();
+			} else {
+				effectMethod.call( elem[0], args, done );
+			}
+		}
+
+		return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
+	},
+
+	show: (function( orig ) {
+		return function( option ) {
+			if ( standardAnimationOption( option ) ) {
+				return orig.apply( this, arguments );
+			} else {
+				var args = _normalizeArguments.apply( this, arguments );
+				args.mode = "show";
+				return this.effect.call( this, args );
+			}
+		};
+	})( $.fn.show ),
+
+	hide: (function( orig ) {
+		return function( option ) {
+			if ( standardAnimationOption( option ) ) {
+				return orig.apply( this, arguments );
+			} else {
+				var args = _normalizeArguments.apply( this, arguments );
+				args.mode = "hide";
+				return this.effect.call( this, args );
+			}
+		};
+	})( $.fn.hide ),
+
+	toggle: (function( orig ) {
+		return function( option ) {
+			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
+				return orig.apply( this, arguments );
+			} else {
+				var args = _normalizeArguments.apply( this, arguments );
+				args.mode = "toggle";
+				return this.effect.call( this, args );
+			}
+		};
+	})( $.fn.toggle ),
+
+	// helper functions
+	cssUnit: function(key) {
+		var style = this.css( key ),
+			val = [];
+
+		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
+			if ( style.indexOf( unit ) > 0 ) {
+				val = [ parseFloat( style ), unit ];
+			}
+		});
+		return val;
+	}
+});
+
+})();
+
+/******************************************************************************/
+/*********************************** EASING ***********************************/
+/******************************************************************************/
+
+(function() {
+
+// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
+
+var baseEasings = {};
+
+$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
+	baseEasings[ name ] = function( p ) {
+		return Math.pow( p, i + 2 );
+	};
+});
+
+$.extend( baseEasings, {
+	Sine: function( p ) {
+		return 1 - Math.cos( p * Math.PI / 2 );
+	},
+	Circ: function( p ) {
+		return 1 - Math.sqrt( 1 - p * p );
+	},
+	Elastic: function( p ) {
+		return p === 0 || p === 1 ? p :
+			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
+	},
+	Back: function( p ) {
+		return p * p * ( 3 * p - 2 );
+	},
+	Bounce: function( p ) {
+		var pow2,
+			bounce = 4;
+
+		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
+		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
+	}
+});
+
+$.each( baseEasings, function( name, easeIn ) {
+	$.easing[ "easeIn" + name ] = easeIn;
+	$.easing[ "easeOut" + name ] = function( p ) {
+		return 1 - easeIn( 1 - p );
+	};
+	$.easing[ "easeInOut" + name ] = function( p ) {
+		return p < 0.5 ?
+			easeIn( p * 2 ) / 2 :
+			1 - easeIn( p * -2 + 2 ) / 2;
+	};
+});
+
+})();
+
+var effect = $.effects;
+
+
+/*!
+ * jQuery UI Effects Blind 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/blind-effect/
+ */
+
+
+var effectBlind = $.effects.effect.blind = function( o, done ) {
+	// Create element
+	var el = $( this ),
+		rvertical = /up|down|vertical/,
+		rpositivemotion = /up|left|vertical|horizontal/,
+		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+		mode = $.effects.setMode( el, o.mode || "hide" ),
+		direction = o.direction || "up",
+		vertical = rvertical.test( direction ),
+		ref = vertical ? "height" : "width",
+		ref2 = vertical ? "top" : "left",
+		motion = rpositivemotion.test( direction ),
+		animation = {},
+		show = mode === "show",
+		wrapper, distance, margin;
+
+	// if already wrapped, the wrapper's properties are my property. #6245
+	if ( el.parent().is( ".ui-effects-wrapper" ) ) {
+		$.effects.save( el.parent(), props );
+	} else {
+		$.effects.save( el, props );
+	}
+	el.show();
+	wrapper = $.effects.createWrapper( el ).css({
+		overflow: "hidden"
+	});
+
+	distance = wrapper[ ref ]();
+	margin = parseFloat( wrapper.css( ref2 ) ) || 0;
+
+	animation[ ref ] = show ? distance : 0;
+	if ( !motion ) {
+		el
+			.css( vertical ? "bottom" : "right", 0 )
+			.css( vertical ? "top" : "left", "auto" )
+			.css({ position: "absolute" });
+
+		animation[ ref2 ] = show ? margin : distance + margin;
+	}
+
+	// start at 0 if we are showing
+	if ( show ) {
+		wrapper.css( ref, 0 );
+		if ( !motion ) {
+			wrapper.css( ref2, margin + distance );
+		}
+	}
+
+	// Animate
+	wrapper.animate( animation, {
+		duration: o.duration,
+		easing: o.easing,
+		queue: false,
+		complete: function() {
+			if ( mode === "hide" ) {
+				el.hide();
+			}
+			$.effects.restore( el, props );
+			$.effects.removeWrapper( el );
+			done();
+		}
+	});
+};
+
+
+/*!
+ * jQuery UI Effects Bounce 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/bounce-effect/
+ */
+
+
+var effectBounce = $.effects.effect.bounce = function( o, done ) {
+	var el = $( this ),
+		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+
+		// defaults:
+		mode = $.effects.setMode( el, o.mode || "effect" ),
+		hide = mode === "hide",
+		show = mode === "show",
+		direction = o.direction || "up",
+		distance = o.distance,
+		times = o.times || 5,
+
+		// number of internal animations
+		anims = times * 2 + ( show || hide ? 1 : 0 ),
+		speed = o.duration / anims,
+		easing = o.easing,
+
+		// utility:
+		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
+		motion = ( direction === "up" || direction === "left" ),
+		i,
+		upAnim,
+		downAnim,
+
+		// we will need to re-assemble the queue to stack our animations in place
+		queue = el.queue(),
+		queuelen = queue.length;
+
+	// Avoid touching opacity to prevent clearType and PNG issues in IE
+	if ( show || hide ) {
+		props.push( "opacity" );
+	}
+
+	$.effects.save( el, props );
+	el.show();
+	$.effects.createWrapper( el ); // Create Wrapper
+
+	// default distance for the BIGGEST bounce is the outer Distance / 3
+	if ( !distance ) {
+		distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
+	}
+
+	if ( show ) {
+		downAnim = { opacity: 1 };
+		downAnim[ ref ] = 0;
+
+		// if we are showing, force opacity 0 and set the initial position
+		// then do the "first" animation
+		el.css( "opacity", 0 )
+			.css( ref, motion ? -distance * 2 : distance * 2 )
+			.animate( downAnim, speed, easing );
+	}
+
+	// start at the smallest distance if we are hiding
+	if ( hide ) {
+		distance = distance / Math.pow( 2, times - 1 );
+	}
+
+	downAnim = {};
+	downAnim[ ref ] = 0;
+	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
+	for ( i = 0; i < times; i++ ) {
+		upAnim = {};
+		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
+
+		el.animate( upAnim, speed, easing )
+			.animate( downAnim, speed, easing );
+
+		distance = hide ? distance * 2 : distance / 2;
+	}
+
+	// Last Bounce when Hiding
+	if ( hide ) {
+		upAnim = { opacity: 0 };
+		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
+
+		el.animate( upAnim, speed, easing );
+	}
+
+	el.queue(function() {
+		if ( hide ) {
+			el.hide();
+		}
+		$.effects.restore( el, props );
+		$.effects.removeWrapper( el );
+		done();
+	});
+
+	// inject all the animations we just queued to be first in line (after "inprogress")
+	if ( queuelen > 1) {
+		queue.splice.apply( queue,
+			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
+	}
+	el.dequeue();
+
+};
+
+
+/*!
+ * jQuery UI Effects Clip 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/clip-effect/
+ */
+
+
+var effectClip = $.effects.effect.clip = function( o, done ) {
+	// Create element
+	var el = $( this ),
+		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+		mode = $.effects.setMode( el, o.mode || "hide" ),
+		show = mode === "show",
+		direction = o.direction || "vertical",
+		vert = direction === "vertical",
+		size = vert ? "height" : "width",
+		position = vert ? "top" : "left",
+		animation = {},
+		wrapper, animate, distance;
+
+	// Save & Show
+	$.effects.save( el, props );
+	el.show();
+
+	// Create Wrapper
+	wrapper = $.effects.createWrapper( el ).css({
+		overflow: "hidden"
+	});
+	animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
+	distance = animate[ size ]();
+
+	// Shift
+	if ( show ) {
+		animate.css( size, 0 );
+		animate.css( position, distance / 2 );
+	}
+
+	// Create Animation Object:
+	animation[ size ] = show ? distance : 0;
+	animation[ position ] = show ? 0 : distance / 2;
+
+	// Animate
+	animate.animate( animation, {
+		queue: false,
+		duration: o.duration,
+		easing: o.easing,
+		complete: function() {
+			if ( !show ) {
+				el.hide();
+			}
+			$.effects.restore( el, props );
+			$.effects.removeWrapper( el );
+			done();
+		}
+	});
+
+};
+
+
+/*!
+ * jQuery UI Effects Drop 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/drop-effect/
+ */
+
+
+var effectDrop = $.effects.effect.drop = function( o, done ) {
+
+	var el = $( this ),
+		props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
+		mode = $.effects.setMode( el, o.mode || "hide" ),
+		show = mode === "show",
+		direction = o.direction || "left",
+		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
+		motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
+		animation = {
+			opacity: show ? 1 : 0
+		},
+		distance;
+
+	// Adjust
+	$.effects.save( el, props );
+	el.show();
+	$.effects.createWrapper( el );
+
+	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
+
+	if ( show ) {
+		el
+			.css( "opacity", 0 )
+			.css( ref, motion === "pos" ? -distance : distance );
+	}
+
+	// Animation
+	animation[ ref ] = ( show ?
+		( motion === "pos" ? "+=" : "-=" ) :
+		( motion === "pos" ? "-=" : "+=" ) ) +
+		distance;
+
+	// Animate
+	el.animate( animation, {
+		queue: false,
+		duration: o.duration,
+		easing: o.easing,
+		complete: function() {
+			if ( mode === "hide" ) {
+				el.hide();
+			}
+			$.effects.restore( el, props );
+			$.effects.removeWrapper( el );
+			done();
+		}
+	});
+};
+
+
+/*!
+ * jQuery UI Effects Explode 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/explode-effect/
+ */
+
+
+var effectExplode = $.effects.effect.explode = function( o, done ) {
+
+	var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
+		cells = rows,
+		el = $( this ),
+		mode = $.effects.setMode( el, o.mode || "hide" ),
+		show = mode === "show",
+
+		// show and then visibility:hidden the element before calculating offset
+		offset = el.show().css( "visibility", "hidden" ).offset(),
+
+		// width and height of a piece
+		width = Math.ceil( el.outerWidth() / cells ),
+		height = Math.ceil( el.outerHeight() / rows ),
+		pieces = [],
+
+		// loop
+		i, j, left, top, mx, my;
+
+	// children animate complete:
+	function childComplete() {
+		pieces.push( this );
+		if ( pieces.length === rows * cells ) {
+			animComplete();
+		}
+	}
+
+	// clone the element for each row and cell.
+	for ( i = 0; i < rows ; i++ ) { // ===>
+		top = offset.top + i * height;
+		my = i - ( rows - 1 ) / 2 ;
+
+		for ( j = 0; j < cells ; j++ ) { // |||
+			left = offset.left + j * width;
+			mx = j - ( cells - 1 ) / 2 ;
+
+			// Create a clone of the now hidden main element that will be absolute positioned
+			// within a wrapper div off the -left and -top equal to size of our pieces
+			el
+				.clone()
+				.appendTo( "body" )
+				.wrap( "<div></div>" )
+				.css({
+					position: "absolute",
+					visibility: "visible",
+					left: -j * width,
+					top: -i * height
+				})
+
+			// select the wrapper - make it overflow: hidden and absolute positioned based on
+			// where the original was located +left and +top equal to the size of pieces
+				.parent()
+				.addClass( "ui-effects-explode" )
+				.css({
+					position: "absolute",
+					overflow: "hidden",
+					width: width,
+					height: height,
+					left: left + ( show ? mx * width : 0 ),
+					top: top + ( show ? my * height : 0 ),
+					opacity: show ? 0 : 1
+				}).animate({
+					left: left + ( show ? 0 : mx * width ),
+					top: top + ( show ? 0 : my * height ),
+					opacity: show ? 1 : 0
+				}, o.duration || 500, o.easing, childComplete );
+		}
+	}
+
+	function animComplete() {
+		el.css({
+			visibility: "visible"
+		});
+		$( pieces ).remove();
+		if ( !show ) {
+			el.hide();
+		}
+		done();
+	}
+};
+
+
+/*!
+ * jQuery UI Effects Fade 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/fade-effect/
+ */
+
+
+var effectFade = $.effects.effect.fade = function( o, done ) {
+	var el = $( this ),
+		mode = $.effects.setMode( el, o.mode || "toggle" );
+
+	el.animate({
+		opacity: mode
+	}, {
+		queue: false,
+		duration: o.duration,
+		easing: o.easing,
+		complete: done
+	});
+};
+
+
+/*!
+ * jQuery UI Effects Fold 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/fold-effect/
+ */
+
+
+var effectFold = $.effects.effect.fold = function( o, done ) {
+
+	// Create element
+	var el = $( this ),
+		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+		mode = $.effects.setMode( el, o.mode || "hide" ),
+		show = mode === "show",
+		hide = mode === "hide",
+		size = o.size || 15,
+		percent = /([0-9]+)%/.exec( size ),
+		horizFirst = !!o.horizFirst,
+		widthFirst = show !== horizFirst,
+		ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
+		duration = o.duration / 2,
+		wrapper, distance,
+		animation1 = {},
+		animation2 = {};
+
+	$.effects.save( el, props );
+	el.show();
+
+	// Create Wrapper
+	wrapper = $.effects.createWrapper( el ).css({
+		overflow: "hidden"
+	});
+	distance = widthFirst ?
+		[ wrapper.width(), wrapper.height() ] :
+		[ wrapper.height(), wrapper.width() ];
+
+	if ( percent ) {
+		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
+	}
+	if ( show ) {
+		wrapper.css( horizFirst ? {
+			height: 0,
+			width: size
+		} : {
+			height: size,
+			width: 0
+		});
+	}
+
+	// Animation
+	animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
+	animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
+
+	// Animate
+	wrapper
+		.animate( animation1, duration, o.easing )
+		.animate( animation2, duration, o.easing, function() {
+			if ( hide ) {
+				el.hide();
+			}
+			$.effects.restore( el, props );
+			$.effects.removeWrapper( el );
+			done();
+		});
+
+};
+
+
+/*!
+ * jQuery UI Effects Highlight 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/highlight-effect/
+ */
+
+
+var effectHighlight = $.effects.effect.highlight = function( o, done ) {
+	var elem = $( this ),
+		props = [ "backgroundImage", "backgroundColor", "opacity" ],
+		mode = $.effects.setMode( elem, o.mode || "show" ),
+		animation = {
+			backgroundColor: elem.css( "backgroundColor" )
+		};
+
+	if (mode === "hide") {
+		animation.opacity = 0;
+	}
+
+	$.effects.save( elem, props );
+
+	elem
+		.show()
+		.css({
+			backgroundImage: "none",
+			backgroundColor: o.color || "#ffff99"
+		})
+		.animate( animation, {
+			queue: false,
+			duration: o.duration,
+			easing: o.easing,
+			complete: function() {
+				if ( mode === "hide" ) {
+					elem.hide();
+				}
+				$.effects.restore( elem, props );
+				done();
+			}
+		});
+};
+
+
+/*!
+ * jQuery UI Effects Size 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/size-effect/
+ */
+
+
+var effectSize = $.effects.effect.size = function( o, done ) {
+
+	// Create element
+	var original, baseline, factor,
+		el = $( this ),
+		props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
+
+		// Always restore
+		props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
+
+		// Copy for children
+		props2 = [ "width", "height", "overflow" ],
+		cProps = [ "fontSize" ],
+		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
+		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
+
+		// Set options
+		mode = $.effects.setMode( el, o.mode || "effect" ),
+		restore = o.restore || mode !== "effect",
+		scale = o.scale || "both",
+		origin = o.origin || [ "middle", "center" ],
+		position = el.css( "position" ),
+		props = restore ? props0 : props1,
+		zero = {
+			height: 0,
+			width: 0,
+			outerHeight: 0,
+			outerWidth: 0
+		};
+
+	if ( mode === "show" ) {
+		el.show();
+	}
+	original = {
+		height: el.height(),
+		width: el.width(),
+		outerHeight: el.outerHeight(),
+		outerWidth: el.outerWidth()
+	};
+
+	if ( o.mode === "toggle" && mode === "show" ) {
+		el.from = o.to || zero;
+		el.to = o.from || original;
+	} else {
+		el.from = o.from || ( mode === "show" ? zero : original );
+		el.to = o.to || ( mode === "hide" ? zero : original );
+	}
+
+	// Set scaling factor
+	factor = {
+		from: {
+			y: el.from.height / original.height,
+			x: el.from.width / original.width
+		},
+		to: {
+			y: el.to.height / original.height,
+			x: el.to.width / original.width
+		}
+	};
+
+	// Scale the css box
+	if ( scale === "box" || scale === "both" ) {
+
+		// Vertical props scaling
+		if ( factor.from.y !== factor.to.y ) {
+			props = props.concat( vProps );
+			el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
+			el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
+		}
+
+		// Horizontal props scaling
+		if ( factor.from.x !== factor.to.x ) {
+			props = props.concat( hProps );
+			el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
+			el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
+		}
+	}
+
+	// Scale the content
+	if ( scale === "content" || scale === "both" ) {
+
+		// Vertical props scaling
+		if ( factor.from.y !== factor.to.y ) {
+			props = props.concat( cProps ).concat( props2 );
+			el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
+			el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
+		}
+	}
+
+	$.effects.save( el, props );
+	el.show();
+	$.effects.createWrapper( el );
+	el.css( "overflow", "hidden" ).css( el.from );
+
+	// Adjust
+	if (origin) { // Calculate baseline shifts
+		baseline = $.effects.getBaseline( origin, original );
+		el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
+		el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
+		el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
+		el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
+	}
+	el.css( el.from ); // set top & left
+
+	// Animate
+	if ( scale === "content" || scale === "both" ) { // Scale the children
+
+		// Add margins/font-size
+		vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
+		hProps = hProps.concat([ "marginLeft", "marginRight" ]);
+		props2 = props0.concat(vProps).concat(hProps);
+
+		el.find( "*[width]" ).each( function() {
+			var child = $( this ),
+				c_original = {
+					height: child.height(),
+					width: child.width(),
+					outerHeight: child.outerHeight(),
+					outerWidth: child.outerWidth()
+				};
+			if (restore) {
+				$.effects.save(child, props2);
+			}
+
+			child.from = {
+				height: c_original.height * factor.from.y,
+				width: c_original.width * factor.from.x,
+				outerHeight: c_original.outerHeight * factor.from.y,
+				outerWidth: c_original.outerWidth * factor.from.x
+			};
+			child.to = {
+				height: c_original.height * factor.to.y,
+				width: c_original.width * factor.to.x,
+				outerHeight: c_original.height * factor.to.y,
+				outerWidth: c_original.width * factor.to.x
+			};
+
+			// Vertical props scaling
+			if ( factor.from.y !== factor.to.y ) {
+				child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
+				child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
+			}
+
+			// Horizontal props scaling
+			if ( factor.from.x !== factor.to.x ) {
+				child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
+				child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
+			}
+
+			// Animate children
+			child.css( child.from );
+			child.animate( child.to, o.duration, o.easing, function() {
+
+				// Restore children
+				if ( restore ) {
+					$.effects.restore( child, props2 );
+				}
+			});
+		});
+	}
+
+	// Animate
+	el.animate( el.to, {
+		queue: false,
+		duration: o.duration,
+		easing: o.easing,
+		complete: function() {
+			if ( el.to.opacity === 0 ) {
+				el.css( "opacity", el.from.opacity );
+			}
+			if ( mode === "hide" ) {
+				el.hide();
+			}
+			$.effects.restore( el, props );
+			if ( !restore ) {
+
+				// we need to calculate our new positioning based on the scaling
+				if ( position === "static" ) {
+					el.css({
+						position: "relative",
+						top: el.to.top,
+						left: el.to.left
+					});
+				} else {
+					$.each([ "top", "left" ], function( idx, pos ) {
+						el.css( pos, function( _, str ) {
+							var val = parseInt( str, 10 ),
+								toRef = idx ? el.to.left : el.to.top;
+
+							// if original was "auto", recalculate the new value from wrapper
+							if ( str === "auto" ) {
+								return toRef + "px";
+							}
+
+							return val + toRef + "px";
+						});
+					});
+				}
+			}
+
+			$.effects.removeWrapper( el );
+			done();
+		}
+	});
+
+};
+
+
+/*!
+ * jQuery UI Effects Scale 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/scale-effect/
+ */
+
+
+var effectScale = $.effects.effect.scale = function( o, done ) {
+
+	// Create element
+	var el = $( this ),
+		options = $.extend( true, {}, o ),
+		mode = $.effects.setMode( el, o.mode || "effect" ),
+		percent = parseInt( o.percent, 10 ) ||
+			( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
+		direction = o.direction || "both",
+		origin = o.origin,
+		original = {
+			height: el.height(),
+			width: el.width(),
+			outerHeight: el.outerHeight(),
+			outerWidth: el.outerWidth()
+		},
+		factor = {
+			y: direction !== "horizontal" ? (percent / 100) : 1,
+			x: direction !== "vertical" ? (percent / 100) : 1
+		};
+
+	// We are going to pass this effect to the size effect:
+	options.effect = "size";
+	options.queue = false;
+	options.complete = done;
+
+	// Set default origin and restore for show/hide
+	if ( mode !== "effect" ) {
+		options.origin = origin || [ "middle", "center" ];
+		options.restore = true;
+	}
+
+	options.from = o.from || ( mode === "show" ? {
+		height: 0,
+		width: 0,
+		outerHeight: 0,
+		outerWidth: 0
+	} : original );
+	options.to = {
+		height: original.height * factor.y,
+		width: original.width * factor.x,
+		outerHeight: original.outerHeight * factor.y,
+		outerWidth: original.outerWidth * factor.x
+	};
+
+	// Fade option to support puff
+	if ( options.fade ) {
+		if ( mode === "show" ) {
+			options.from.opacity = 0;
+			options.to.opacity = 1;
+		}
+		if ( mode === "hide" ) {
+			options.from.opacity = 1;
+			options.to.opacity = 0;
+		}
+	}
+
+	// Animate
+	el.effect( options );
+
+};
+
+
+/*!
+ * jQuery UI Effects Puff 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/puff-effect/
+ */
+
+
+var effectPuff = $.effects.effect.puff = function( o, done ) {
+	var elem = $( this ),
+		mode = $.effects.setMode( elem, o.mode || "hide" ),
+		hide = mode === "hide",
+		percent = parseInt( o.percent, 10 ) || 150,
+		factor = percent / 100,
+		original = {
+			height: elem.height(),
+			width: elem.width(),
+			outerHeight: elem.outerHeight(),
+			outerWidth: elem.outerWidth()
+		};
+
+	$.extend( o, {
+		effect: "scale",
+		queue: false,
+		fade: true,
+		mode: mode,
+		complete: done,
+		percent: hide ? percent : 100,
+		from: hide ?
+			original :
+			{
+				height: original.height * factor,
+				width: original.width * factor,
+				outerHeight: original.outerHeight * factor,
+				outerWidth: original.outerWidth * factor
+			}
+	});
+
+	elem.effect( o );
+};
+
+
+/*!
+ * jQuery UI Effects Pulsate 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/pulsate-effect/
+ */
+
+
+var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
+	var elem = $( this ),
+		mode = $.effects.setMode( elem, o.mode || "show" ),
+		show = mode === "show",
+		hide = mode === "hide",
+		showhide = ( show || mode === "hide" ),
+
+		// showing or hiding leaves of the "last" animation
+		anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
+		duration = o.duration / anims,
+		animateTo = 0,
+		queue = elem.queue(),
+		queuelen = queue.length,
+		i;
+
+	if ( show || !elem.is(":visible")) {
+		elem.css( "opacity", 0 ).show();
+		animateTo = 1;
+	}
+
+	// anims - 1 opacity "toggles"
+	for ( i = 1; i < anims; i++ ) {
+		elem.animate({
+			opacity: animateTo
+		}, duration, o.easing );
+		animateTo = 1 - animateTo;
+	}
+
+	elem.animate({
+		opacity: animateTo
+	}, duration, o.easing);
+
+	elem.queue(function() {
+		if ( hide ) {
+			elem.hide();
+		}
+		done();
+	});
+
+	// We just queued up "anims" animations, we need to put them next in the queue
+	if ( queuelen > 1 ) {
+		queue.splice.apply( queue,
+			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
+	}
+	elem.dequeue();
+};
+
+
+/*!
+ * jQuery UI Effects Shake 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/shake-effect/
+ */
+
+
+var effectShake = $.effects.effect.shake = function( o, done ) {
+
+	var el = $( this ),
+		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+		mode = $.effects.setMode( el, o.mode || "effect" ),
+		direction = o.direction || "left",
+		distance = o.distance || 20,
+		times = o.times || 3,
+		anims = times * 2 + 1,
+		speed = Math.round( o.duration / anims ),
+		ref = (direction === "up" || direction === "down") ? "top" : "left",
+		positiveMotion = (direction === "up" || direction === "left"),
+		animation = {},
+		animation1 = {},
+		animation2 = {},
+		i,
+
+		// we will need to re-assemble the queue to stack our animations in place
+		queue = el.queue(),
+		queuelen = queue.length;
+
+	$.effects.save( el, props );
+	el.show();
+	$.effects.createWrapper( el );
+
+	// Animation
+	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
+	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
+	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
+
+	// Animate
+	el.animate( animation, speed, o.easing );
+
+	// Shakes
+	for ( i = 1; i < times; i++ ) {
+		el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
+	}
+	el
+		.animate( animation1, speed, o.easing )
+		.animate( animation, speed / 2, o.easing )
+		.queue(function() {
+			if ( mode === "hide" ) {
+				el.hide();
+			}
+			$.effects.restore( el, props );
+			$.effects.removeWrapper( el );
+			done();
+		});
+
+	// inject all the animations we just queued to be first in line (after "inprogress")
+	if ( queuelen > 1) {
+		queue.splice.apply( queue,
+			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
+	}
+	el.dequeue();
+
+};
+
+
+/*!
+ * jQuery UI Effects Slide 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/slide-effect/
+ */
+
+
+var effectSlide = $.effects.effect.slide = function( o, done ) {
+
+	// Create element
+	var el = $( this ),
+		props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
+		mode = $.effects.setMode( el, o.mode || "show" ),
+		show = mode === "show",
+		direction = o.direction || "left",
+		ref = (direction === "up" || direction === "down") ? "top" : "left",
+		positiveMotion = (direction === "up" || direction === "left"),
+		distance,
+		animation = {};
+
+	// Adjust
+	$.effects.save( el, props );
+	el.show();
+	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
+
+	$.effects.createWrapper( el ).css({
+		overflow: "hidden"
+	});
+
+	if ( show ) {
+		el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
+	}
+
+	// Animation
+	animation[ ref ] = ( show ?
+		( positiveMotion ? "+=" : "-=") :
+		( positiveMotion ? "-=" : "+=")) +
+		distance;
+
+	// Animate
+	el.animate( animation, {
+		queue: false,
+		duration: o.duration,
+		easing: o.easing,
+		complete: function() {
+			if ( mode === "hide" ) {
+				el.hide();
+			}
+			$.effects.restore( el, props );
+			$.effects.removeWrapper( el );
+			done();
+		}
+	});
+};
+
+
+/*!
+ * jQuery UI Effects Transfer 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/transfer-effect/
+ */
+
+
+var effectTransfer = $.effects.effect.transfer = function( o, done ) {
+	var elem = $( this ),
+		target = $( o.to ),
+		targetFixed = target.css( "position" ) === "fixed",
+		body = $("body"),
+		fixTop = targetFixed ? body.scrollTop() : 0,
+		fixLeft = targetFixed ? body.scrollLeft() : 0,
+		endPosition = target.offset(),
+		animation = {
+			top: endPosition.top - fixTop,
+			left: endPosition.left - fixLeft,
+			height: target.innerHeight(),
+			width: target.innerWidth()
+		},
+		startPosition = elem.offset(),
+		transfer = $( "<div class='ui-effects-transfer'></div>" )
+			.appendTo( document.body )
+			.addClass( o.className )
+			.css({
+				top: startPosition.top - fixTop,
+				left: startPosition.left - fixLeft,
+				height: elem.innerHeight(),
+				width: elem.innerWidth(),
+				position: targetFixed ? "fixed" : "absolute"
+			})
+			.animate( animation, o.duration, o.easing, function() {
+				transfer.remove();
+				done();
+			});
+};
+
+
+/*!
+ * jQuery UI Progressbar 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/progressbar/
+ */
+
+
+var progressbar = $.widget( "ui.progressbar", {
+	version: "1.11.4",
+	options: {
+		max: 100,
+		value: 0,
+
+		change: null,
+		complete: null
+	},
+
+	min: 0,
+
+	_create: function() {
+		// Constrain initial value
+		this.oldValue = this.options.value = this._constrainedValue();
+
+		this.element
+			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+			.attr({
+				// Only set static values, aria-valuenow and aria-valuemax are
+				// set inside _refreshValue()
+				role: "progressbar",
+				"aria-valuemin": this.min
+			});
+
+		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
+			.appendTo( this.element );
+
+		this._refreshValue();
+	},
+
+	_destroy: function() {
+		this.element
+			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+			.removeAttr( "role" )
+			.removeAttr( "aria-valuemin" )
+			.removeAttr( "aria-valuemax" )
+			.removeAttr( "aria-valuenow" );
+
+		this.valueDiv.remove();
+	},
+
+	value: function( newValue ) {
+		if ( newValue === undefined ) {
+			return this.options.value;
+		}
+
+		this.options.value = this._constrainedValue( newValue );
+		this._refreshValue();
+	},
+
+	_constrainedValue: function( newValue ) {
+		if ( newValue === undefined ) {
+			newValue = this.options.value;
+		}
+
+		this.indeterminate = newValue === false;
+
+		// sanitize value
+		if ( typeof newValue !== "number" ) {
+			newValue = 0;
+		}
+
+		return this.indeterminate ? false :
+			Math.min( this.options.max, Math.max( this.min, newValue ) );
+	},
+
+	_setOptions: function( options ) {
+		// Ensure "value" option is set after other values (like max)
+		var value = options.value;
+		delete options.value;
+
+		this._super( options );
+
+		this.options.value = this._constrainedValue( value );
+		this._refreshValue();
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "max" ) {
+			// Don't allow a max less than min
+			value = Math.max( this.min, value );
+		}
+		if ( key === "disabled" ) {
+			this.element
+				.toggleClass( "ui-state-disabled", !!value )
+				.attr( "aria-disabled", value );
+		}
+		this._super( key, value );
+	},
+
+	_percentage: function() {
+		return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
+	},
+
+	_refreshValue: function() {
+		var value = this.options.value,
+			percentage = this._percentage();
+
+		this.valueDiv
+			.toggle( this.indeterminate || value > this.min )
+			.toggleClass( "ui-corner-right", value === this.options.max )
+			.width( percentage.toFixed(0) + "%" );
+
+		this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
+
+		if ( this.indeterminate ) {
+			this.element.removeAttr( "aria-valuenow" );
+			if ( !this.overlayDiv ) {
+				this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
+			}
+		} else {
+			this.element.attr({
+				"aria-valuemax": this.options.max,
+				"aria-valuenow": value
+			});
+			if ( this.overlayDiv ) {
+				this.overlayDiv.remove();
+				this.overlayDiv = null;
+			}
+		}
+
+		if ( this.oldValue !== value ) {
+			this.oldValue = value;
+			this._trigger( "change" );
+		}
+		if ( value === this.options.max ) {
+			this._trigger( "complete" );
+		}
+	}
+});
+
+
+/*!
+ * jQuery UI Selectable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/selectable/
+ */
+
+
+var selectable = $.widget("ui.selectable", $.ui.mouse, {
+	version: "1.11.4",
+	options: {
+		appendTo: "body",
+		autoRefresh: true,
+		distance: 0,
+		filter: "*",
+		tolerance: "touch",
+
+		// callbacks
+		selected: null,
+		selecting: null,
+		start: null,
+		stop: null,
+		unselected: null,
+		unselecting: null
+	},
+	_create: function() {
+		var selectees,
+			that = this;
+
+		this.element.addClass("ui-selectable");
+
+		this.dragged = false;
+
+		// cache selectee children based on filter
+		this.refresh = function() {
+			selectees = $(that.options.filter, that.element[0]);
+			selectees.addClass("ui-selectee");
+			selectees.each(function() {
+				var $this = $(this),
+					pos = $this.offset();
+				$.data(this, "selectable-item", {
+					element: this,
+					$element: $this,
+					left: pos.left,
+					top: pos.top,
+					right: pos.left + $this.outerWidth(),
+					bottom: pos.top + $this.outerHeight(),
+					startselected: false,
+					selected: $this.hasClass("ui-selected"),
+					selecting: $this.hasClass("ui-selecting"),
+					unselecting: $this.hasClass("ui-unselecting")
+				});
+			});
+		};
+		this.refresh();
+
+		this.selectees = selectees.addClass("ui-selectee");
+
+		this._mouseInit();
+
+		this.helper = $("<div class='ui-selectable-helper'></div>");
+	},
+
+	_destroy: function() {
+		this.selectees
+			.removeClass("ui-selectee")
+			.removeData("selectable-item");
+		this.element
+			.removeClass("ui-selectable ui-selectable-disabled");
+		this._mouseDestroy();
+	},
+
+	_mouseStart: function(event) {
+		var that = this,
+			options = this.options;
+
+		this.opos = [ event.pageX, event.pageY ];
+
+		if (this.options.disabled) {
+			return;
+		}
+
+		this.selectees = $(options.filter, this.element[0]);
+
+		this._trigger("start", event);
+
+		$(options.appendTo).append(this.helper);
+		// position helper (lasso)
+		this.helper.css({
+			"left": event.pageX,
+			"top": event.pageY,
+			"width": 0,
+			"height": 0
+		});
+
+		if (options.autoRefresh) {
+			this.refresh();
+		}
+
+		this.selectees.filter(".ui-selected").each(function() {
+			var selectee = $.data(this, "selectable-item");
+			selectee.startselected = true;
+			if (!event.metaKey && !event.ctrlKey) {
+				selectee.$element.removeClass("ui-selected");
+				selectee.selected = false;
+				selectee.$element.addClass("ui-unselecting");
+				selectee.unselecting = true;
+				// selectable UNSELECTING callback
+				that._trigger("unselecting", event, {
+					unselecting: selectee.element
+				});
+			}
+		});
+
+		$(event.target).parents().addBack().each(function() {
+			var doSelect,
+				selectee = $.data(this, "selectable-item");
+			if (selectee) {
+				doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
+				selectee.$element
+					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
+					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
+				selectee.unselecting = !doSelect;
+				selectee.selecting = doSelect;
+				selectee.selected = doSelect;
+				// selectable (UN)SELECTING callback
+				if (doSelect) {
+					that._trigger("selecting", event, {
+						selecting: selectee.element
+					});
+				} else {
+					that._trigger("unselecting", event, {
+						unselecting: selectee.element
+					});
+				}
+				return false;
+			}
+		});
+
+	},
+
+	_mouseDrag: function(event) {
+
+		this.dragged = true;
+
+		if (this.options.disabled) {
+			return;
+		}
+
+		var tmp,
+			that = this,
+			options = this.options,
+			x1 = this.opos[0],
+			y1 = this.opos[1],
+			x2 = event.pageX,
+			y2 = event.pageY;
+
+		if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
+		if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
+		this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
+
+		this.selectees.each(function() {
+			var selectee = $.data(this, "selectable-item"),
+				hit = false;
+
+			//prevent helper from being selected if appendTo: selectable
+			if (!selectee || selectee.element === that.element[0]) {
+				return;
+			}
+
+			if (options.tolerance === "touch") {
+				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
+			} else if (options.tolerance === "fit") {
+				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
+			}
+
+			if (hit) {
+				// SELECT
+				if (selectee.selected) {
+					selectee.$element.removeClass("ui-selected");
+					selectee.selected = false;
+				}
+				if (selectee.unselecting) {
+					selectee.$element.removeClass("ui-unselecting");
+					selectee.unselecting = false;
+				}
+				if (!selectee.selecting) {
+					selectee.$element.addClass("ui-selecting");
+					selectee.selecting = true;
+					// selectable SELECTING callback
+					that._trigger("selecting", event, {
+						selecting: selectee.element
+					});
+				}
+			} else {
+				// UNSELECT
+				if (selectee.selecting) {
+					if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
+						selectee.$element.removeClass("ui-selecting");
+						selectee.selecting = false;
+						selectee.$element.addClass("ui-selected");
+						selectee.selected = true;
+					} else {
+						selectee.$element.removeClass("ui-selecting");
+						selectee.selecting = false;
+						if (selectee.startselected) {
+							selectee.$element.addClass("ui-unselecting");
+							selectee.unselecting = true;
+						}
+						// selectable UNSELECTING callback
+						that._trigger("unselecting", event, {
+							unselecting: selectee.element
+						});
+					}
+				}
+				if (selectee.selected) {
+					if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
+						selectee.$element.removeClass("ui-selected");
+						selectee.selected = false;
+
+						selectee.$element.addClass("ui-unselecting");
+						selectee.unselecting = true;
+						// selectable UNSELECTING callback
+						that._trigger("unselecting", event, {
+							unselecting: selectee.element
+						});
+					}
+				}
+			}
+		});
+
+		return false;
+	},
+
+	_mouseStop: function(event) {
+		var that = this;
+
+		this.dragged = false;
+
+		$(".ui-unselecting", this.element[0]).each(function() {
+			var selectee = $.data(this, "selectable-item");
+			selectee.$element.removeClass("ui-unselecting");
+			selectee.unselecting = false;
+			selectee.startselected = false;
+			that._trigger("unselected", event, {
+				unselected: selectee.element
+			});
+		});
+		$(".ui-selecting", this.element[0]).each(function() {
+			var selectee = $.data(this, "selectable-item");
+			selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
+			selectee.selecting = false;
+			selectee.selected = true;
+			selectee.startselected = true;
+			that._trigger("selected", event, {
+				selected: selectee.element
+			});
+		});
+		this._trigger("stop", event);
+
+		this.helper.remove();
+
+		return false;
+	}
+
+});
+
+
+/*!
+ * jQuery UI Selectmenu 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/selectmenu
+ */
+
+
+var selectmenu = $.widget( "ui.selectmenu", {
+	version: "1.11.4",
+	defaultElement: "<select>",
+	options: {
+		appendTo: null,
+		disabled: null,
+		icons: {
+			button: "ui-icon-triangle-1-s"
+		},
+		position: {
+			my: "left top",
+			at: "left bottom",
+			collision: "none"
+		},
+		width: null,
+
+		// callbacks
+		change: null,
+		close: null,
+		focus: null,
+		open: null,
+		select: null
+	},
+
+	_create: function() {
+		var selectmenuId = this.element.uniqueId().attr( "id" );
+		this.ids = {
+			element: selectmenuId,
+			button: selectmenuId + "-button",
+			menu: selectmenuId + "-menu"
+		};
+
+		this._drawButton();
+		this._drawMenu();
+
+		if ( this.options.disabled ) {
+			this.disable();
+		}
+	},
+
+	_drawButton: function() {
+		var that = this;
+
+		// Associate existing label with the new button
+		this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
+		this._on( this.label, {
+			click: function( event ) {
+				this.button.focus();
+				event.preventDefault();
+			}
+		});
+
+		// Hide original select element
+		this.element.hide();
+
+		// Create button
+		this.button = $( "<span>", {
+			"class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
+			tabindex: this.options.disabled ? -1 : 0,
+			id: this.ids.button,
+			role: "combobox",
+			"aria-expanded": "false",
+			"aria-autocomplete": "list",
+			"aria-owns": this.ids.menu,
+			"aria-haspopup": "true"
+		})
+			.insertAfter( this.element );
+
+		$( "<span>", {
+			"class": "ui-icon " + this.options.icons.button
+		})
+			.prependTo( this.button );
+
+		this.buttonText = $( "<span>", {
+			"class": "ui-selectmenu-text"
+		})
+			.appendTo( this.button );
+
+		this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
+		this._resizeButton();
+
+		this._on( this.button, this._buttonEvents );
+		this.button.one( "focusin", function() {
+
+			// Delay rendering the menu items until the button receives focus.
+			// The menu may have already been rendered via a programmatic open.
+			if ( !that.menuItems ) {
+				that._refreshMenu();
+			}
+		});
+		this._hoverable( this.button );
+		this._focusable( this.button );
+	},
+
+	_drawMenu: function() {
+		var that = this;
+
+		// Create menu
+		this.menu = $( "<ul>", {
+			"aria-hidden": "true",
+			"aria-labelledby": this.ids.button,
+			id: this.ids.menu
+		});
+
+		// Wrap menu
+		this.menuWrap = $( "<div>", {
+			"class": "ui-selectmenu-menu ui-front"
+		})
+			.append( this.menu )
+			.appendTo( this._appendTo() );
+
+		// Initialize menu widget
+		this.menuInstance = this.menu
+			.menu({
+				role: "listbox",
+				select: function( event, ui ) {
+					event.preventDefault();
+
+					// support: IE8
+					// If the item was selected via a click, the text selection
+					// will be destroyed in IE
+					that._setSelection();
+
+					that._select( ui.item.data( "ui-selectmenu-item" ), event );
+				},
+				focus: function( event, ui ) {
+					var item = ui.item.data( "ui-selectmenu-item" );
+
+					// Prevent inital focus from firing and check if its a newly focused item
+					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
+						that._trigger( "focus", event, { item: item } );
+						if ( !that.isOpen ) {
+							that._select( item, event );
+						}
+					}
+					that.focusIndex = item.index;
+
+					that.button.attr( "aria-activedescendant",
+						that.menuItems.eq( item.index ).attr( "id" ) );
+				}
+			})
+			.menu( "instance" );
+
+		// Adjust menu styles to dropdown
+		this.menu
+			.addClass( "ui-corner-bottom" )
+			.removeClass( "ui-corner-all" );
+
+		// Don't close the menu on mouseleave
+		this.menuInstance._off( this.menu, "mouseleave" );
+
+		// Cancel the menu's collapseAll on document click
+		this.menuInstance._closeOnDocumentClick = function() {
+			return false;
+		};
+
+		// Selects often contain empty items, but never contain dividers
+		this.menuInstance._isDivider = function() {
+			return false;
+		};
+	},
+
+	refresh: function() {
+		this._refreshMenu();
+		this._setText( this.buttonText, this._getSelectedItem().text() );
+		if ( !this.options.width ) {
+			this._resizeButton();
+		}
+	},
+
+	_refreshMenu: function() {
+		this.menu.empty();
+
+		var item,
+			options = this.element.find( "option" );
+
+		if ( !options.length ) {
+			return;
+		}
+
+		this._parseOptions( options );
+		this._renderMenu( this.menu, this.items );
+
+		this.menuInstance.refresh();
+		this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
+
+		item = this._getSelectedItem();
+
+		// Update the menu to have the correct item focused
+		this.menuInstance.focus( null, item );
+		this._setAria( item.data( "ui-selectmenu-item" ) );
+
+		// Set disabled state
+		this._setOption( "disabled", this.element.prop( "disabled" ) );
+	},
+
+	open: function( event ) {
+		if ( this.options.disabled ) {
+			return;
+		}
+
+		// If this is the first time the menu is being opened, render the items
+		if ( !this.menuItems ) {
+			this._refreshMenu();
+		} else {
+
+			// Menu clears focus on close, reset focus to selected item
+			this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
+			this.menuInstance.focus( null, this._getSelectedItem() );
+		}
+
+		this.isOpen = true;
+		this._toggleAttr();
+		this._resizeMenu();
+		this._position();
+
+		this._on( this.document, this._documentClick );
+
+		this._trigger( "open", event );
+	},
+
+	_position: function() {
+		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
+	},
+
+	close: function( event ) {
+		if ( !this.isOpen ) {
+			return;
+		}
+
+		this.isOpen = false;
+		this._toggleAttr();
+
+		this.range = null;
+		this._off( this.document );
+
+		this._trigger( "close", event );
+	},
+
+	widget: function() {
+		return this.button;
+	},
+
+	menuWidget: function() {
+		return this.menu;
+	},
+
+	_renderMenu: function( ul, items ) {
+		var that = this,
+			currentOptgroup = "";
+
+		$.each( items, function( index, item ) {
+			if ( item.optgroup !== currentOptgroup ) {
+				$( "<li>", {
+					"class": "ui-selectmenu-optgroup ui-menu-divider" +
+						( item.element.parent( "optgroup" ).prop( "disabled" ) ?
+							" ui-state-disabled" :
+							"" ),
+					text: item.optgroup
+				})
+					.appendTo( ul );
+
+				currentOptgroup = item.optgroup;
+			}
+
+			that._renderItemData( ul, item );
+		});
+	},
+
+	_renderItemData: function( ul, item ) {
+		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
+	},
+
+	_renderItem: function( ul, item ) {
+		var li = $( "<li>" );
+
+		if ( item.disabled ) {
+			li.addClass( "ui-state-disabled" );
+		}
+		this._setText( li, item.label );
+
+		return li.appendTo( ul );
+	},
+
+	_setText: function( element, value ) {
+		if ( value ) {
+			element.text( value );
+		} else {
+			element.html( "&#160;" );
+		}
+	},
+
+	_move: function( direction, event ) {
+		var item, next,
+			filter = ".ui-menu-item";
+
+		if ( this.isOpen ) {
+			item = this.menuItems.eq( this.focusIndex );
+		} else {
+			item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
+			filter += ":not(.ui-state-disabled)";
+		}
+
+		if ( direction === "first" || direction === "last" ) {
+			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
+		} else {
+			next = item[ direction + "All" ]( filter ).eq( 0 );
+		}
+
+		if ( next.length ) {
+			this.menuInstance.focus( event, next );
+		}
+	},
+
+	_getSelectedItem: function() {
+		return this.menuItems.eq( this.element[ 0 ].selectedIndex );
+	},
+
+	_toggle: function( event ) {
+		this[ this.isOpen ? "close" : "open" ]( event );
+	},
+
+	_setSelection: function() {
+		var selection;
+
+		if ( !this.range ) {
+			return;
+		}
+
+		if ( window.getSelection ) {
+			selection = window.getSelection();
+			selection.removeAllRanges();
+			selection.addRange( this.range );
+
+		// support: IE8
+		} else {
+			this.range.select();
+		}
+
+		// support: IE
+		// Setting the text selection kills the button focus in IE, but
+		// restoring the focus doesn't kill the selection.
+		this.button.focus();
+	},
+
+	_documentClick: {
+		mousedown: function( event ) {
+			if ( !this.isOpen ) {
+				return;
+			}
+
+			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
+				this.close( event );
+			}
+		}
+	},
+
+	_buttonEvents: {
+
+		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
+		mousedown: function() {
+			var selection;
+
+			if ( window.getSelection ) {
+				selection = window.getSelection();
+				if ( selection.rangeCount ) {
+					this.range = selection.getRangeAt( 0 );
+				}
+
+			// support: IE8
+			} else {
+				this.range = document.selection.createRange();
+			}
+		},
+
+		click: function( event ) {
+			this._setSelection();
+			this._toggle( event );
+		},
+
+		keydown: function( event ) {
+			var preventDefault = true;
+			switch ( event.keyCode ) {
+				case $.ui.keyCode.TAB:
+				case $.ui.keyCode.ESCAPE:
+					this.close( event );
+					preventDefault = false;
+					break;
+				case $.ui.keyCode.ENTER:
+					if ( this.isOpen ) {
+						this._selectFocusedItem( event );
+					}
+					break;
+				case $.ui.keyCode.UP:
+					if ( event.altKey ) {
+						this._toggle( event );
+					} else {
+						this._move( "prev", event );
+					}
+					break;
+				case $.ui.keyCode.DOWN:
+					if ( event.altKey ) {
+						this._toggle( event );
+					} else {
+						this._move( "next", event );
+					}
+					break;
+				case $.ui.keyCode.SPACE:
+					if ( this.isOpen ) {
+						this._selectFocusedItem( event );
+					} else {
+						this._toggle( event );
+					}
+					break;
+				case $.ui.keyCode.LEFT:
+					this._move( "prev", event );
+					break;
+				case $.ui.keyCode.RIGHT:
+					this._move( "next", event );
+					break;
+				case $.ui.keyCode.HOME:
+				case $.ui.keyCode.PAGE_UP:
+					this._move( "first", event );
+					break;
+				case $.ui.keyCode.END:
+				case $.ui.keyCode.PAGE_DOWN:
+					this._move( "last", event );
+					break;
+				default:
+					this.menu.trigger( event );
+					preventDefault = false;
+			}
+
+			if ( preventDefault ) {
+				event.preventDefault();
+			}
+		}
+	},
+
+	_selectFocusedItem: function( event ) {
+		var item = this.menuItems.eq( this.focusIndex );
+		if ( !item.hasClass( "ui-state-disabled" ) ) {
+			this._select( item.data( "ui-selectmenu-item" ), event );
+		}
+	},
+
+	_select: function( item, event ) {
+		var oldIndex = this.element[ 0 ].selectedIndex;
+
+		// Change native select element
+		this.element[ 0 ].selectedIndex = item.index;
+		this._setText( this.buttonText, item.label );
+		this._setAria( item );
+		this._trigger( "select", event, { item: item } );
+
+		if ( item.index !== oldIndex ) {
+			this._trigger( "change", event, { item: item } );
+		}
+
+		this.close( event );
+	},
+
+	_setAria: function( item ) {
+		var id = this.menuItems.eq( item.index ).attr( "id" );
+
+		this.button.attr({
+			"aria-labelledby": id,
+			"aria-activedescendant": id
+		});
+		this.menu.attr( "aria-activedescendant", id );
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "icons" ) {
+			this.button.find( "span.ui-icon" )
+				.removeClass( this.options.icons.button )
+				.addClass( value.button );
+		}
+
+		this._super( key, value );
+
+		if ( key === "appendTo" ) {
+			this.menuWrap.appendTo( this._appendTo() );
+		}
+
+		if ( key === "disabled" ) {
+			this.menuInstance.option( "disabled", value );
+			this.button
+				.toggleClass( "ui-state-disabled", value )
+				.attr( "aria-disabled", value );
+
+			this.element.prop( "disabled", value );
+			if ( value ) {
+				this.button.attr( "tabindex", -1 );
+				this.close();
+			} else {
+				this.button.attr( "tabindex", 0 );
+			}
+		}
+
+		if ( key === "width" ) {
+			this._resizeButton();
+		}
+	},
+
+	_appendTo: function() {
+		var element = this.options.appendTo;
+
+		if ( element ) {
+			element = element.jquery || element.nodeType ?
+				$( element ) :
+				this.document.find( element ).eq( 0 );
+		}
+
+		if ( !element || !element[ 0 ] ) {
+			element = this.element.closest( ".ui-front" );
+		}
+
+		if ( !element.length ) {
+			element = this.document[ 0 ].body;
+		}
+
+		return element;
+	},
+
+	_toggleAttr: function() {
+		this.button
+			.toggleClass( "ui-corner-top", this.isOpen )
+			.toggleClass( "ui-corner-all", !this.isOpen )
+			.attr( "aria-expanded", this.isOpen );
+		this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
+		this.menu.attr( "aria-hidden", !this.isOpen );
+	},
+
+	_resizeButton: function() {
+		var width = this.options.width;
+
+		if ( !width ) {
+			width = this.element.show().outerWidth();
+			this.element.hide();
+		}
+
+		this.button.outerWidth( width );
+	},
+
+	_resizeMenu: function() {
+		this.menu.outerWidth( Math.max(
+			this.button.outerWidth(),
+
+			// support: IE10
+			// IE10 wraps long text (possibly a rounding bug)
+			// so we add 1px to avoid the wrapping
+			this.menu.width( "" ).outerWidth() + 1
+		) );
+	},
+
+	_getCreateOptions: function() {
+		return { disabled: this.element.prop( "disabled" ) };
+	},
+
+	_parseOptions: function( options ) {
+		var data = [];
+		options.each(function( index, item ) {
+			var option = $( item ),
+				optgroup = option.parent( "optgroup" );
+			data.push({
+				element: option,
+				index: index,
+				value: option.val(),
+				label: option.text(),
+				optgroup: optgroup.attr( "label" ) || "",
+				disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
+			});
+		});
+		this.items = data;
+	},
+
+	_destroy: function() {
+		this.menuWrap.remove();
+		this.button.remove();
+		this.element.show();
+		this.element.removeUniqueId();
+		this.label.attr( "for", this.ids.element );
+	}
+});
+
+
+/*!
+ * jQuery UI Slider 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/slider/
+ */
+
+
+var slider = $.widget( "ui.slider", $.ui.mouse, {
+	version: "1.11.4",
+	widgetEventPrefix: "slide",
+
+	options: {
+		animate: false,
+		distance: 0,
+		max: 100,
+		min: 0,
+		orientation: "horizontal",
+		range: false,
+		step: 1,
+		value: 0,
+		values: null,
+
+		// callbacks
+		change: null,
+		slide: null,
+		start: null,
+		stop: null
+	},
+
+	// number of pages in a slider
+	// (how many times can you page up/down to go through the whole range)
+	numPages: 5,
+
+	_create: function() {
+		this._keySliding = false;
+		this._mouseSliding = false;
+		this._animateOff = true;
+		this._handleIndex = null;
+		this._detectOrientation();
+		this._mouseInit();
+		this._calculateNewMax();
+
+		this.element
+			.addClass( "ui-slider" +
+				" ui-slider-" + this.orientation +
+				" ui-widget" +
+				" ui-widget-content" +
+				" ui-corner-all");
+
+		this._refresh();
+		this._setOption( "disabled", this.options.disabled );
+
+		this._animateOff = false;
+	},
+
+	_refresh: function() {
+		this._createRange();
+		this._createHandles();
+		this._setupEvents();
+		this._refreshValue();
+	},
+
+	_createHandles: function() {
+		var i, handleCount,
+			options = this.options,
+			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
+			handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",
+			handles = [];
+
+		handleCount = ( options.values && options.values.length ) || 1;
+
+		if ( existingHandles.length > handleCount ) {
+			existingHandles.slice( handleCount ).remove();
+			existingHandles = existingHandles.slice( 0, handleCount );
+		}
+
+		for ( i = existingHandles.length; i < handleCount; i++ ) {
+			handles.push( handle );
+		}
+
+		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
+
+		this.handle = this.handles.eq( 0 );
+
+		this.handles.each(function( i ) {
+			$( this ).data( "ui-slider-handle-index", i );
+		});
+	},
+
+	_createRange: function() {
+		var options = this.options,
+			classes = "";
+
+		if ( options.range ) {
+			if ( options.range === true ) {
+				if ( !options.values ) {
+					options.values = [ this._valueMin(), this._valueMin() ];
+				} else if ( options.values.length && options.values.length !== 2 ) {
+					options.values = [ options.values[0], options.values[0] ];
+				} else if ( $.isArray( options.values ) ) {
+					options.values = options.values.slice(0);
+				}
+			}
+
+			if ( !this.range || !this.range.length ) {
+				this.range = $( "<div></div>" )
+					.appendTo( this.element );
+
+				classes = "ui-slider-range" +
+				// note: this isn't the most fittingly semantic framework class for this element,
+				// but worked best visually with a variety of themes
+				" ui-widget-header ui-corner-all";
+			} else {
+				this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
+					// Handle range switching from true to min/max
+					.css({
+						"left": "",
+						"bottom": ""
+					});
+			}
+
+			this.range.addClass( classes +
+				( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
+		} else {
+			if ( this.range ) {
+				this.range.remove();
+			}
+			this.range = null;
+		}
+	},
+
+	_setupEvents: function() {
+		this._off( this.handles );
+		this._on( this.handles, this._handleEvents );
+		this._hoverable( this.handles );
+		this._focusable( this.handles );
+	},
+
+	_destroy: function() {
+		this.handles.remove();
+		if ( this.range ) {
+			this.range.remove();
+		}
+
+		this.element
+			.removeClass( "ui-slider" +
+				" ui-slider-horizontal" +
+				" ui-slider-vertical" +
+				" ui-widget" +
+				" ui-widget-content" +
+				" ui-corner-all" );
+
+		this._mouseDestroy();
+	},
+
+	_mouseCapture: function( event ) {
+		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
+			that = this,
+			o = this.options;
+
+		if ( o.disabled ) {
+			return false;
+		}
+
+		this.elementSize = {
+			width: this.element.outerWidth(),
+			height: this.element.outerHeight()
+		};
+		this.elementOffset = this.element.offset();
+
+		position = { x: event.pageX, y: event.pageY };
+		normValue = this._normValueFromMouse( position );
+		distance = this._valueMax() - this._valueMin() + 1;
+		this.handles.each(function( i ) {
+			var thisDistance = Math.abs( normValue - that.values(i) );
+			if (( distance > thisDistance ) ||
+				( distance === thisDistance &&
+					(i === that._lastChangedValue || that.values(i) === o.min ))) {
+				distance = thisDistance;
+				closestHandle = $( this );
+				index = i;
+			}
+		});
+
+		allowed = this._start( event, index );
+		if ( allowed === false ) {
+			return false;
+		}
+		this._mouseSliding = true;
+
+		this._handleIndex = index;
+
+		closestHandle
+			.addClass( "ui-state-active" )
+			.focus();
+
+		offset = closestHandle.offset();
+		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
+		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
+			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
+			top: event.pageY - offset.top -
+				( closestHandle.height() / 2 ) -
+				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
+				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
+				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
+		};
+
+		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
+			this._slide( event, index, normValue );
+		}
+		this._animateOff = true;
+		return true;
+	},
+
+	_mouseStart: function() {
+		return true;
+	},
+
+	_mouseDrag: function( event ) {
+		var position = { x: event.pageX, y: event.pageY },
+			normValue = this._normValueFromMouse( position );
+
+		this._slide( event, this._handleIndex, normValue );
+
+		return false;
+	},
+
+	_mouseStop: function( event ) {
+		this.handles.removeClass( "ui-state-active" );
+		this._mouseSliding = false;
+
+		this._stop( event, this._handleIndex );
+		this._change( event, this._handleIndex );
+
+		this._handleIndex = null;
+		this._clickOffset = null;
+		this._animateOff = false;
+
+		return false;
+	},
+
+	_detectOrientation: function() {
+		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
+	},
+
+	_normValueFromMouse: function( position ) {
+		var pixelTotal,
+			pixelMouse,
+			percentMouse,
+			valueTotal,
+			valueMouse;
+
+		if ( this.orientation === "horizontal" ) {
+			pixelTotal = this.elementSize.width;
+			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
+		} else {
+			pixelTotal = this.elementSize.height;
+			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
+		}
+
+		percentMouse = ( pixelMouse / pixelTotal );
+		if ( percentMouse > 1 ) {
+			percentMouse = 1;
+		}
+		if ( percentMouse < 0 ) {
+			percentMouse = 0;
+		}
+		if ( this.orientation === "vertical" ) {
+			percentMouse = 1 - percentMouse;
+		}
+
+		valueTotal = this._valueMax() - this._valueMin();
+		valueMouse = this._valueMin() + percentMouse * valueTotal;
+
+		return this._trimAlignValue( valueMouse );
+	},
+
+	_start: function( event, index ) {
+		var uiHash = {
+			handle: this.handles[ index ],
+			value: this.value()
+		};
+		if ( this.options.values && this.options.values.length ) {
+			uiHash.value = this.values( index );
+			uiHash.values = this.values();
+		}
+		return this._trigger( "start", event, uiHash );
+	},
+
+	_slide: function( event, index, newVal ) {
+		var otherVal,
+			newValues,
+			allowed;
+
+		if ( this.options.values && this.options.values.length ) {
+			otherVal = this.values( index ? 0 : 1 );
+
+			if ( ( this.options.values.length === 2 && this.options.range === true ) &&
+					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
+				) {
+				newVal = otherVal;
+			}
+
+			if ( newVal !== this.values( index ) ) {
+				newValues = this.values();
+				newValues[ index ] = newVal;
+				// A slide can be canceled by returning false from the slide callback
+				allowed = this._trigger( "slide", event, {
+					handle: this.handles[ index ],
+					value: newVal,
+					values: newValues
+				} );
+				otherVal = this.values( index ? 0 : 1 );
+				if ( allowed !== false ) {
+					this.values( index, newVal );
+				}
+			}
+		} else {
+			if ( newVal !== this.value() ) {
+				// A slide can be canceled by returning false from the slide callback
+				allowed = this._trigger( "slide", event, {
+					handle: this.handles[ index ],
+					value: newVal
+				} );
+				if ( allowed !== false ) {
+					this.value( newVal );
+				}
+			}
+		}
+	},
+
+	_stop: function( event, index ) {
+		var uiHash = {
+			handle: this.handles[ index ],
+			value: this.value()
+		};
+		if ( this.options.values && this.options.values.length ) {
+			uiHash.value = this.values( index );
+			uiHash.values = this.values();
+		}
+
+		this._trigger( "stop", event, uiHash );
+	},
+
+	_change: function( event, index ) {
+		if ( !this._keySliding && !this._mouseSliding ) {
+			var uiHash = {
+				handle: this.handles[ index ],
+				value: this.value()
+			};
+			if ( this.options.values && this.options.values.length ) {
+				uiHash.value = this.values( index );
+				uiHash.values = this.values();
+			}
+
+			//store the last changed value index for reference when handles overlap
+			this._lastChangedValue = index;
+
+			this._trigger( "change", event, uiHash );
+		}
+	},
+
+	value: function( newValue ) {
+		if ( arguments.length ) {
+			this.options.value = this._trimAlignValue( newValue );
+			this._refreshValue();
+			this._change( null, 0 );
+			return;
+		}
+
+		return this._value();
+	},
+
+	values: function( index, newValue ) {
+		var vals,
+			newValues,
+			i;
+
+		if ( arguments.length > 1 ) {
+			this.options.values[ index ] = this._trimAlignValue( newValue );
+			this._refreshValue();
+			this._change( null, index );
+			return;
+		}
+
+		if ( arguments.length ) {
+			if ( $.isArray( arguments[ 0 ] ) ) {
+				vals = this.options.values;
+				newValues = arguments[ 0 ];
+				for ( i = 0; i < vals.length; i += 1 ) {
+					vals[ i ] = this._trimAlignValue( newValues[ i ] );
+					this._change( null, i );
+				}
+				this._refreshValue();
+			} else {
+				if ( this.options.values && this.options.values.length ) {
+					return this._values( index );
+				} else {
+					return this.value();
+				}
+			}
+		} else {
+			return this._values();
+		}
+	},
+
+	_setOption: function( key, value ) {
+		var i,
+			valsLength = 0;
+
+		if ( key === "range" && this.options.range === true ) {
+			if ( value === "min" ) {
+				this.options.value = this._values( 0 );
+				this.options.values = null;
+			} else if ( value === "max" ) {
+				this.options.value = this._values( this.options.values.length - 1 );
+				this.options.values = null;
+			}
+		}
+
+		if ( $.isArray( this.options.values ) ) {
+			valsLength = this.options.values.length;
+		}
+
+		if ( key === "disabled" ) {
+			this.element.toggleClass( "ui-state-disabled", !!value );
+		}
+
+		this._super( key, value );
+
+		switch ( key ) {
+			case "orientation":
+				this._detectOrientation();
+				this.element
+					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
+					.addClass( "ui-slider-" + this.orientation );
+				this._refreshValue();
+
+				// Reset positioning from previous orientation
+				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
+				break;
+			case "value":
+				this._animateOff = true;
+				this._refreshValue();
+				this._change( null, 0 );
+				this._animateOff = false;
+				break;
+			case "values":
+				this._animateOff = true;
+				this._refreshValue();
+				for ( i = 0; i < valsLength; i += 1 ) {
+					this._change( null, i );
+				}
+				this._animateOff = false;
+				break;
+			case "step":
+			case "min":
+			case "max":
+				this._animateOff = true;
+				this._calculateNewMax();
+				this._refreshValue();
+				this._animateOff = false;
+				break;
+			case "range":
+				this._animateOff = true;
+				this._refresh();
+				this._animateOff = false;
+				break;
+		}
+	},
+
+	//internal value getter
+	// _value() returns value trimmed by min and max, aligned by step
+	_value: function() {
+		var val = this.options.value;
+		val = this._trimAlignValue( val );
+
+		return val;
+	},
+
+	//internal values getter
+	// _values() returns array of values trimmed by min and max, aligned by step
+	// _values( index ) returns single value trimmed by min and max, aligned by step
+	_values: function( index ) {
+		var val,
+			vals,
+			i;
+
+		if ( arguments.length ) {
+			val = this.options.values[ index ];
+			val = this._trimAlignValue( val );
+
+			return val;
+		} else if ( this.options.values && this.options.values.length ) {
+			// .slice() creates a copy of the array
+			// this copy gets trimmed by min and max and then returned
+			vals = this.options.values.slice();
+			for ( i = 0; i < vals.length; i += 1) {
+				vals[ i ] = this._trimAlignValue( vals[ i ] );
+			}
+
+			return vals;
+		} else {
+			return [];
+		}
+	},
+
+	// returns the step-aligned value that val is closest to, between (inclusive) min and max
+	_trimAlignValue: function( val ) {
+		if ( val <= this._valueMin() ) {
+			return this._valueMin();
+		}
+		if ( val >= this._valueMax() ) {
+			return this._valueMax();
+		}
+		var step = ( this.options.step > 0 ) ? this.options.step : 1,
+			valModStep = (val - this._valueMin()) % step,
+			alignValue = val - valModStep;
+
+		if ( Math.abs(valModStep) * 2 >= step ) {
+			alignValue += ( valModStep > 0 ) ? step : ( -step );
+		}
+
+		// Since JavaScript has problems with large floats, round
+		// the final value to 5 digits after the decimal point (see #4124)
+		return parseFloat( alignValue.toFixed(5) );
+	},
+
+	_calculateNewMax: function() {
+		var max = this.options.max,
+			min = this._valueMin(),
+			step = this.options.step,
+			aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step;
+		max = aboveMin + min;
+		this.max = parseFloat( max.toFixed( this._precision() ) );
+	},
+
+	_precision: function() {
+		var precision = this._precisionOf( this.options.step );
+		if ( this.options.min !== null ) {
+			precision = Math.max( precision, this._precisionOf( this.options.min ) );
+		}
+		return precision;
+	},
+
+	_precisionOf: function( num ) {
+		var str = num.toString(),
+			decimal = str.indexOf( "." );
+		return decimal === -1 ? 0 : str.length - decimal - 1;
+	},
+
+	_valueMin: function() {
+		return this.options.min;
+	},
+
+	_valueMax: function() {
+		return this.max;
+	},
+
+	_refreshValue: function() {
+		var lastValPercent, valPercent, value, valueMin, valueMax,
+			oRange = this.options.range,
+			o = this.options,
+			that = this,
+			animate = ( !this._animateOff ) ? o.animate : false,
+			_set = {};
+
+		if ( this.options.values && this.options.values.length ) {
+			this.handles.each(function( i ) {
+				valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
+				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+				if ( that.options.range === true ) {
+					if ( that.orientation === "horizontal" ) {
+						if ( i === 0 ) {
+							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
+						}
+						if ( i === 1 ) {
+							that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+						}
+					} else {
+						if ( i === 0 ) {
+							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
+						}
+						if ( i === 1 ) {
+							that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+						}
+					}
+				}
+				lastValPercent = valPercent;
+			});
+		} else {
+			value = this.value();
+			valueMin = this._valueMin();
+			valueMax = this._valueMax();
+			valPercent = ( valueMax !== valueMin ) ?
+					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
+					0;
+			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+
+			if ( oRange === "min" && this.orientation === "horizontal" ) {
+				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
+			}
+			if ( oRange === "max" && this.orientation === "horizontal" ) {
+				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+			}
+			if ( oRange === "min" && this.orientation === "vertical" ) {
+				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
+			}
+			if ( oRange === "max" && this.orientation === "vertical" ) {
+				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+			}
+		}
+	},
+
+	_handleEvents: {
+		keydown: function( event ) {
+			var allowed, curVal, newVal, step,
+				index = $( event.target ).data( "ui-slider-handle-index" );
+
+			switch ( event.keyCode ) {
+				case $.ui.keyCode.HOME:
+				case $.ui.keyCode.END:
+				case $.ui.keyCode.PAGE_UP:
+				case $.ui.keyCode.PAGE_DOWN:
+				case $.ui.keyCode.UP:
+				case $.ui.keyCode.RIGHT:
+				case $.ui.keyCode.DOWN:
+				case $.ui.keyCode.LEFT:
+					event.preventDefault();
+					if ( !this._keySliding ) {
+						this._keySliding = true;
+						$( event.target ).addClass( "ui-state-active" );
+						allowed = this._start( event, index );
+						if ( allowed === false ) {
+							return;
+						}
+					}
+					break;
+			}
+
+			step = this.options.step;
+			if ( this.options.values && this.options.values.length ) {
+				curVal = newVal = this.values( index );
+			} else {
+				curVal = newVal = this.value();
+			}
+
+			switch ( event.keyCode ) {
+				case $.ui.keyCode.HOME:
+					newVal = this._valueMin();
+					break;
+				case $.ui.keyCode.END:
+					newVal = this._valueMax();
+					break;
+				case $.ui.keyCode.PAGE_UP:
+					newVal = this._trimAlignValue(
+						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
+					);
+					break;
+				case $.ui.keyCode.PAGE_DOWN:
+					newVal = this._trimAlignValue(
+						curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
+					break;
+				case $.ui.keyCode.UP:
+				case $.ui.keyCode.RIGHT:
+					if ( curVal === this._valueMax() ) {
+						return;
+					}
+					newVal = this._trimAlignValue( curVal + step );
+					break;
+				case $.ui.keyCode.DOWN:
+				case $.ui.keyCode.LEFT:
+					if ( curVal === this._valueMin() ) {
+						return;
+					}
+					newVal = this._trimAlignValue( curVal - step );
+					break;
+			}
+
+			this._slide( event, index, newVal );
+		},
+		keyup: function( event ) {
+			var index = $( event.target ).data( "ui-slider-handle-index" );
+
+			if ( this._keySliding ) {
+				this._keySliding = false;
+				this._stop( event, index );
+				this._change( event, index );
+				$( event.target ).removeClass( "ui-state-active" );
+			}
+		}
+	}
+});
+
+
+/*!
+ * jQuery UI Sortable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/sortable/
+ */
+
+
+var sortable = $.widget("ui.sortable", $.ui.mouse, {
+	version: "1.11.4",
+	widgetEventPrefix: "sort",
+	ready: false,
+	options: {
+		appendTo: "parent",
+		axis: false,
+		connectWith: false,
+		containment: false,
+		cursor: "auto",
+		cursorAt: false,
+		dropOnEmpty: true,
+		forcePlaceholderSize: false,
+		forceHelperSize: false,
+		grid: false,
+		handle: false,
+		helper: "original",
+		items: "> *",
+		opacity: false,
+		placeholder: false,
+		revert: false,
+		scroll: true,
+		scrollSensitivity: 20,
+		scrollSpeed: 20,
+		scope: "default",
+		tolerance: "intersect",
+		zIndex: 1000,
+
+		// callbacks
+		activate: null,
+		beforeStop: null,
+		change: null,
+		deactivate: null,
+		out: null,
+		over: null,
+		receive: null,
+		remove: null,
+		sort: null,
+		start: null,
+		stop: null,
+		update: null
+	},
+
+	_isOverAxis: function( x, reference, size ) {
+		return ( x >= reference ) && ( x < ( reference + size ) );
+	},
+
+	_isFloating: function( item ) {
+		return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
+	},
+
+	_create: function() {
+		this.containerCache = {};
+		this.element.addClass("ui-sortable");
+
+		//Get the items
+		this.refresh();
+
+		//Let's determine the parent's offset
+		this.offset = this.element.offset();
+
+		//Initialize mouse events for interaction
+		this._mouseInit();
+
+		this._setHandleClassName();
+
+		//We're ready to go
+		this.ready = true;
+
+	},
+
+	_setOption: function( key, value ) {
+		this._super( key, value );
+
+		if ( key === "handle" ) {
+			this._setHandleClassName();
+		}
+	},
+
+	_setHandleClassName: function() {
+		this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
+		$.each( this.items, function() {
+			( this.instance.options.handle ?
+				this.item.find( this.instance.options.handle ) : this.item )
+				.addClass( "ui-sortable-handle" );
+		});
+	},
+
+	_destroy: function() {
+		this.element
+			.removeClass( "ui-sortable ui-sortable-disabled" )
+			.find( ".ui-sortable-handle" )
+				.removeClass( "ui-sortable-handle" );
+		this._mouseDestroy();
+
+		for ( var i = this.items.length - 1; i >= 0; i-- ) {
+			this.items[i].item.removeData(this.widgetName + "-item");
+		}
+
+		return this;
+	},
+
+	_mouseCapture: function(event, overrideHandle) {
+		var currentItem = null,
+			validHandle = false,
+			that = this;
+
+		if (this.reverting) {
+			return false;
+		}
+
+		if(this.options.disabled || this.options.type === "static") {
+			return false;
+		}
+
+		//We have to refresh the items data once first
+		this._refreshItems(event);
+
+		//Find out if the clicked node (or one of its parents) is a actual item in this.items
+		$(event.target).parents().each(function() {
+			if($.data(this, that.widgetName + "-item") === that) {
+				currentItem = $(this);
+				return false;
+			}
+		});
+		if($.data(event.target, that.widgetName + "-item") === that) {
+			currentItem = $(event.target);
+		}
+
+		if(!currentItem) {
+			return false;
+		}
+		if(this.options.handle && !overrideHandle) {
+			$(this.options.handle, currentItem).find("*").addBack().each(function() {
+				if(this === event.target) {
+					validHandle = true;
+				}
+			});
+			if(!validHandle) {
+				return false;
+			}
+		}
+
+		this.currentItem = currentItem;
+		this._removeCurrentsFromItems();
+		return true;
+
+	},
+
+	_mouseStart: function(event, overrideHandle, noActivation) {
+
+		var i, body,
+			o = this.options;
+
+		this.currentContainer = this;
+
+		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
+		this.refreshPositions();
+
+		//Create and append the visible helper
+		this.helper = this._createHelper(event);
+
+		//Cache the helper size
+		this._cacheHelperProportions();
+
+		/*
+		 * - Position generation -
+		 * This block generates everything position related - it's the core of draggables.
+		 */
+
+		//Cache the margins of the original element
+		this._cacheMargins();
+
+		//Get the next scrolling parent
+		this.scrollParent = this.helper.scrollParent();
+
+		//The element's absolute position on the page minus margins
+		this.offset = this.currentItem.offset();
+		this.offset = {
+			top: this.offset.top - this.margins.top,
+			left: this.offset.left - this.margins.left
+		};
+
+		$.extend(this.offset, {
+			click: { //Where the click happened, relative to the element
+				left: event.pageX - this.offset.left,
+				top: event.pageY - this.offset.top
+			},
+			parent: this._getParentOffset(),
+			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+		});
+
+		// Only after we got the offset, we can change the helper's position to absolute
+		// TODO: Still need to figure out a way to make relative sorting possible
+		this.helper.css("position", "absolute");
+		this.cssPosition = this.helper.css("position");
+
+		//Generate the original position
+		this.originalPosition = this._generatePosition(event);
+		this.originalPageX = event.pageX;
+		this.originalPageY = event.pageY;
+
+		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
+		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+		//Cache the former DOM position
+		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
+
+		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
+		if(this.helper[0] !== this.currentItem[0]) {
+			this.currentItem.hide();
+		}
+
+		//Create the placeholder
+		this._createPlaceholder();
+
+		//Set a containment if given in the options
+		if(o.containment) {
+			this._setContainment();
+		}
+
+		if( o.cursor && o.cursor !== "auto" ) { // cursor option
+			body = this.document.find( "body" );
+
+			// support: IE
+			this.storedCursor = body.css( "cursor" );
+			body.css( "cursor", o.cursor );
+
+			this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
+		}
+
+		if(o.opacity) { // opacity option
+			if (this.helper.css("opacity")) {
+				this._storedOpacity = this.helper.css("opacity");
+			}
+			this.helper.css("opacity", o.opacity);
+		}
+
+		if(o.zIndex) { // zIndex option
+			if (this.helper.css("zIndex")) {
+				this._storedZIndex = this.helper.css("zIndex");
+			}
+			this.helper.css("zIndex", o.zIndex);
+		}
+
+		//Prepare scrolling
+		if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
+			this.overflowOffset = this.scrollParent.offset();
+		}
+
+		//Call callbacks
+		this._trigger("start", event, this._uiHash());
+
+		//Recache the helper size
+		if(!this._preserveHelperProportions) {
+			this._cacheHelperProportions();
+		}
+
+
+		//Post "activate" events to possible containers
+		if( !noActivation ) {
+			for ( i = this.containers.length - 1; i >= 0; i-- ) {
+				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
+			}
+		}
+
+		//Prepare possible droppables
+		if($.ui.ddmanager) {
+			$.ui.ddmanager.current = this;
+		}
+
+		if ($.ui.ddmanager && !o.dropBehaviour) {
+			$.ui.ddmanager.prepareOffsets(this, event);
+		}
+
+		this.dragging = true;
+
+		this.helper.addClass("ui-sortable-helper");
+		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+		return true;
+
+	},
+
+	_mouseDrag: function(event) {
+		var i, item, itemElement, intersection,
+			o = this.options,
+			scrolled = false;
+
+		//Compute the helpers position
+		this.position = this._generatePosition(event);
+		this.positionAbs = this._convertPositionTo("absolute");
+
+		if (!this.lastPositionAbs) {
+			this.lastPositionAbs = this.positionAbs;
+		}
+
+		//Do scrolling
+		if(this.options.scroll) {
+			if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
+
+				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
+					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
+				} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
+					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
+				}
+
+				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
+					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
+				} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
+					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
+				}
+
+			} else {
+
+				if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) {
+					scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed);
+				} else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) {
+					scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed);
+				}
+
+				if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) {
+					scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed);
+				} else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) {
+					scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed);
+				}
+
+			}
+
+			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
+				$.ui.ddmanager.prepareOffsets(this, event);
+			}
+		}
+
+		//Regenerate the absolute position used for position checks
+		this.positionAbs = this._convertPositionTo("absolute");
+
+		//Set the helper position
+		if(!this.options.axis || this.options.axis !== "y") {
+			this.helper[0].style.left = this.position.left+"px";
+		}
+		if(!this.options.axis || this.options.axis !== "x") {
+			this.helper[0].style.top = this.position.top+"px";
+		}
+
+		//Rearrange
+		for (i = this.items.length - 1; i >= 0; i--) {
+
+			//Cache variables and intersection, continue if no intersection
+			item = this.items[i];
+			itemElement = item.item[0];
+			intersection = this._intersectsWithPointer(item);
+			if (!intersection) {
+				continue;
+			}
+
+			// Only put the placeholder inside the current Container, skip all
+			// items from other containers. This works because when moving
+			// an item from one container to another the
+			// currentContainer is switched before the placeholder is moved.
+			//
+			// Without this, moving items in "sub-sortables" can cause
+			// the placeholder to jitter between the outer and inner container.
+			if (item.instance !== this.currentContainer) {
+				continue;
+			}
+
+			// cannot intersect with itself
+			// no useless actions that have been done before
+			// no action if the item moved is the parent of the item checked
+			if (itemElement !== this.currentItem[0] &&
+				this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
+				!$.contains(this.placeholder[0], itemElement) &&
+				(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
+			) {
+
+				this.direction = intersection === 1 ? "down" : "up";
+
+				if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
+					this._rearrange(event, item);
+				} else {
+					break;
+				}
+
+				this._trigger("change", event, this._uiHash());
+				break;
+			}
+		}
+
+		//Post events to containers
+		this._contactContainers(event);
+
+		//Interconnect with droppables
+		if($.ui.ddmanager) {
+			$.ui.ddmanager.drag(this, event);
+		}
+
+		//Call callbacks
+		this._trigger("sort", event, this._uiHash());
+
+		this.lastPositionAbs = this.positionAbs;
+		return false;
+
+	},
+
+	_mouseStop: function(event, noPropagation) {
+
+		if(!event) {
+			return;
+		}
+
+		//If we are using droppables, inform the manager about the drop
+		if ($.ui.ddmanager && !this.options.dropBehaviour) {
+			$.ui.ddmanager.drop(this, event);
+		}
+
+		if(this.options.revert) {
+			var that = this,
+				cur = this.placeholder.offset(),
+				axis = this.options.axis,
+				animation = {};
+
+			if ( !axis || axis === "x" ) {
+				animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft);
+			}
+			if ( !axis || axis === "y" ) {
+				animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop);
+			}
+			this.reverting = true;
+			$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
+				that._clear(event);
+			});
+		} else {
+			this._clear(event, noPropagation);
+		}
+
+		return false;
+
+	},
+
+	cancel: function() {
+
+		if(this.dragging) {
+
+			this._mouseUp({ target: null });
+
+			if(this.options.helper === "original") {
+				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+			} else {
+				this.currentItem.show();
+			}
+
+			//Post deactivating events to containers
+			for (var i = this.containers.length - 1; i >= 0; i--){
+				this.containers[i]._trigger("deactivate", null, this._uiHash(this));
+				if(this.containers[i].containerCache.over) {
+					this.containers[i]._trigger("out", null, this._uiHash(this));
+					this.containers[i].containerCache.over = 0;
+				}
+			}
+
+		}
+
+		if (this.placeholder) {
+			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+			if(this.placeholder[0].parentNode) {
+				this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+			}
+			if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
+				this.helper.remove();
+			}
+
+			$.extend(this, {
+				helper: null,
+				dragging: false,
+				reverting: false,
+				_noFinalSort: null
+			});
+
+			if(this.domPosition.prev) {
+				$(this.domPosition.prev).after(this.currentItem);
+			} else {
+				$(this.domPosition.parent).prepend(this.currentItem);
+			}
+		}
+
+		return this;
+
+	},
+
+	serialize: function(o) {
+
+		var items = this._getItemsAsjQuery(o && o.connected),
+			str = [];
+		o = o || {};
+
+		$(items).each(function() {
+			var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
+			if (res) {
+				str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
+			}
+		});
+
+		if(!str.length && o.key) {
+			str.push(o.key + "=");
+		}
+
+		return str.join("&");
+
+	},
+
+	toArray: function(o) {
+
+		var items = this._getItemsAsjQuery(o && o.connected),
+			ret = [];
+
+		o = o || {};
+
+		items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
+		return ret;
+
+	},
+
+	/* Be careful with the following core functions */
+	_intersectsWith: function(item) {
+
+		var x1 = this.positionAbs.left,
+			x2 = x1 + this.helperProportions.width,
+			y1 = this.positionAbs.top,
+			y2 = y1 + this.helperProportions.height,
+			l = item.left,
+			r = l + item.width,
+			t = item.top,
+			b = t + item.height,
+			dyClick = this.offset.click.top,
+			dxClick = this.offset.click.left,
+			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
+			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
+			isOverElement = isOverElementHeight && isOverElementWidth;
+
+		if ( this.options.tolerance === "pointer" ||
+			this.options.forcePointerForContainers ||
+			(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
+		) {
+			return isOverElement;
+		} else {
+
+			return (l < x1 + (this.helperProportions.width / 2) && // Right Half
+				x2 - (this.helperProportions.width / 2) < r && // Left Half
+				t < y1 + (this.helperProportions.height / 2) && // Bottom Half
+				y2 - (this.helperProportions.height / 2) < b ); // Top Half
+
+		}
+	},
+
+	_intersectsWithPointer: function(item) {
+
+		var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
+			isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
+			isOverElement = isOverElementHeight && isOverElementWidth,
+			verticalDirection = this._getDragVerticalDirection(),
+			horizontalDirection = this._getDragHorizontalDirection();
+
+		if (!isOverElement) {
+			return false;
+		}
+
+		return this.floating ?
+			( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
+			: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
+
+	},
+
+	_intersectsWithSides: function(item) {
+
+		var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
+			isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
+			verticalDirection = this._getDragVerticalDirection(),
+			horizontalDirection = this._getDragHorizontalDirection();
+
+		if (this.floating && horizontalDirection) {
+			return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
+		} else {
+			return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
+		}
+
+	},
+
+	_getDragVerticalDirection: function() {
+		var delta = this.positionAbs.top - this.lastPositionAbs.top;
+		return delta !== 0 && (delta > 0 ? "down" : "up");
+	},
+
+	_getDragHorizontalDirection: function() {
+		var delta = this.positionAbs.left - this.lastPositionAbs.left;
+		return delta !== 0 && (delta > 0 ? "right" : "left");
+	},
+
+	refresh: function(event) {
+		this._refreshItems(event);
+		this._setHandleClassName();
+		this.refreshPositions();
+		return this;
+	},
+
+	_connectWith: function() {
+		var options = this.options;
+		return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
+	},
+
+	_getItemsAsjQuery: function(connected) {
+
+		var i, j, cur, inst,
+			items = [],
+			queries = [],
+			connectWith = this._connectWith();
+
+		if(connectWith && connected) {
+			for (i = connectWith.length - 1; i >= 0; i--){
+				cur = $(connectWith[i], this.document[0]);
+				for ( j = cur.length - 1; j >= 0; j--){
+					inst = $.data(cur[j], this.widgetFullName);
+					if(inst && inst !== this && !inst.options.disabled) {
+						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
+					}
+				}
+			}
+		}
+
+		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
+
+		function addItems() {
+			items.push( this );
+		}
+		for (i = queries.length - 1; i >= 0; i--){
+			queries[i][0].each( addItems );
+		}
+
+		return $(items);
+
+	},
+
+	_removeCurrentsFromItems: function() {
+
+		var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
+
+		this.items = $.grep(this.items, function (item) {
+			for (var j=0; j < list.length; j++) {
+				if(list[j] === item.item[0]) {
+					return false;
+				}
+			}
+			return true;
+		});
+
+	},
+
+	_refreshItems: function(event) {
+
+		this.items = [];
+		this.containers = [this];
+
+		var i, j, cur, inst, targetData, _queries, item, queriesLength,
+			items = this.items,
+			queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
+			connectWith = this._connectWith();
+
+		if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
+			for (i = connectWith.length - 1; i >= 0; i--){
+				cur = $(connectWith[i], this.document[0]);
+				for (j = cur.length - 1; j >= 0; j--){
+					inst = $.data(cur[j], this.widgetFullName);
+					if(inst && inst !== this && !inst.options.disabled) {
+						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
+						this.containers.push(inst);
+					}
+				}
+			}
+		}
+
+		for (i = queries.length - 1; i >= 0; i--) {
+			targetData = queries[i][1];
+			_queries = queries[i][0];
+
+			for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
+				item = $(_queries[j]);
+
+				item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
+
+				items.push({
+					item: item,
+					instance: targetData,
+					width: 0, height: 0,
+					left: 0, top: 0
+				});
+			}
+		}
+
+	},
+
+	refreshPositions: function(fast) {
+
+		// Determine whether items are being displayed horizontally
+		this.floating = this.items.length ?
+			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
+			false;
+
+		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
+		if(this.offsetParent && this.helper) {
+			this.offset.parent = this._getParentOffset();
+		}
+
+		var i, item, t, p;
+
+		for (i = this.items.length - 1; i >= 0; i--){
+			item = this.items[i];
+
+			//We ignore calculating positions of all connected containers when we're not over them
+			if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
+				continue;
+			}
+
+			t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
+
+			if (!fast) {
+				item.width = t.outerWidth();
+				item.height = t.outerHeight();
+			}
+
+			p = t.offset();
+			item.left = p.left;
+			item.top = p.top;
+		}
+
+		if(this.options.custom && this.options.custom.refreshContainers) {
+			this.options.custom.refreshContainers.call(this);
+		} else {
+			for (i = this.containers.length - 1; i >= 0; i--){
+				p = this.containers[i].element.offset();
+				this.containers[i].containerCache.left = p.left;
+				this.containers[i].containerCache.top = p.top;
+				this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
+				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
+			}
+		}
+
+		return this;
+	},
+
+	_createPlaceholder: function(that) {
+		that = that || this;
+		var className,
+			o = that.options;
+
+		if(!o.placeholder || o.placeholder.constructor === String) {
+			className = o.placeholder;
+			o.placeholder = {
+				element: function() {
+
+					var nodeName = that.currentItem[0].nodeName.toLowerCase(),
+						element = $( "<" + nodeName + ">", that.document[0] )
+							.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
+							.removeClass("ui-sortable-helper");
+
+					if ( nodeName === "tbody" ) {
+						that._createTrPlaceholder(
+							that.currentItem.find( "tr" ).eq( 0 ),
+							$( "<tr>", that.document[ 0 ] ).appendTo( element )
+						);
+					} else if ( nodeName === "tr" ) {
+						that._createTrPlaceholder( that.currentItem, element );
+					} else if ( nodeName === "img" ) {
+						element.attr( "src", that.currentItem.attr( "src" ) );
+					}
+
+					if ( !className ) {
+						element.css( "visibility", "hidden" );
+					}
+
+					return element;
+				},
+				update: function(container, p) {
+
+					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
+					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
+					if(className && !o.forcePlaceholderSize) {
+						return;
+					}
+
+					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
+					if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
+					if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
+				}
+			};
+		}
+
+		//Create the placeholder
+		that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
+
+		//Append it after the actual current item
+		that.currentItem.after(that.placeholder);
+
+		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
+		o.placeholder.update(that, that.placeholder);
+
+	},
+
+	_createTrPlaceholder: function( sourceTr, targetTr ) {
+		var that = this;
+
+		sourceTr.children().each(function() {
+			$( "<td>&#160;</td>", that.document[ 0 ] )
+				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
+				.appendTo( targetTr );
+		});
+	},
+
+	_contactContainers: function(event) {
+		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
+			innermostContainer = null,
+			innermostIndex = null;
+
+		// get innermost container that intersects with item
+		for (i = this.containers.length - 1; i >= 0; i--) {
+
+			// never consider a container that's located within the item itself
+			if($.contains(this.currentItem[0], this.containers[i].element[0])) {
+				continue;
+			}
+
+			if(this._intersectsWith(this.containers[i].containerCache)) {
+
+				// if we've already found a container and it's more "inner" than this, then continue
+				if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
+					continue;
+				}
+
+				innermostContainer = this.containers[i];
+				innermostIndex = i;
+
+			} else {
+				// container doesn't intersect. trigger "out" event if necessary
+				if(this.containers[i].containerCache.over) {
+					this.containers[i]._trigger("out", event, this._uiHash(this));
+					this.containers[i].containerCache.over = 0;
+				}
+			}
+
+		}
+
+		// if no intersecting containers found, return
+		if(!innermostContainer) {
+			return;
+		}
+
+		// move the item into the container if it's not there already
+		if(this.containers.length === 1) {
+			if (!this.containers[innermostIndex].containerCache.over) {
+				this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+				this.containers[innermostIndex].containerCache.over = 1;
+			}
+		} else {
+
+			//When entering a new container, we will find the item with the least distance and append our item near it
+			dist = 10000;
+			itemWithLeastDistance = null;
+			floating = innermostContainer.floating || this._isFloating(this.currentItem);
+			posProperty = floating ? "left" : "top";
+			sizeProperty = floating ? "width" : "height";
+			axis = floating ? "clientX" : "clientY";
+
+			for (j = this.items.length - 1; j >= 0; j--) {
+				if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
+					continue;
+				}
+				if(this.items[j].item[0] === this.currentItem[0]) {
+					continue;
+				}
+
+				cur = this.items[j].item.offset()[posProperty];
+				nearBottom = false;
+				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
+					nearBottom = true;
+				}
+
+				if ( Math.abs( event[ axis ] - cur ) < dist ) {
+					dist = Math.abs( event[ axis ] - cur );
+					itemWithLeastDistance = this.items[ j ];
+					this.direction = nearBottom ? "up": "down";
+				}
+			}
+
+			//Check if dropOnEmpty is enabled
+			if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
+				return;
+			}
+
+			if(this.currentContainer === this.containers[innermostIndex]) {
+				if ( !this.currentContainer.containerCache.over ) {
+					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
+					this.currentContainer.containerCache.over = 1;
+				}
+				return;
+			}
+
+			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
+			this._trigger("change", event, this._uiHash());
+			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
+			this.currentContainer = this.containers[innermostIndex];
+
+			//Update the placeholder
+			this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+			this.containers[innermostIndex].containerCache.over = 1;
+		}
+
+
+	},
+
+	_createHelper: function(event) {
+
+		var o = this.options,
+			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
+
+		//Add the helper to the DOM if that didn't happen already
+		if(!helper.parents("body").length) {
+			$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
+		}
+
+		if(helper[0] === this.currentItem[0]) {
+			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
+		}
+
+		if(!helper[0].style.width || o.forceHelperSize) {
+			helper.width(this.currentItem.width());
+		}
+		if(!helper[0].style.height || o.forceHelperSize) {
+			helper.height(this.currentItem.height());
+		}
+
+		return helper;
+
+	},
+
+	_adjustOffsetFromHelper: function(obj) {
+		if (typeof obj === "string") {
+			obj = obj.split(" ");
+		}
+		if ($.isArray(obj)) {
+			obj = {left: +obj[0], top: +obj[1] || 0};
+		}
+		if ("left" in obj) {
+			this.offset.click.left = obj.left + this.margins.left;
+		}
+		if ("right" in obj) {
+			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+		}
+		if ("top" in obj) {
+			this.offset.click.top = obj.top + this.margins.top;
+		}
+		if ("bottom" in obj) {
+			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+		}
+	},
+
+	_getParentOffset: function() {
+
+
+		//Get the offsetParent and cache its position
+		this.offsetParent = this.helper.offsetParent();
+		var po = this.offsetParent.offset();
+
+		// This is a special case where we need to modify a offset calculated on start, since the following happened:
+		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+		if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) {
+			po.left += this.scrollParent.scrollLeft();
+			po.top += this.scrollParent.scrollTop();
+		}
+
+		// This needs to be actually done for all browsers, since pageX/pageY includes this information
+		// with an ugly IE fix
+		if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
+			po = { top: 0, left: 0 };
+		}
+
+		return {
+			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+		};
+
+	},
+
+	_getRelativeOffset: function() {
+
+		if(this.cssPosition === "relative") {
+			var p = this.currentItem.position();
+			return {
+				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+			};
+		} else {
+			return { top: 0, left: 0 };
+		}
+
+	},
+
+	_cacheMargins: function() {
+		this.margins = {
+			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
+			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
+		};
+	},
+
+	_cacheHelperProportions: function() {
+		this.helperProportions = {
+			width: this.helper.outerWidth(),
+			height: this.helper.outerHeight()
+		};
+	},
+
+	_setContainment: function() {
+
+		var ce, co, over,
+			o = this.options;
+		if(o.containment === "parent") {
+			o.containment = this.helper[0].parentNode;
+		}
+		if(o.containment === "document" || o.containment === "window") {
+			this.containment = [
+				0 - this.offset.relative.left - this.offset.parent.left,
+				0 - this.offset.relative.top - this.offset.parent.top,
+				o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left,
+				(o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+			];
+		}
+
+		if(!(/^(document|window|parent)$/).test(o.containment)) {
+			ce = $(o.containment)[0];
+			co = $(o.containment).offset();
+			over = ($(ce).css("overflow") !== "hidden");
+
+			this.containment = [
+				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
+				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
+				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
+				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
+			];
+		}
+
+	},
+
+	_convertPositionTo: function(d, pos) {
+
+		if(!pos) {
+			pos = this.position;
+		}
+		var mod = d === "absolute" ? 1 : -1,
+			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
+			scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+		return {
+			top: (
+				pos.top	+																// The absolute mouse position
+				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.top * mod -											// The offsetParent's offset without borders (offset + border)
+				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+			),
+			left: (
+				pos.left +																// The absolute mouse position
+				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
+				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+			)
+		};
+
+	},
+
+	_generatePosition: function(event) {
+
+		var top, left,
+			o = this.options,
+			pageX = event.pageX,
+			pageY = event.pageY,
+			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+		// This is another very weird special case that only happens for relative elements:
+		// 1. If the css position is relative
+		// 2. and the scroll parent is the document or similar to the offset parent
+		// we have to refresh the relative offset during the scroll so there are no jumps
+		if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) {
+			this.offset.relative = this._getRelativeOffset();
+		}
+
+		/*
+		 * - Position constraining -
+		 * Constrain the position to a mix of grid, containment.
+		 */
+
+		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+
+			if(this.containment) {
+				if(event.pageX - this.offset.click.left < this.containment[0]) {
+					pageX = this.containment[0] + this.offset.click.left;
+				}
+				if(event.pageY - this.offset.click.top < this.containment[1]) {
+					pageY = this.containment[1] + this.offset.click.top;
+				}
+				if(event.pageX - this.offset.click.left > this.containment[2]) {
+					pageX = this.containment[2] + this.offset.click.left;
+				}
+				if(event.pageY - this.offset.click.top > this.containment[3]) {
+					pageY = this.containment[3] + this.offset.click.top;
+				}
+			}
+
+			if(o.grid) {
+				top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
+				pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+				left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
+				pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+			}
+
+		}
+
+		return {
+			top: (
+				pageY -																// The absolute mouse position
+				this.offset.click.top -													// Click offset (relative to the element)
+				this.offset.relative.top	-											// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
+				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+			),
+			left: (
+				pageX -																// The absolute mouse position
+				this.offset.click.left -												// Click offset (relative to the element)
+				this.offset.relative.left	-											// Only for relative positioned nodes: Relative offset from element to offset parent
+				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
+				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+			)
+		};
+
+	},
+
+	_rearrange: function(event, i, a, hardRefresh) {
+
+		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
+
+		//Various things done here to improve the performance:
+		// 1. we create a setTimeout, that calls refreshPositions
+		// 2. on the instance, we have a counter variable, that get's higher after every append
+		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
+		// 4. this lets only the last addition to the timeout stack through
+		this.counter = this.counter ? ++this.counter : 1;
+		var counter = this.counter;
+
+		this._delay(function() {
+			if(counter === this.counter) {
+				this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
+			}
+		});
+
+	},
+
+	_clear: function(event, noPropagation) {
+
+		this.reverting = false;
+		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
+		// everything else normalized again
+		var i,
+			delayedTriggers = [];
+
+		// We first have to update the dom position of the actual currentItem
+		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
+		if(!this._noFinalSort && this.currentItem.parent().length) {
+			this.placeholder.before(this.currentItem);
+		}
+		this._noFinalSort = null;
+
+		if(this.helper[0] === this.currentItem[0]) {
+			for(i in this._storedCSS) {
+				if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
+					this._storedCSS[i] = "";
+				}
+			}
+			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+		} else {
+			this.currentItem.show();
+		}
+
+		if(this.fromOutside && !noPropagation) {
+			delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
+		}
+		if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
+			delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
+		}
+
+		// Check if the items Container has Changed and trigger appropriate
+		// events.
+		if (this !== this.currentContainer) {
+			if(!noPropagation) {
+				delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+				delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
+				delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
+			}
+		}
+
+
+		//Post events to containers
+		function delayEvent( type, instance, container ) {
+			return function( event ) {
+				container._trigger( type, event, instance._uiHash( instance ) );
+			};
+		}
+		for (i = this.containers.length - 1; i >= 0; i--){
+			if (!noPropagation) {
+				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
+			}
+			if(this.containers[i].containerCache.over) {
+				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
+				this.containers[i].containerCache.over = 0;
+			}
+		}
+
+		//Do what was originally in plugins
+		if ( this.storedCursor ) {
+			this.document.find( "body" ).css( "cursor", this.storedCursor );
+			this.storedStylesheet.remove();
+		}
+		if(this._storedOpacity) {
+			this.helper.css("opacity", this._storedOpacity);
+		}
+		if(this._storedZIndex) {
+			this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
+		}
+
+		this.dragging = false;
+
+		if(!noPropagation) {
+			this._trigger("beforeStop", event, this._uiHash());
+		}
+
+		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+
+		if ( !this.cancelHelperRemoval ) {
+			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
+				this.helper.remove();
+			}
+			this.helper = null;
+		}
+
+		if(!noPropagation) {
+			for (i=0; i < delayedTriggers.length; i++) {
+				delayedTriggers[i].call(this, event);
+			} //Trigger all delayed events
+			this._trigger("stop", event, this._uiHash());
+		}
+
+		this.fromOutside = false;
+		return !this.cancelHelperRemoval;
+
+	},
+
+	_trigger: function() {
+		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
+			this.cancel();
+		}
+	},
+
+	_uiHash: function(_inst) {
+		var inst = _inst || this;
+		return {
+			helper: inst.helper,
+			placeholder: inst.placeholder || $([]),
+			position: inst.position,
+			originalPosition: inst.originalPosition,
+			offset: inst.positionAbs,
+			item: inst.currentItem,
+			sender: _inst ? _inst.element : null
+		};
+	}
+
+});
+
+
+/*!
+ * jQuery UI Spinner 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/spinner/
+ */
+
+
+function spinner_modifier( fn ) {
+	return function() {
+		var previous = this.element.val();
+		fn.apply( this, arguments );
+		this._refresh();
+		if ( previous !== this.element.val() ) {
+			this._trigger( "change" );
+		}
+	};
+}
+
+var spinner = $.widget( "ui.spinner", {
+	version: "1.11.4",
+	defaultElement: "<input>",
+	widgetEventPrefix: "spin",
+	options: {
+		culture: null,
+		icons: {
+			down: "ui-icon-triangle-1-s",
+			up: "ui-icon-triangle-1-n"
+		},
+		incremental: true,
+		max: null,
+		min: null,
+		numberFormat: null,
+		page: 10,
+		step: 1,
+
+		change: null,
+		spin: null,
+		start: null,
+		stop: null
+	},
+
+	_create: function() {
+		// handle string values that need to be parsed
+		this._setOption( "max", this.options.max );
+		this._setOption( "min", this.options.min );
+		this._setOption( "step", this.options.step );
+
+		// Only format if there is a value, prevents the field from being marked
+		// as invalid in Firefox, see #9573.
+		if ( this.value() !== "" ) {
+			// Format the value, but don't constrain.
+			this._value( this.element.val(), true );
+		}
+
+		this._draw();
+		this._on( this._events );
+		this._refresh();
+
+		// turning off autocomplete prevents the browser from remembering the
+		// value when navigating through history, so we re-enable autocomplete
+		// if the page is unloaded before the widget is destroyed. #7790
+		this._on( this.window, {
+			beforeunload: function() {
+				this.element.removeAttr( "autocomplete" );
+			}
+		});
+	},
+
+	_getCreateOptions: function() {
+		var options = {},
+			element = this.element;
+
+		$.each( [ "min", "max", "step" ], function( i, option ) {
+			var value = element.attr( option );
+			if ( value !== undefined && value.length ) {
+				options[ option ] = value;
+			}
+		});
+
+		return options;
+	},
+
+	_events: {
+		keydown: function( event ) {
+			if ( this._start( event ) && this._keydown( event ) ) {
+				event.preventDefault();
+			}
+		},
+		keyup: "_stop",
+		focus: function() {
+			this.previous = this.element.val();
+		},
+		blur: function( event ) {
+			if ( this.cancelBlur ) {
+				delete this.cancelBlur;
+				return;
+			}
+
+			this._stop();
+			this._refresh();
+			if ( this.previous !== this.element.val() ) {
+				this._trigger( "change", event );
+			}
+		},
+		mousewheel: function( event, delta ) {
+			if ( !delta ) {
+				return;
+			}
+			if ( !this.spinning && !this._start( event ) ) {
+				return false;
+			}
+
+			this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
+			clearTimeout( this.mousewheelTimer );
+			this.mousewheelTimer = this._delay(function() {
+				if ( this.spinning ) {
+					this._stop( event );
+				}
+			}, 100 );
+			event.preventDefault();
+		},
+		"mousedown .ui-spinner-button": function( event ) {
+			var previous;
+
+			// We never want the buttons to have focus; whenever the user is
+			// interacting with the spinner, the focus should be on the input.
+			// If the input is focused then this.previous is properly set from
+			// when the input first received focus. If the input is not focused
+			// then we need to set this.previous based on the value before spinning.
+			previous = this.element[0] === this.document[0].activeElement ?
+				this.previous : this.element.val();
+			function checkFocus() {
+				var isActive = this.element[0] === this.document[0].activeElement;
+				if ( !isActive ) {
+					this.element.focus();
+					this.previous = previous;
+					// support: IE
+					// IE sets focus asynchronously, so we need to check if focus
+					// moved off of the input because the user clicked on the button.
+					this._delay(function() {
+						this.previous = previous;
+					});
+				}
+			}
+
+			// ensure focus is on (or stays on) the text field
+			event.preventDefault();
+			checkFocus.call( this );
+
+			// support: IE
+			// IE doesn't prevent moving focus even with event.preventDefault()
+			// so we set a flag to know when we should ignore the blur event
+			// and check (again) if focus moved off of the input.
+			this.cancelBlur = true;
+			this._delay(function() {
+				delete this.cancelBlur;
+				checkFocus.call( this );
+			});
+
+			if ( this._start( event ) === false ) {
+				return;
+			}
+
+			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
+		},
+		"mouseup .ui-spinner-button": "_stop",
+		"mouseenter .ui-spinner-button": function( event ) {
+			// button will add ui-state-active if mouse was down while mouseleave and kept down
+			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
+				return;
+			}
+
+			if ( this._start( event ) === false ) {
+				return false;
+			}
+			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
+		},
+		// TODO: do we really want to consider this a stop?
+		// shouldn't we just stop the repeater and wait until mouseup before
+		// we trigger the stop event?
+		"mouseleave .ui-spinner-button": "_stop"
+	},
+
+	_draw: function() {
+		var uiSpinner = this.uiSpinner = this.element
+			.addClass( "ui-spinner-input" )
+			.attr( "autocomplete", "off" )
+			.wrap( this._uiSpinnerHtml() )
+			.parent()
+				// add buttons
+				.append( this._buttonHtml() );
+
+		this.element.attr( "role", "spinbutton" );
+
+		// button bindings
+		this.buttons = uiSpinner.find( ".ui-spinner-button" )
+			.attr( "tabIndex", -1 )
+			.button()
+			.removeClass( "ui-corner-all" );
+
+		// IE 6 doesn't understand height: 50% for the buttons
+		// unless the wrapper has an explicit height
+		if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
+				uiSpinner.height() > 0 ) {
+			uiSpinner.height( uiSpinner.height() );
+		}
+
+		// disable spinner if element was already disabled
+		if ( this.options.disabled ) {
+			this.disable();
+		}
+	},
+
+	_keydown: function( event ) {
+		var options = this.options,
+			keyCode = $.ui.keyCode;
+
+		switch ( event.keyCode ) {
+		case keyCode.UP:
+			this._repeat( null, 1, event );
+			return true;
+		case keyCode.DOWN:
+			this._repeat( null, -1, event );
+			return true;
+		case keyCode.PAGE_UP:
+			this._repeat( null, options.page, event );
+			return true;
+		case keyCode.PAGE_DOWN:
+			this._repeat( null, -options.page, event );
+			return true;
+		}
+
+		return false;
+	},
+
+	_uiSpinnerHtml: function() {
+		return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
+	},
+
+	_buttonHtml: function() {
+		return "" +
+			"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
+				"<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
+			"</a>" +
+			"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
+				"<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
+			"</a>";
+	},
+
+	_start: function( event ) {
+		if ( !this.spinning && this._trigger( "start", event ) === false ) {
+			return false;
+		}
+
+		if ( !this.counter ) {
+			this.counter = 1;
+		}
+		this.spinning = true;
+		return true;
+	},
+
+	_repeat: function( i, steps, event ) {
+		i = i || 500;
+
+		clearTimeout( this.timer );
+		this.timer = this._delay(function() {
+			this._repeat( 40, steps, event );
+		}, i );
+
+		this._spin( steps * this.options.step, event );
+	},
+
+	_spin: function( step, event ) {
+		var value = this.value() || 0;
+
+		if ( !this.counter ) {
+			this.counter = 1;
+		}
+
+		value = this._adjustValue( value + step * this._increment( this.counter ) );
+
+		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
+			this._value( value );
+			this.counter++;
+		}
+	},
+
+	_increment: function( i ) {
+		var incremental = this.options.incremental;
+
+		if ( incremental ) {
+			return $.isFunction( incremental ) ?
+				incremental( i ) :
+				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
+		}
+
+		return 1;
+	},
+
+	_precision: function() {
+		var precision = this._precisionOf( this.options.step );
+		if ( this.options.min !== null ) {
+			precision = Math.max( precision, this._precisionOf( this.options.min ) );
+		}
+		return precision;
+	},
+
+	_precisionOf: function( num ) {
+		var str = num.toString(),
+			decimal = str.indexOf( "." );
+		return decimal === -1 ? 0 : str.length - decimal - 1;
+	},
+
+	_adjustValue: function( value ) {
+		var base, aboveMin,
+			options = this.options;
+
+		// make sure we're at a valid step
+		// - find out where we are relative to the base (min or 0)
+		base = options.min !== null ? options.min : 0;
+		aboveMin = value - base;
+		// - round to the nearest step
+		aboveMin = Math.round(aboveMin / options.step) * options.step;
+		// - rounding is based on 0, so adjust back to our base
+		value = base + aboveMin;
+
+		// fix precision from bad JS floating point math
+		value = parseFloat( value.toFixed( this._precision() ) );
+
+		// clamp the value
+		if ( options.max !== null && value > options.max) {
+			return options.max;
+		}
+		if ( options.min !== null && value < options.min ) {
+			return options.min;
+		}
+
+		return value;
+	},
+
+	_stop: function( event ) {
+		if ( !this.spinning ) {
+			return;
+		}
+
+		clearTimeout( this.timer );
+		clearTimeout( this.mousewheelTimer );
+		this.counter = 0;
+		this.spinning = false;
+		this._trigger( "stop", event );
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "culture" || key === "numberFormat" ) {
+			var prevValue = this._parse( this.element.val() );
+			this.options[ key ] = value;
+			this.element.val( this._format( prevValue ) );
+			return;
+		}
+
+		if ( key === "max" || key === "min" || key === "step" ) {
+			if ( typeof value === "string" ) {
+				value = this._parse( value );
+			}
+		}
+		if ( key === "icons" ) {
+			this.buttons.first().find( ".ui-icon" )
+				.removeClass( this.options.icons.up )
+				.addClass( value.up );
+			this.buttons.last().find( ".ui-icon" )
+				.removeClass( this.options.icons.down )
+				.addClass( value.down );
+		}
+
+		this._super( key, value );
+
+		if ( key === "disabled" ) {
+			this.widget().toggleClass( "ui-state-disabled", !!value );
+			this.element.prop( "disabled", !!value );
+			this.buttons.button( value ? "disable" : "enable" );
+		}
+	},
+
+	_setOptions: spinner_modifier(function( options ) {
+		this._super( options );
+	}),
+
+	_parse: function( val ) {
+		if ( typeof val === "string" && val !== "" ) {
+			val = window.Globalize && this.options.numberFormat ?
+				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
+		}
+		return val === "" || isNaN( val ) ? null : val;
+	},
+
+	_format: function( value ) {
+		if ( value === "" ) {
+			return "";
+		}
+		return window.Globalize && this.options.numberFormat ?
+			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
+			value;
+	},
+
+	_refresh: function() {
+		this.element.attr({
+			"aria-valuemin": this.options.min,
+			"aria-valuemax": this.options.max,
+			// TODO: what should we do with values that can't be parsed?
+			"aria-valuenow": this._parse( this.element.val() )
+		});
+	},
+
+	isValid: function() {
+		var value = this.value();
+
+		// null is invalid
+		if ( value === null ) {
+			return false;
+		}
+
+		// if value gets adjusted, it's invalid
+		return value === this._adjustValue( value );
+	},
+
+	// update the value without triggering change
+	_value: function( value, allowAny ) {
+		var parsed;
+		if ( value !== "" ) {
+			parsed = this._parse( value );
+			if ( parsed !== null ) {
+				if ( !allowAny ) {
+					parsed = this._adjustValue( parsed );
+				}
+				value = this._format( parsed );
+			}
+		}
+		this.element.val( value );
+		this._refresh();
+	},
+
+	_destroy: function() {
+		this.element
+			.removeClass( "ui-spinner-input" )
+			.prop( "disabled", false )
+			.removeAttr( "autocomplete" )
+			.removeAttr( "role" )
+			.removeAttr( "aria-valuemin" )
+			.removeAttr( "aria-valuemax" )
+			.removeAttr( "aria-valuenow" );
+		this.uiSpinner.replaceWith( this.element );
+	},
+
+	stepUp: spinner_modifier(function( steps ) {
+		this._stepUp( steps );
+	}),
+	_stepUp: function( steps ) {
+		if ( this._start() ) {
+			this._spin( (steps || 1) * this.options.step );
+			this._stop();
+		}
+	},
+
+	stepDown: spinner_modifier(function( steps ) {
+		this._stepDown( steps );
+	}),
+	_stepDown: function( steps ) {
+		if ( this._start() ) {
+			this._spin( (steps || 1) * -this.options.step );
+			this._stop();
+		}
+	},
+
+	pageUp: spinner_modifier(function( pages ) {
+		this._stepUp( (pages || 1) * this.options.page );
+	}),
+
+	pageDown: spinner_modifier(function( pages ) {
+		this._stepDown( (pages || 1) * this.options.page );
+	}),
+
+	value: function( newVal ) {
+		if ( !arguments.length ) {
+			return this._parse( this.element.val() );
+		}
+		spinner_modifier( this._value ).call( this, newVal );
+	},
+
+	widget: function() {
+		return this.uiSpinner;
+	}
+});
+
+
+/*!
+ * jQuery UI Tabs 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/tabs/
+ */
+
+
+var tabs = $.widget( "ui.tabs", {
+	version: "1.11.4",
+	delay: 300,
+	options: {
+		active: null,
+		collapsible: false,
+		event: "click",
+		heightStyle: "content",
+		hide: null,
+		show: null,
+
+		// callbacks
+		activate: null,
+		beforeActivate: null,
+		beforeLoad: null,
+		load: null
+	},
+
+	_isLocal: (function() {
+		var rhash = /#.*$/;
+
+		return function( anchor ) {
+			var anchorUrl, locationUrl;
+
+			// support: IE7
+			// IE7 doesn't normalize the href property when set via script (#9317)
+			anchor = anchor.cloneNode( false );
+
+			anchorUrl = anchor.href.replace( rhash, "" );
+			locationUrl = location.href.replace( rhash, "" );
+
+			// decoding may throw an error if the URL isn't UTF-8 (#9518)
+			try {
+				anchorUrl = decodeURIComponent( anchorUrl );
+			} catch ( error ) {}
+			try {
+				locationUrl = decodeURIComponent( locationUrl );
+			} catch ( error ) {}
+
+			return anchor.hash.length > 1 && anchorUrl === locationUrl;
+		};
+	})(),
+
+	_create: function() {
+		var that = this,
+			options = this.options;
+
+		this.running = false;
+
+		this.element
+			.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
+			.toggleClass( "ui-tabs-collapsible", options.collapsible );
+
+		this._processTabs();
+		options.active = this._initialActive();
+
+		// Take disabling tabs via class attribute from HTML
+		// into account and update option properly.
+		if ( $.isArray( options.disabled ) ) {
+			options.disabled = $.unique( options.disabled.concat(
+				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
+					return that.tabs.index( li );
+				})
+			) ).sort();
+		}
+
+		// check for length avoids error when initializing empty list
+		if ( this.options.active !== false && this.anchors.length ) {
+			this.active = this._findActive( options.active );
+		} else {
+			this.active = $();
+		}
+
+		this._refresh();
+
+		if ( this.active.length ) {
+			this.load( options.active );
+		}
+	},
+
+	_initialActive: function() {
+		var active = this.options.active,
+			collapsible = this.options.collapsible,
+			locationHash = location.hash.substring( 1 );
+
+		if ( active === null ) {
+			// check the fragment identifier in the URL
+			if ( locationHash ) {
+				this.tabs.each(function( i, tab ) {
+					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
+						active = i;
+						return false;
+					}
+				});
+			}
+
+			// check for a tab marked active via a class
+			if ( active === null ) {
+				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
+			}
+
+			// no active tab, set to false
+			if ( active === null || active === -1 ) {
+				active = this.tabs.length ? 0 : false;
+			}
+		}
+
+		// handle numbers: negative, out of range
+		if ( active !== false ) {
+			active = this.tabs.index( this.tabs.eq( active ) );
+			if ( active === -1 ) {
+				active = collapsible ? false : 0;
+			}
+		}
+
+		// don't allow collapsible: false and active: false
+		if ( !collapsible && active === false && this.anchors.length ) {
+			active = 0;
+		}
+
+		return active;
+	},
+
+	_getCreateEventData: function() {
+		return {
+			tab: this.active,
+			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
+		};
+	},
+
+	_tabKeydown: function( event ) {
+		var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
+			selectedIndex = this.tabs.index( focusedTab ),
+			goingForward = true;
+
+		if ( this._handlePageNav( event ) ) {
+			return;
+		}
+
+		switch ( event.keyCode ) {
+			case $.ui.keyCode.RIGHT:
+			case $.ui.keyCode.DOWN:
+				selectedIndex++;
+				break;
+			case $.ui.keyCode.UP:
+			case $.ui.keyCode.LEFT:
+				goingForward = false;
+				selectedIndex--;
+				break;
+			case $.ui.keyCode.END:
+				selectedIndex = this.anchors.length - 1;
+				break;
+			case $.ui.keyCode.HOME:
+				selectedIndex = 0;
+				break;
+			case $.ui.keyCode.SPACE:
+				// Activate only, no collapsing
+				event.preventDefault();
+				clearTimeout( this.activating );
+				this._activate( selectedIndex );
+				return;
+			case $.ui.keyCode.ENTER:
+				// Toggle (cancel delayed activation, allow collapsing)
+				event.preventDefault();
+				clearTimeout( this.activating );
+				// Determine if we should collapse or activate
+				this._activate( selectedIndex === this.options.active ? false : selectedIndex );
+				return;
+			default:
+				return;
+		}
+
+		// Focus the appropriate tab, based on which key was pressed
+		event.preventDefault();
+		clearTimeout( this.activating );
+		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
+
+		// Navigating with control/command key will prevent automatic activation
+		if ( !event.ctrlKey && !event.metaKey ) {
+
+			// Update aria-selected immediately so that AT think the tab is already selected.
+			// Otherwise AT may confuse the user by stating that they need to activate the tab,
+			// but the tab will already be activated by the time the announcement finishes.
+			focusedTab.attr( "aria-selected", "false" );
+			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
+
+			this.activating = this._delay(function() {
+				this.option( "active", selectedIndex );
+			}, this.delay );
+		}
+	},
+
+	_panelKeydown: function( event ) {
+		if ( this._handlePageNav( event ) ) {
+			return;
+		}
+
+		// Ctrl+up moves focus to the current tab
+		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
+			event.preventDefault();
+			this.active.focus();
+		}
+	},
+
+	// Alt+page up/down moves focus to the previous/next tab (and activates)
+	_handlePageNav: function( event ) {
+		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
+			this._activate( this._focusNextTab( this.options.active - 1, false ) );
+			return true;
+		}
+		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
+			this._activate( this._focusNextTab( this.options.active + 1, true ) );
+			return true;
+		}
+	},
+
+	_findNextTab: function( index, goingForward ) {
+		var lastTabIndex = this.tabs.length - 1;
+
+		function constrain() {
+			if ( index > lastTabIndex ) {
+				index = 0;
+			}
+			if ( index < 0 ) {
+				index = lastTabIndex;
+			}
+			return index;
+		}
+
+		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
+			index = goingForward ? index + 1 : index - 1;
+		}
+
+		return index;
+	},
+
+	_focusNextTab: function( index, goingForward ) {
+		index = this._findNextTab( index, goingForward );
+		this.tabs.eq( index ).focus();
+		return index;
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "active" ) {
+			// _activate() will handle invalid values and update this.options
+			this._activate( value );
+			return;
+		}
+
+		if ( key === "disabled" ) {
+			// don't use the widget factory's disabled handling
+			this._setupDisabled( value );
+			return;
+		}
+
+		this._super( key, value);
+
+		if ( key === "collapsible" ) {
+			this.element.toggleClass( "ui-tabs-collapsible", value );
+			// Setting collapsible: false while collapsed; open first panel
+			if ( !value && this.options.active === false ) {
+				this._activate( 0 );
+			}
+		}
+
+		if ( key === "event" ) {
+			this._setupEvents( value );
+		}
+
+		if ( key === "heightStyle" ) {
+			this._setupHeightStyle( value );
+		}
+	},
+
+	_sanitizeSelector: function( hash ) {
+		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
+	},
+
+	refresh: function() {
+		var options = this.options,
+			lis = this.tablist.children( ":has(a[href])" );
+
+		// get disabled tabs from class attribute from HTML
+		// this will get converted to a boolean if needed in _refresh()
+		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
+			return lis.index( tab );
+		});
+
+		this._processTabs();
+
+		// was collapsed or no tabs
+		if ( options.active === false || !this.anchors.length ) {
+			options.active = false;
+			this.active = $();
+		// was active, but active tab is gone
+		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
+			// all remaining tabs are disabled
+			if ( this.tabs.length === options.disabled.length ) {
+				options.active = false;
+				this.active = $();
+			// activate previous tab
+			} else {
+				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
+			}
+		// was active, active tab still exists
+		} else {
+			// make sure active index is correct
+			options.active = this.tabs.index( this.active );
+		}
+
+		this._refresh();
+	},
+
+	_refresh: function() {
+		this._setupDisabled( this.options.disabled );
+		this._setupEvents( this.options.event );
+		this._setupHeightStyle( this.options.heightStyle );
+
+		this.tabs.not( this.active ).attr({
+			"aria-selected": "false",
+			"aria-expanded": "false",
+			tabIndex: -1
+		});
+		this.panels.not( this._getPanelForTab( this.active ) )
+			.hide()
+			.attr({
+				"aria-hidden": "true"
+			});
+
+		// Make sure one tab is in the tab order
+		if ( !this.active.length ) {
+			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
+		} else {
+			this.active
+				.addClass( "ui-tabs-active ui-state-active" )
+				.attr({
+					"aria-selected": "true",
+					"aria-expanded": "true",
+					tabIndex: 0
+				});
+			this._getPanelForTab( this.active )
+				.show()
+				.attr({
+					"aria-hidden": "false"
+				});
+		}
+	},
+
+	_processTabs: function() {
+		var that = this,
+			prevTabs = this.tabs,
+			prevAnchors = this.anchors,
+			prevPanels = this.panels;
+
+		this.tablist = this._getList()
+			.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
+			.attr( "role", "tablist" )
+
+			// Prevent users from focusing disabled tabs via click
+			.delegate( "> li", "mousedown" + this.eventNamespace, function( event ) {
+				if ( $( this ).is( ".ui-state-disabled" ) ) {
+					event.preventDefault();
+				}
+			})
+
+			// support: IE <9
+			// Preventing the default action in mousedown doesn't prevent IE
+			// from focusing the element, so if the anchor gets focused, blur.
+			// We don't have to worry about focusing the previously focused
+			// element since clicking on a non-focusable element should focus
+			// the body anyway.
+			.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
+				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
+					this.blur();
+				}
+			});
+
+		this.tabs = this.tablist.find( "> li:has(a[href])" )
+			.addClass( "ui-state-default ui-corner-top" )
+			.attr({
+				role: "tab",
+				tabIndex: -1
+			});
+
+		this.anchors = this.tabs.map(function() {
+				return $( "a", this )[ 0 ];
+			})
+			.addClass( "ui-tabs-anchor" )
+			.attr({
+				role: "presentation",
+				tabIndex: -1
+			});
+
+		this.panels = $();
+
+		this.anchors.each(function( i, anchor ) {
+			var selector, panel, panelId,
+				anchorId = $( anchor ).uniqueId().attr( "id" ),
+				tab = $( anchor ).closest( "li" ),
+				originalAriaControls = tab.attr( "aria-controls" );
+
+			// inline tab
+			if ( that._isLocal( anchor ) ) {
+				selector = anchor.hash;
+				panelId = selector.substring( 1 );
+				panel = that.element.find( that._sanitizeSelector( selector ) );
+			// remote tab
+			} else {
+				// If the tab doesn't already have aria-controls,
+				// generate an id by using a throw-away element
+				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
+				selector = "#" + panelId;
+				panel = that.element.find( selector );
+				if ( !panel.length ) {
+					panel = that._createPanel( panelId );
+					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
+				}
+				panel.attr( "aria-live", "polite" );
+			}
+
+			if ( panel.length) {
+				that.panels = that.panels.add( panel );
+			}
+			if ( originalAriaControls ) {
+				tab.data( "ui-tabs-aria-controls", originalAriaControls );
+			}
+			tab.attr({
+				"aria-controls": panelId,
+				"aria-labelledby": anchorId
+			});
+			panel.attr( "aria-labelledby", anchorId );
+		});
+
+		this.panels
+			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+			.attr( "role", "tabpanel" );
+
+		// Avoid memory leaks (#10056)
+		if ( prevTabs ) {
+			this._off( prevTabs.not( this.tabs ) );
+			this._off( prevAnchors.not( this.anchors ) );
+			this._off( prevPanels.not( this.panels ) );
+		}
+	},
+
+	// allow overriding how to find the list for rare usage scenarios (#7715)
+	_getList: function() {
+		return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
+	},
+
+	_createPanel: function( id ) {
+		return $( "<div>" )
+			.attr( "id", id )
+			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+			.data( "ui-tabs-destroy", true );
+	},
+
+	_setupDisabled: function( disabled ) {
+		if ( $.isArray( disabled ) ) {
+			if ( !disabled.length ) {
+				disabled = false;
+			} else if ( disabled.length === this.anchors.length ) {
+				disabled = true;
+			}
+		}
+
+		// disable tabs
+		for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
+			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
+				$( li )
+					.addClass( "ui-state-disabled" )
+					.attr( "aria-disabled", "true" );
+			} else {
+				$( li )
+					.removeClass( "ui-state-disabled" )
+					.removeAttr( "aria-disabled" );
+			}
+		}
+
+		this.options.disabled = disabled;
+	},
+
+	_setupEvents: function( event ) {
+		var events = {};
+		if ( event ) {
+			$.each( event.split(" "), function( index, eventName ) {
+				events[ eventName ] = "_eventHandler";
+			});
+		}
+
+		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
+		// Always prevent the default action, even when disabled
+		this._on( true, this.anchors, {
+			click: function( event ) {
+				event.preventDefault();
+			}
+		});
+		this._on( this.anchors, events );
+		this._on( this.tabs, { keydown: "_tabKeydown" } );
+		this._on( this.panels, { keydown: "_panelKeydown" } );
+
+		this._focusable( this.tabs );
+		this._hoverable( this.tabs );
+	},
+
+	_setupHeightStyle: function( heightStyle ) {
+		var maxHeight,
+			parent = this.element.parent();
+
+		if ( heightStyle === "fill" ) {
+			maxHeight = parent.height();
+			maxHeight -= this.element.outerHeight() - this.element.height();
+
+			this.element.siblings( ":visible" ).each(function() {
+				var elem = $( this ),
+					position = elem.css( "position" );
+
+				if ( position === "absolute" || position === "fixed" ) {
+					return;
+				}
+				maxHeight -= elem.outerHeight( true );
+			});
+
+			this.element.children().not( this.panels ).each(function() {
+				maxHeight -= $( this ).outerHeight( true );
+			});
+
+			this.panels.each(function() {
+				$( this ).height( Math.max( 0, maxHeight -
+					$( this ).innerHeight() + $( this ).height() ) );
+			})
+			.css( "overflow", "auto" );
+		} else if ( heightStyle === "auto" ) {
+			maxHeight = 0;
+			this.panels.each(function() {
+				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
+			}).height( maxHeight );
+		}
+	},
+
+	_eventHandler: function( event ) {
+		var options = this.options,
+			active = this.active,
+			anchor = $( event.currentTarget ),
+			tab = anchor.closest( "li" ),
+			clickedIsActive = tab[ 0 ] === active[ 0 ],
+			collapsing = clickedIsActive && options.collapsible,
+			toShow = collapsing ? $() : this._getPanelForTab( tab ),
+			toHide = !active.length ? $() : this._getPanelForTab( active ),
+			eventData = {
+				oldTab: active,
+				oldPanel: toHide,
+				newTab: collapsing ? $() : tab,
+				newPanel: toShow
+			};
+
+		event.preventDefault();
+
+		if ( tab.hasClass( "ui-state-disabled" ) ||
+				// tab is already loading
+				tab.hasClass( "ui-tabs-loading" ) ||
+				// can't switch durning an animation
+				this.running ||
+				// click on active header, but not collapsible
+				( clickedIsActive && !options.collapsible ) ||
+				// allow canceling activation
+				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
+			return;
+		}
+
+		options.active = collapsing ? false : this.tabs.index( tab );
+
+		this.active = clickedIsActive ? $() : tab;
+		if ( this.xhr ) {
+			this.xhr.abort();
+		}
+
+		if ( !toHide.length && !toShow.length ) {
+			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
+		}
+
+		if ( toShow.length ) {
+			this.load( this.tabs.index( tab ), event );
+		}
+		this._toggle( event, eventData );
+	},
+
+	// handles show/hide for selecting tabs
+	_toggle: function( event, eventData ) {
+		var that = this,
+			toShow = eventData.newPanel,
+			toHide = eventData.oldPanel;
+
+		this.running = true;
+
+		function complete() {
+			that.running = false;
+			that._trigger( "activate", event, eventData );
+		}
+
+		function show() {
+			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
+
+			if ( toShow.length && that.options.show ) {
+				that._show( toShow, that.options.show, complete );
+			} else {
+				toShow.show();
+				complete();
+			}
+		}
+
+		// start out by hiding, then showing, then completing
+		if ( toHide.length && this.options.hide ) {
+			this._hide( toHide, this.options.hide, function() {
+				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+				show();
+			});
+		} else {
+			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+			toHide.hide();
+			show();
+		}
+
+		toHide.attr( "aria-hidden", "true" );
+		eventData.oldTab.attr({
+			"aria-selected": "false",
+			"aria-expanded": "false"
+		});
+		// If we're switching tabs, remove the old tab from the tab order.
+		// If we're opening from collapsed state, remove the previous tab from the tab order.
+		// If we're collapsing, then keep the collapsing tab in the tab order.
+		if ( toShow.length && toHide.length ) {
+			eventData.oldTab.attr( "tabIndex", -1 );
+		} else if ( toShow.length ) {
+			this.tabs.filter(function() {
+				return $( this ).attr( "tabIndex" ) === 0;
+			})
+			.attr( "tabIndex", -1 );
+		}
+
+		toShow.attr( "aria-hidden", "false" );
+		eventData.newTab.attr({
+			"aria-selected": "true",
+			"aria-expanded": "true",
+			tabIndex: 0
+		});
+	},
+
+	_activate: function( index ) {
+		var anchor,
+			active = this._findActive( index );
+
+		// trying to activate the already active panel
+		if ( active[ 0 ] === this.active[ 0 ] ) {
+			return;
+		}
+
+		// trying to collapse, simulate a click on the current active header
+		if ( !active.length ) {
+			active = this.active;
+		}
+
+		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
+		this._eventHandler({
+			target: anchor,
+			currentTarget: anchor,
+			preventDefault: $.noop
+		});
+	},
+
+	_findActive: function( index ) {
+		return index === false ? $() : this.tabs.eq( index );
+	},
+
+	_getIndex: function( index ) {
+		// meta-function to give users option to provide a href string instead of a numerical index.
+		if ( typeof index === "string" ) {
+			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
+		}
+
+		return index;
+	},
+
+	_destroy: function() {
+		if ( this.xhr ) {
+			this.xhr.abort();
+		}
+
+		this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
+
+		this.tablist
+			.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
+			.removeAttr( "role" );
+
+		this.anchors
+			.removeClass( "ui-tabs-anchor" )
+			.removeAttr( "role" )
+			.removeAttr( "tabIndex" )
+			.removeUniqueId();
+
+		this.tablist.unbind( this.eventNamespace );
+
+		this.tabs.add( this.panels ).each(function() {
+			if ( $.data( this, "ui-tabs-destroy" ) ) {
+				$( this ).remove();
+			} else {
+				$( this )
+					.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
+						"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
+					.removeAttr( "tabIndex" )
+					.removeAttr( "aria-live" )
+					.removeAttr( "aria-busy" )
+					.removeAttr( "aria-selected" )
+					.removeAttr( "aria-labelledby" )
+					.removeAttr( "aria-hidden" )
+					.removeAttr( "aria-expanded" )
+					.removeAttr( "role" );
+			}
+		});
+
+		this.tabs.each(function() {
+			var li = $( this ),
+				prev = li.data( "ui-tabs-aria-controls" );
+			if ( prev ) {
+				li
+					.attr( "aria-controls", prev )
+					.removeData( "ui-tabs-aria-controls" );
+			} else {
+				li.removeAttr( "aria-controls" );
+			}
+		});
+
+		this.panels.show();
+
+		if ( this.options.heightStyle !== "content" ) {
+			this.panels.css( "height", "" );
+		}
+	},
+
+	enable: function( index ) {
+		var disabled = this.options.disabled;
+		if ( disabled === false ) {
+			return;
+		}
+
+		if ( index === undefined ) {
+			disabled = false;
+		} else {
+			index = this._getIndex( index );
+			if ( $.isArray( disabled ) ) {
+				disabled = $.map( disabled, function( num ) {
+					return num !== index ? num : null;
+				});
+			} else {
+				disabled = $.map( this.tabs, function( li, num ) {
+					return num !== index ? num : null;
+				});
+			}
+		}
+		this._setupDisabled( disabled );
+	},
+
+	disable: function( index ) {
+		var disabled = this.options.disabled;
+		if ( disabled === true ) {
+			return;
+		}
+
+		if ( index === undefined ) {
+			disabled = true;
+		} else {
+			index = this._getIndex( index );
+			if ( $.inArray( index, disabled ) !== -1 ) {
+				return;
+			}
+			if ( $.isArray( disabled ) ) {
+				disabled = $.merge( [ index ], disabled ).sort();
+			} else {
+				disabled = [ index ];
+			}
+		}
+		this._setupDisabled( disabled );
+	},
+
+	load: function( index, event ) {
+		index = this._getIndex( index );
+		var that = this,
+			tab = this.tabs.eq( index ),
+			anchor = tab.find( ".ui-tabs-anchor" ),
+			panel = this._getPanelForTab( tab ),
+			eventData = {
+				tab: tab,
+				panel: panel
+			},
+			complete = function( jqXHR, status ) {
+				if ( status === "abort" ) {
+					that.panels.stop( false, true );
+				}
+
+				tab.removeClass( "ui-tabs-loading" );
+				panel.removeAttr( "aria-busy" );
+
+				if ( jqXHR === that.xhr ) {
+					delete that.xhr;
+				}
+			};
+
+		// not remote
+		if ( this._isLocal( anchor[ 0 ] ) ) {
+			return;
+		}
+
+		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
+
+		// support: jQuery <1.8
+		// jQuery <1.8 returns false if the request is canceled in beforeSend,
+		// but as of 1.8, $.ajax() always returns a jqXHR object.
+		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
+			tab.addClass( "ui-tabs-loading" );
+			panel.attr( "aria-busy", "true" );
+
+			this.xhr
+				.done(function( response, status, jqXHR ) {
+					// support: jQuery <1.8
+					// http://bugs.jquery.com/ticket/11778
+					setTimeout(function() {
+						panel.html( response );
+						that._trigger( "load", event, eventData );
+
+						complete( jqXHR, status );
+					}, 1 );
+				})
+				.fail(function( jqXHR, status ) {
+					// support: jQuery <1.8
+					// http://bugs.jquery.com/ticket/11778
+					setTimeout(function() {
+						complete( jqXHR, status );
+					}, 1 );
+				});
+		}
+	},
+
+	_ajaxSettings: function( anchor, event, eventData ) {
+		var that = this;
+		return {
+			url: anchor.attr( "href" ),
+			beforeSend: function( jqXHR, settings ) {
+				return that._trigger( "beforeLoad", event,
+					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
+			}
+		};
+	},
+
+	_getPanelForTab: function( tab ) {
+		var id = $( tab ).attr( "aria-controls" );
+		return this.element.find( this._sanitizeSelector( "#" + id ) );
+	}
+});
+
+
+/*!
+ * jQuery UI Tooltip 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/tooltip/
+ */
+
+
+var tooltip = $.widget( "ui.tooltip", {
+	version: "1.11.4",
+	options: {
+		content: function() {
+			// support: IE<9, Opera in jQuery <1.7
+			// .text() can't accept undefined, so coerce to a string
+			var title = $( this ).attr( "title" ) || "";
+			// Escape title, since we're going from an attribute to raw HTML
+			return $( "<a>" ).text( title ).html();
+		},
+		hide: true,
+		// Disabled elements have inconsistent behavior across browsers (#8661)
+		items: "[title]:not([disabled])",
+		position: {
+			my: "left top+15",
+			at: "left bottom",
+			collision: "flipfit flip"
+		},
+		show: true,
+		tooltipClass: null,
+		track: false,
+
+		// callbacks
+		close: null,
+		open: null
+	},
+
+	_addDescribedBy: function( elem, id ) {
+		var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
+		describedby.push( id );
+		elem
+			.data( "ui-tooltip-id", id )
+			.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
+	},
+
+	_removeDescribedBy: function( elem ) {
+		var id = elem.data( "ui-tooltip-id" ),
+			describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
+			index = $.inArray( id, describedby );
+
+		if ( index !== -1 ) {
+			describedby.splice( index, 1 );
+		}
+
+		elem.removeData( "ui-tooltip-id" );
+		describedby = $.trim( describedby.join( " " ) );
+		if ( describedby ) {
+			elem.attr( "aria-describedby", describedby );
+		} else {
+			elem.removeAttr( "aria-describedby" );
+		}
+	},
+
+	_create: function() {
+		this._on({
+			mouseover: "open",
+			focusin: "open"
+		});
+
+		// IDs of generated tooltips, needed for destroy
+		this.tooltips = {};
+
+		// IDs of parent tooltips where we removed the title attribute
+		this.parents = {};
+
+		if ( this.options.disabled ) {
+			this._disable();
+		}
+
+		// Append the aria-live region so tooltips announce correctly
+		this.liveRegion = $( "<div>" )
+			.attr({
+				role: "log",
+				"aria-live": "assertive",
+				"aria-relevant": "additions"
+			})
+			.addClass( "ui-helper-hidden-accessible" )
+			.appendTo( this.document[ 0 ].body );
+	},
+
+	_setOption: function( key, value ) {
+		var that = this;
+
+		if ( key === "disabled" ) {
+			this[ value ? "_disable" : "_enable" ]();
+			this.options[ key ] = value;
+			// disable element style changes
+			return;
+		}
+
+		this._super( key, value );
+
+		if ( key === "content" ) {
+			$.each( this.tooltips, function( id, tooltipData ) {
+				that._updateContent( tooltipData.element );
+			});
+		}
+	},
+
+	_disable: function() {
+		var that = this;
+
+		// close open tooltips
+		$.each( this.tooltips, function( id, tooltipData ) {
+			var event = $.Event( "blur" );
+			event.target = event.currentTarget = tooltipData.element[ 0 ];
+			that.close( event, true );
+		});
+
+		// remove title attributes to prevent native tooltips
+		this.element.find( this.options.items ).addBack().each(function() {
+			var element = $( this );
+			if ( element.is( "[title]" ) ) {
+				element
+					.data( "ui-tooltip-title", element.attr( "title" ) )
+					.removeAttr( "title" );
+			}
+		});
+	},
+
+	_enable: function() {
+		// restore title attributes
+		this.element.find( this.options.items ).addBack().each(function() {
+			var element = $( this );
+			if ( element.data( "ui-tooltip-title" ) ) {
+				element.attr( "title", element.data( "ui-tooltip-title" ) );
+			}
+		});
+	},
+
+	open: function( event ) {
+		var that = this,
+			target = $( event ? event.target : this.element )
+				// we need closest here due to mouseover bubbling,
+				// but always pointing at the same event target
+				.closest( this.options.items );
+
+		// No element to show a tooltip for or the tooltip is already open
+		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
+			return;
+		}
+
+		if ( target.attr( "title" ) ) {
+			target.data( "ui-tooltip-title", target.attr( "title" ) );
+		}
+
+		target.data( "ui-tooltip-open", true );
+
+		// kill parent tooltips, custom or native, for hover
+		if ( event && event.type === "mouseover" ) {
+			target.parents().each(function() {
+				var parent = $( this ),
+					blurEvent;
+				if ( parent.data( "ui-tooltip-open" ) ) {
+					blurEvent = $.Event( "blur" );
+					blurEvent.target = blurEvent.currentTarget = this;
+					that.close( blurEvent, true );
+				}
+				if ( parent.attr( "title" ) ) {
+					parent.uniqueId();
+					that.parents[ this.id ] = {
+						element: this,
+						title: parent.attr( "title" )
+					};
+					parent.attr( "title", "" );
+				}
+			});
+		}
+
+		this._registerCloseHandlers( event, target );
+		this._updateContent( target, event );
+	},
+
+	_updateContent: function( target, event ) {
+		var content,
+			contentOption = this.options.content,
+			that = this,
+			eventType = event ? event.type : null;
+
+		if ( typeof contentOption === "string" ) {
+			return this._open( event, target, contentOption );
+		}
+
+		content = contentOption.call( target[0], function( response ) {
+
+			// IE may instantly serve a cached response for ajax requests
+			// delay this call to _open so the other call to _open runs first
+			that._delay(function() {
+
+				// Ignore async response if tooltip was closed already
+				if ( !target.data( "ui-tooltip-open" ) ) {
+					return;
+				}
+
+				// jQuery creates a special event for focusin when it doesn't
+				// exist natively. To improve performance, the native event
+				// object is reused and the type is changed. Therefore, we can't
+				// rely on the type being correct after the event finished
+				// bubbling, so we set it back to the previous value. (#8740)
+				if ( event ) {
+					event.type = eventType;
+				}
+				this._open( event, target, response );
+			});
+		});
+		if ( content ) {
+			this._open( event, target, content );
+		}
+	},
+
+	_open: function( event, target, content ) {
+		var tooltipData, tooltip, delayedShow, a11yContent,
+			positionOption = $.extend( {}, this.options.position );
+
+		if ( !content ) {
+			return;
+		}
+
+		// Content can be updated multiple times. If the tooltip already
+		// exists, then just update the content and bail.
+		tooltipData = this._find( target );
+		if ( tooltipData ) {
+			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
+			return;
+		}
+
+		// if we have a title, clear it to prevent the native tooltip
+		// we have to check first to avoid defining a title if none exists
+		// (we don't want to cause an element to start matching [title])
+		//
+		// We use removeAttr only for key events, to allow IE to export the correct
+		// accessible attributes. For mouse events, set to empty string to avoid
+		// native tooltip showing up (happens only when removing inside mouseover).
+		if ( target.is( "[title]" ) ) {
+			if ( event && event.type === "mouseover" ) {
+				target.attr( "title", "" );
+			} else {
+				target.removeAttr( "title" );
+			}
+		}
+
+		tooltipData = this._tooltip( target );
+		tooltip = tooltipData.tooltip;
+		this._addDescribedBy( target, tooltip.attr( "id" ) );
+		tooltip.find( ".ui-tooltip-content" ).html( content );
+
+		// Support: Voiceover on OS X, JAWS on IE <= 9
+		// JAWS announces deletions even when aria-relevant="additions"
+		// Voiceover will sometimes re-read the entire log region's contents from the beginning
+		this.liveRegion.children().hide();
+		if ( content.clone ) {
+			a11yContent = content.clone();
+			a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
+		} else {
+			a11yContent = content;
+		}
+		$( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
+
+		function position( event ) {
+			positionOption.of = event;
+			if ( tooltip.is( ":hidden" ) ) {
+				return;
+			}
+			tooltip.position( positionOption );
+		}
+		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
+			this._on( this.document, {
+				mousemove: position
+			});
+			// trigger once to override element-relative positioning
+			position( event );
+		} else {
+			tooltip.position( $.extend({
+				of: target
+			}, this.options.position ) );
+		}
+
+		tooltip.hide();
+
+		this._show( tooltip, this.options.show );
+		// Handle tracking tooltips that are shown with a delay (#8644). As soon
+		// as the tooltip is visible, position the tooltip using the most recent
+		// event.
+		if ( this.options.show && this.options.show.delay ) {
+			delayedShow = this.delayedShow = setInterval(function() {
+				if ( tooltip.is( ":visible" ) ) {
+					position( positionOption.of );
+					clearInterval( delayedShow );
+				}
+			}, $.fx.interval );
+		}
+
+		this._trigger( "open", event, { tooltip: tooltip } );
+	},
+
+	_registerCloseHandlers: function( event, target ) {
+		var events = {
+			keyup: function( event ) {
+				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
+					var fakeEvent = $.Event(event);
+					fakeEvent.currentTarget = target[0];
+					this.close( fakeEvent, true );
+				}
+			}
+		};
+
+		// Only bind remove handler for delegated targets. Non-delegated
+		// tooltips will handle this in destroy.
+		if ( target[ 0 ] !== this.element[ 0 ] ) {
+			events.remove = function() {
+				this._removeTooltip( this._find( target ).tooltip );
+			};
+		}
+
+		if ( !event || event.type === "mouseover" ) {
+			events.mouseleave = "close";
+		}
+		if ( !event || event.type === "focusin" ) {
+			events.focusout = "close";
+		}
+		this._on( true, target, events );
+	},
+
+	close: function( event ) {
+		var tooltip,
+			that = this,
+			target = $( event ? event.currentTarget : this.element ),
+			tooltipData = this._find( target );
+
+		// The tooltip may already be closed
+		if ( !tooltipData ) {
+
+			// We set ui-tooltip-open immediately upon open (in open()), but only set the
+			// additional data once there's actually content to show (in _open()). So even if the
+			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
+			// the period between open() and _open().
+			target.removeData( "ui-tooltip-open" );
+			return;
+		}
+
+		tooltip = tooltipData.tooltip;
+
+		// disabling closes the tooltip, so we need to track when we're closing
+		// to avoid an infinite loop in case the tooltip becomes disabled on close
+		if ( tooltipData.closing ) {
+			return;
+		}
+
+		// Clear the interval for delayed tracking tooltips
+		clearInterval( this.delayedShow );
+
+		// only set title if we had one before (see comment in _open())
+		// If the title attribute has changed since open(), don't restore
+		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
+			target.attr( "title", target.data( "ui-tooltip-title" ) );
+		}
+
+		this._removeDescribedBy( target );
+
+		tooltipData.hiding = true;
+		tooltip.stop( true );
+		this._hide( tooltip, this.options.hide, function() {
+			that._removeTooltip( $( this ) );
+		});
+
+		target.removeData( "ui-tooltip-open" );
+		this._off( target, "mouseleave focusout keyup" );
+
+		// Remove 'remove' binding only on delegated targets
+		if ( target[ 0 ] !== this.element[ 0 ] ) {
+			this._off( target, "remove" );
+		}
+		this._off( this.document, "mousemove" );
+
+		if ( event && event.type === "mouseleave" ) {
+			$.each( this.parents, function( id, parent ) {
+				$( parent.element ).attr( "title", parent.title );
+				delete that.parents[ id ];
+			});
+		}
+
+		tooltipData.closing = true;
+		this._trigger( "close", event, { tooltip: tooltip } );
+		if ( !tooltipData.hiding ) {
+			tooltipData.closing = false;
+		}
+	},
+
+	_tooltip: function( element ) {
+		var tooltip = $( "<div>" )
+				.attr( "role", "tooltip" )
+				.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
+					( this.options.tooltipClass || "" ) ),
+			id = tooltip.uniqueId().attr( "id" );
+
+		$( "<div>" )
+			.addClass( "ui-tooltip-content" )
+			.appendTo( tooltip );
+
+		tooltip.appendTo( this.document[0].body );
+
+		return this.tooltips[ id ] = {
+			element: element,
+			tooltip: tooltip
+		};
+	},
+
+	_find: function( target ) {
+		var id = target.data( "ui-tooltip-id" );
+		return id ? this.tooltips[ id ] : null;
+	},
+
+	_removeTooltip: function( tooltip ) {
+		tooltip.remove();
+		delete this.tooltips[ tooltip.attr( "id" ) ];
+	},
+
+	_destroy: function() {
+		var that = this;
+
+		// close open tooltips
+		$.each( this.tooltips, function( id, tooltipData ) {
+			// Delegate to close method to handle common cleanup
+			var event = $.Event( "blur" ),
+				element = tooltipData.element;
+			event.target = event.currentTarget = element[ 0 ];
+			that.close( event, true );
+
+			// Remove immediately; destroying an open tooltip doesn't use the
+			// hide animation
+			$( "#" + id ).remove();
+
+			// Restore the title
+			if ( element.data( "ui-tooltip-title" ) ) {
+				// If the title attribute has changed since open(), don't restore
+				if ( !element.attr( "title" ) ) {
+					element.attr( "title", element.data( "ui-tooltip-title" ) );
+				}
+				element.removeData( "ui-tooltip-title" );
+			}
+		});
+		this.liveRegion.remove();
+	}
+});
+
+
+
+}));
\ No newline at end of file
-- 
GitLab