diff --git a/.gitignore b/.gitignore
index 37aad71..8f16afd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,12 @@
+/desuto-viewer/Desuto-webviewer/js/config/config.js
 /data/
 .DS_Store
 .jshintrc
 .project
 .tern-project
 .settings/
 node_modules/
 *~
 .idea
 README.pdf
 .env
diff --git a/desuto-couchdb/local.ini b/desuto-couchdb/10-docker-default.ini
similarity index 100%
rename from desuto-couchdb/local.ini
rename to desuto-couchdb/10-docker-default.ini
diff --git a/desuto-couchdb/Dockerfile b/desuto-couchdb/Dockerfile
index be31eb2..fe502be 100755
--- a/desuto-couchdb/Dockerfile
+++ b/desuto-couchdb/Dockerfile
@@ -1,128 +1,6 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
-# use this file except in compliance with the License. You may obtain a copy of
-# the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations under
-# the License.
+FROM couchdb:latest
+MAINTAINER Roger Schaer roger.schaer@hevs.ch
 
-FROM debian:jessie
-
-MAINTAINER CouchDB Developers dev@couchdb.apache.org
-
-# Add CouchDB user account
-RUN groupadd -r couchdb && useradd -d /opt/couchdb -g couchdb couchdb
-
-RUN apt-get update -y && apt-get install -y --no-install-recommends \
-    ca-certificates \
-    curl \
-    erlang-nox \
-    erlang-reltool \
-    haproxy \
-    libicu52 \
-    libmozjs185-1.0 \
-    openssl \
-  && rm -rf /var/lib/apt/lists/*
-
-# grab gosu for easy step-down from root and tini for signal handling
-# see https://github.com/apache/couchdb-docker/pull/28#discussion_r141112407
-ENV GOSU_VERSION 1.10
-ENV TINI_VERSION 0.16.1
-RUN set -ex; \
-	\
-	apt-get update; \
-	apt-get install -y --no-install-recommends wget; \
-	rm -rf /var/lib/apt/lists/*; \
-	\
-	dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
-	\
-# install gosu
-	wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-$dpkgArch"; \
-	wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
-	export GNUPGHOME="$(mktemp -d)"; \
-	gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
-	gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
-	rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc; \
-	chmod +x /usr/local/bin/gosu; \
-	gosu nobody true; \
-	\
-# install tini
-	wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$dpkgArch"; \
-	wget -O /usr/local/bin/tini.asc "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$dpkgArch.asc"; \
-	export GNUPGHOME="$(mktemp -d)"; \
-	gpg --keyserver ha.pool.sks-keyservers.net --recv-keys 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7; \
-	gpg --batch --verify /usr/local/bin/tini.asc /usr/local/bin/tini; \
-	rm -r "$GNUPGHOME" /usr/local/bin/tini.asc; \
-	chmod +x /usr/local/bin/tini; \
-	tini --version; \
-	\
-	apt-get purge -y --auto-remove wget
-
-# https://www.apache.org/dist/couchdb/KEYS
-ENV GPG_KEYS \
-  15DD4F3B8AACA54740EB78C7B7B7C53943ECCEE1 \
-  1CFBFA43C19B6DF4A0CA3934669C02FFDF3CEBA3 \
-  25BBBAC113C1BFD5AA594A4C9F96B92930380381 \
-  4BFCA2B99BADC6F9F105BEC9C5E32E2D6B065BFB \
-  5D680346FAA3E51B29DBCB681015F68F9DA248BC \
-  7BCCEB868313DDA925DF1805ECA5BCB7BB9656B0 \
-  C3F4DFAEAD621E1C94523AEEC376457E61D50B88 \
-  D2B17F9DA23C0A10991AF2E3D9EE01E47852AEE4 \
-  E0AF0A194D55C84E4A19A801CDB0C0F904F4EE9B \
-  29E4F38113DF707D722A6EF91FE9AF73118F1A7C \
-  2EC788AE3F239FA13E82D215CDE711289384AE37
-RUN set -xe \
-  && for key in $GPG_KEYS; do \
-    gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
-  done
-
-ENV COUCHDB_VERSION 2.1.1
-
-# Download dev dependencies
-RUN buildDeps=' \
-    apt-transport-https \
-    gcc \
-    g++ \
-    erlang-dev \
-    libcurl4-openssl-dev \
-    libicu-dev \
-    libmozjs185-dev \
-    make \
-  ' \
- && apt-get update -y -qq && apt-get install -y --no-install-recommends $buildDeps \
- # Acquire CouchDB source code
- && cd /usr/src && mkdir couchdb \
- && curl -fSL https://dist.apache.org/repos/dist/release/couchdb/source/$COUCHDB_VERSION/apache-couchdb-$COUCHDB_VERSION.tar.gz -o couchdb.tar.gz \
- && curl -fSL https://dist.apache.org/repos/dist/release/couchdb/source/$COUCHDB_VERSION/apache-couchdb-$COUCHDB_VERSION.tar.gz.asc -o couchdb.tar.gz.asc \
- && gpg --batch --verify couchdb.tar.gz.asc couchdb.tar.gz \
- && tar -xzf couchdb.tar.gz -C couchdb --strip-components=1 \
- && cd couchdb \
- # Build the release and install into /opt
- && ./configure --disable-docs \
- && make release \
- && mv /usr/src/couchdb/rel/couchdb /opt/ \
- # Cleanup build detritus
- && apt-get purge -y --auto-remove $buildDeps \
- && rm -rf /var/lib/apt/lists/* /usr/src/couchdb* \
- && mkdir /opt/couchdb/data \
- && chown -R couchdb:couchdb /opt/couchdb
-
-# Add configuration
-COPY local.ini /opt/couchdb/etc/local.d/
+COPY 10-docker-default.ini /opt/couchdb/etc/default.d/
 COPY vm.args /opt/couchdb/etc/
-
-COPY ./docker-entrypoint.sh /
-
-# Setup directories and permissions
-RUN chown -R couchdb:couchdb /opt/couchdb/etc/local.d/ /opt/couchdb/etc/vm.args
-
-WORKDIR /opt/couchdb
-EXPOSE 5984 4369 9100
-VOLUME ["/opt/couchdb/data"]
-
-ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"]
-CMD ["/opt/couchdb/bin/couchdb"]
+COPY docker-entrypoint.sh /usr/local/bin
\ No newline at end of file
diff --git a/desuto-couchdb/docker-entrypoint.sh b/desuto-couchdb/docker-entrypoint.sh
index dcccc81..ae06393 100755
--- a/desuto-couchdb/docker-entrypoint.sh
+++ b/desuto-couchdb/docker-entrypoint.sh
@@ -1,96 +1,98 @@
 #!/bin/bash
 # Licensed under the Apache License, Version 2.0 (the "License"); you may not
 # use this file except in compliance with the License. You may obtain a copy of
 # the License at
 #
 #   http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 # License for the specific language governing permissions and limitations under
 # the License.
 
 set -m
 
 if [ "$1" = '/opt/couchdb/bin/couchdb' ]; then
 	# we need to set the permissions here because docker mounts volumes as root
 	chown -R couchdb:couchdb /opt/couchdb
 
 	chmod -R 0770 /opt/couchdb/data
 
 	chmod 664 /opt/couchdb/etc/*.ini
 	chmod 664 /opt/couchdb/etc/local.d/*.ini
 	chmod 775 /opt/couchdb/etc/*.d
 
 	if [ ! -z "$NODENAME" ] && ! grep "couchdb@" /opt/couchdb/etc/vm.args; then
 		echo "-name couchdb@$NODENAME" >> /opt/couchdb/etc/vm.args
 	fi
 
 	if [ "$COUCHDB_USER" ] && [ "$COUCHDB_PASSWORD" ]; then
 		# Create admin
 		printf "[admins]\n%s = %s\n" "$COUCHDB_USER" "$COUCHDB_PASSWORD" > /opt/couchdb/etc/local.d/docker.ini
 		chown couchdb:couchdb /opt/couchdb/etc/local.d/docker.ini
 	fi
 
 	# if we don't find an [admins] section followed by a non-comment, display a warning
 	if ! grep -Pzoqr '\[admins\]\n[^;]\w+' /opt/couchdb/etc/local.d/*.ini; then
 		# The - option suppresses leading tabs but *not* spaces. :)
 		cat >&2 <<-'EOWARN'
 			****************************************************
 			WARNING: CouchDB is running in Admin Party mode.
 			         This will allow anyone with access to the
 			         CouchDB port to access your database. In
 			         Docker's default configuration, this is
 			         effectively any other container on the same
 			         system.
 			         Use "-e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password"
 			         to set it in "docker run".
 			****************************************************
 		EOWARN
 	fi
 
 	#exec gosu couchdb "$@"
 
 	# Run CouchdB in background
 	gosu couchdb "$@" &
 
 	# Wait for the server to be up
 	sleep 10
 
 	# Variables (set your own)
-	user=admin
-	pass='$TH3C0uch---4Dmin!'
-	host=localhost
-	port=5984
-	protocol=http
-	dbname=histopatho
+	user=$COUCHDB_USER
+	pass=$COUCHDB_PASSWORD
+	host=$COUCHDB_HOST
+	port=$COUCHDB_PORT
+	protocol=$COUCHDB_PROTOCOL
+	dbname=$COUCHDB_DB_NAME
+
+	echo "Base URL for configuring the DB : $protocol://$user:$pass"'@'"$host:$port/"
 
 	####################
 	### Configure DB ###
 	####################
 
 	# Set timeout of cookies to 10h
 	curl -H "Content-Type: application/json" -X PUT -d '36000' "$protocol://$user:$pass"'@'"$host:$port/$dbname"
 
-  # Create system DBs
+    # Create system DBs
 	curl -X PUT "$protocol://$user:$pass"'@'"$host:$port/_users"
 	curl -X PUT "$protocol://$user:$pass"'@'"$host:$port/_replicator"
 	curl -X PUT "$protocol://$user:$pass"'@'"$host:$port/_global_changes"
 
 	# Create DB
 	curl -X PUT "$protocol://$user:$pass"'@'"$host:$port/$dbname"
 
 	# Setup DB security roles
 	curl -H "Content-Type: application/json" -X PUT -d '{"admins":{"names":["admin"],"roles":["admins"]},"members":{"names":[],"roles":["users","pathologists"]}}' "$protocol://$user:$pass"'@'"$host:$port/$dbname/_security"
 
 	# Setup users in DB
 	curl -H "Content-Type: application/json" -X PUT "$protocol://$user:$pass"'@'"$host:$port/_users/org.couchdb.user:user" --data-binary '{"_id": "org.couchdb.user:user","name": "user","roles": ["users", "regions"],"type": "user","password": "userpass"}'
 	curl -H "Content-Type: application/json" -X PUT "$protocol://$user:$pass"'@'"$host:$port/_users/org.couchdb.user:pathologist1" --data-binary '{"_id": "org.couchdb.user:pathologist1","name": "pathologist1","roles": ["users", "pathologists", "regions"],"type": "user","password": "pathologistpass"}'
 	curl -H "Content-Type: application/json" -X PUT "$protocol://$user:$pass"'@'"$host:$port/_users/org.couchdb.user:pathologist2" --data-binary '{"_id": "org.couchdb.user:pathologist2","name": "pathologist2","roles": ["users", "pathologists", "regions"],"type": "user","password": "pathologistpass"}'
 
 	# Bring CouchDB to foreground
 	fg
 fi
 
 exec "$@"
diff --git a/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py b/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py
index fd96861..dfe664a 100755
--- a/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py
+++ b/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py
@@ -1,105 +1,111 @@
 import web
 import urllib
 from slide import Slide
 from web.wsgiserver import CherryPyWSGIServer
 
 urls = (
     '/slide_properties/microns_pixel_x/(.*)', 'mppx',
     '/slide_properties/microns_pixel_y/(.*)', 'mppy',
     '/slide_properties/pixels_mm/(.*)', 'pmm',
     '/slide_properties/pixels_m/(.*)', 'pm',
     '/slide_properties/bounds/(.*)', 'bounds',
     '/slide_properties/nbr_levels/(.*)', 'nbrlevels',
     '/slide_properties/level_downsamples/(.*)', 'leveldownsamples',
     '/slide_properties/level_dimensions/(.*)', 'leveldimensions',
     '/slide_properties/best_level_for_downsample/(.*)/(.*)', 'bestleveldownsample',
     '/slide_properties/common_info/(.*)', 'commoninfo',
     '/slide_properties/magnification/(.*)', 'magnification'
 )
 
 app = web.application(urls, globals())
 
 def corshook():
     web.header('Access-Control-Allow-Origin',      '*')
     web.header('Access-Control-Allow-Credentials', 'true')
 
+def contentType():
+    web.header('Content-Type', 'text/plain')
+
 app.add_processor(web.loadhook(corshook))
+app.add_processor(web.loadhook(contentType))
 
 class commoninfo:
     def GET(self, imagepath):
+        web.header('Content-Type', 'application/json')
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.common_info()
 
 class magnification:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.magnification()
 
 class mppx:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.mpp_x()
 
 class mppy:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.mpp_y()
 
 class pmm:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.px_mm()
 
 class pm:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.px_m()
 
 class vendor:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.vendor()
 
 class bounds:
     def GET(self, imagepath):
+        web.header('Content-Type', 'application/json')
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.bounds()
 
 class nbrlevels:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.nbr_levels()
 
 class leveldownsamples:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.level_downsamples()
 
 class leveldimensions:
     def GET(self, imagepath):
         imagepath = urllib.unquote(imagepath)
         slide = Slide(imagepath)
         return slide.level_dimensions()
 
 class bestleveldownsample:
     def GET(self, imagepath, downsample):
         imagepath = urllib.unquote(imagepath)
         print(imagepath)
         print(downsample)
         slide = Slide(imagepath)
         return slide.best_level_for_downsample(downsample)
 
 
 
 if __name__ == "__main__":
     app.run()
diff --git a/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py b/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py
index 1384312..5692d55 100755
--- a/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py
+++ b/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py
@@ -1,91 +1,97 @@
 import openslide
 from openslide import OpenSlide, OpenSlideError
 import os
 import json
 
+
 class Slide:
 
     def __init__(self, imagepath):
-        self.osr = OpenSlide(imagepath);
+        self.osr = OpenSlide(imagepath)
 
     # Microns per pixel y
     def mpp_y(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_MPP_X)
 
     # Microns per pixel x
     def mpp_x(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_MPP_Y)
 
     # Pixels mer milimeter
     def px_mm(self):
-        return 1/(((float(self.mpp_x())+float(self.mpp_y()))/2)/1000)
+        if self.mpp_x() is not None and self.mpp_y() is not None:
+            return 1 / (((float(self.mpp_x()) + float(self.mpp_y())) / 2) / 1000)
+        else:
+            return None
 
     # Pixels mer milimeter
     def px_m(self):
-        return self.px_mm()*1000;
+        if self.px_mm() is not None:
+            return self.px_mm() * 1000
+        else:
+            return None
 
     # Vendor
     def vendor(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_VENDOR)
 
     # X coordinate of the rectangle bounding the non-empty region of the slide, if available
     def bounds_x(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_X)
 
     # X coordinate of the rectangle bounding the non-empty region of the slide, if available
     def bounds_y(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_Y)
 
     # width of the rectangle bounding the non-empty region of the slide, if available.
     def bounds_width(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_WIDTH)
 
     # Height of the rectangle bounding the non-empty region of the slide, if available.
     def bounds_height(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_HEIGHT)
 
     # x, y and rectangle width & height bounding the non-empty region of the slide, if available. JSON
     def bounds(self):
         info = {}
-        info['x']  =  self.bounds_x()
+        info['x'] = self.bounds_x()
         info['y'] = self.bounds_y()
         info['width'] = self.bounds_width()
         info['height'] = self.bounds_height()
         return json.dumps(info)
 
     # Number of magnification levels
     def nbr_levels(self):
         return self.osr.level_count
 
     # A list of downsample factors for each level of the slide. level_downsamples[k] is the downsample factor of level k.
     def level_downsamples(self):
         return self.osr.level_downsamples
 
     # A list of (width, height) tuples, one for each level of the slide. level_dimensions[k] are the dimensions of level k.
     def level_dimensions(self):
         return self.osr.level_dimensions
 
     # Best level for displaying the given downsample.
     def best_level_for_downsample(self, downsample):
         return self.osr.get_best_level_for_downsample(float(downsample))
 
     # Magnification level
     def magnification(self):
         return self.osr.properties.get(openslide.PROPERTY_NAME_OBJECTIVE_POWER)
 
     def common_info(self):
         info = {}
         info['pmm'] = self.px_mm()
         info['pm'] = self.px_m()
         info['nbrlevels'] = self.nbr_levels()
         info['leveldownsamples'] = self.level_downsamples()
         info['leveldimensions'] = self.level_dimensions()
 
-
         info['bounds'] = {}
-        info['bounds']['x']  =  self.bounds_x()
+        info['bounds']['x'] = self.bounds_x()
         info['bounds']['y'] = self.bounds_y()
         info['bounds']['width'] = self.bounds_width()
         info['bounds']['height'] = self.bounds_height()
 
-        return json.dumps(info);
+        return json.dumps(info)
diff --git a/desuto-viewer/.dockerignore b/desuto-viewer/.dockerignore
index 93f1361..e68de85 100755
--- a/desuto-viewer/.dockerignore
+++ b/desuto-viewer/.dockerignore
@@ -1,2 +1,3 @@
 node_modules
 npm-debug.log
+/public/js/config/config.js
diff --git a/desuto-viewer/Desuto-webviewer/config.js b/desuto-viewer/Desuto-webviewer/config.js
new file mode 100644
index 0000000..e0dfe84
--- /dev/null
+++ b/desuto-viewer/Desuto-webviewer/config.js
@@ -0,0 +1,8 @@
+module.exports = {
+  couchDBRootURL : process.env.COUCHDB_BACKEND_ROOT_URL,
+  tempDir : process.env.TEMP_DIR,
+  baseDir : '/slideviewerdata/',
+  uploadedDir : process.env.WSI_UPLOADED_DIR,
+  convertedDir : process.env.WSI_CONVERTED_DIR,
+  overlaysDir : process.env.WSI_OVERLAYS_DIR
+};
diff --git a/desuto-viewer/Desuto-webviewer/config.json b/desuto-viewer/Desuto-webviewer/config.json
deleted file mode 100644
index d710c80..0000000
--- a/desuto-viewer/Desuto-webviewer/config.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "couchDBRootURL" : "http://localhost/couchdb/",
-  "tempDir" : "/tmp/nodejs/",
-  "baseDir" : "/mnt/nas2/results/IntermediateResults/Desuto/SlideViewerData/",
-  "uploadedDir" : "uploaded/",
-  "convertedDir" : "converted/",
-  "overlaysDir" : "overlays/"
-}
diff --git a/desuto-viewer/Desuto-webviewer/package-lock.json b/desuto-viewer/Desuto-webviewer/package-lock.json
index e495305..288de6b 100644
--- a/desuto-viewer/Desuto-webviewer/package-lock.json
+++ b/desuto-viewer/Desuto-webviewer/package-lock.json
@@ -1,1438 +1,1492 @@
 {
   "name": "slide-viewer-backend",
   "version": "0.0.2",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
     "@types/babel-types": {
       "version": "7.0.4",
       "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.4.tgz",
       "integrity": "sha512-WiZhq3SVJHFRgRYLXvpf65XnV6ipVHhnNaNvE8yCimejrGglkg38kEj0JcizqwSHxmPSjcTlig/6JouxLGEhGw=="
     },
     "@types/babylon": {
       "version": "6.16.3",
       "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.3.tgz",
       "integrity": "sha512-lyJ8sW1PbY3uwuvpOBZ9zMYKshMnQpXmeDHh8dj9j2nJm/xrW0FgB5gLSYOArj5X0IfaXnmhFoJnhS4KbqIMug==",
       "requires": {
         "@types/babel-types": "*"
       }
     },
+    "@types/caseless": {
+      "version": "0.12.2",
+      "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
+      "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w=="
+    },
+    "@types/form-data": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
+      "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
+      "requires": {
+        "@types/node": "*"
+      }
+    },
+    "@types/node": {
+      "version": "11.11.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.3.tgz",
+      "integrity": "sha512-wp6IOGu1lxsfnrD+5mX6qwSwWuqsdkKKxTN4aQc4wByHAKZJf9/D4KXPQ1POUjEbnCP5LMggB0OEFNY9OTsMqg=="
+    },
+    "@types/request": {
+      "version": "2.48.1",
+      "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz",
+      "integrity": "sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==",
+      "requires": {
+        "@types/caseless": "*",
+        "@types/form-data": "*",
+        "@types/node": "*",
+        "@types/tough-cookie": "*"
+      }
+    },
+    "@types/tough-cookie": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz",
+      "integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg=="
+    },
     "accepts": {
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
       "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
       "requires": {
         "mime-types": "~2.1.18",
         "negotiator": "0.6.1"
       }
     },
     "acorn": {
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
       "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
     },
     "acorn-globals": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
       "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
       "requires": {
         "acorn": "^4.0.4"
       },
       "dependencies": {
         "acorn": {
           "version": "4.0.13",
           "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
           "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
         }
       }
     },
     "ajv": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+      "version": "6.10.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
+      "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
       "requires": {
-        "co": "^4.6.0",
-        "fast-deep-equal": "^1.0.0",
+        "fast-deep-equal": "^2.0.1",
         "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.3.0"
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
       }
     },
     "align-text": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
       "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
       "requires": {
         "kind-of": "^3.0.2",
         "longest": "^1.0.1",
         "repeat-string": "^1.5.2"
       }
     },
     "array-flatten": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
     },
     "asap": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
       "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
     },
     "asn1": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
-      "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
     },
     "assert-plus": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
     },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
     },
     "aws-sign2": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
     },
     "aws4": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
-      "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
     },
     "babel-runtime": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
       "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
       "requires": {
         "core-js": "^2.4.0",
         "regenerator-runtime": "^0.11.0"
       }
     },
     "babel-types": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
       "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
       "requires": {
         "babel-runtime": "^6.26.0",
         "esutils": "^2.0.2",
         "lodash": "^4.17.4",
         "to-fast-properties": "^1.0.3"
       }
     },
     "babylon": {
       "version": "6.18.0",
       "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
       "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
     },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
     },
     "basic-auth": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz",
-      "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+      "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
       "requires": {
-        "safe-buffer": "5.1.1"
-      },
-      "dependencies": {
-        "safe-buffer": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
-          "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
-        }
+        "safe-buffer": "5.1.2"
       }
     },
     "bcrypt-pbkdf": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
       "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
-      "optional": true,
       "requires": {
         "tweetnacl": "^0.14.3"
       }
     },
     "body-parser": {
       "version": "1.18.3",
       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
       "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
       "requires": {
         "bytes": "3.0.0",
         "content-type": "~1.0.4",
         "debug": "2.6.9",
         "depd": "~1.1.2",
         "http-errors": "~1.6.3",
         "iconv-lite": "0.4.23",
         "on-finished": "~2.3.0",
         "qs": "6.5.2",
         "raw-body": "2.3.3",
         "type-is": "~1.6.16"
       }
     },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
       "requires": {
         "balanced-match": "^1.0.0",
         "concat-map": "0.0.1"
       }
     },
     "browser-request": {
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz",
       "integrity": "sha1-ns5bWsqJopkyJC4Yv5M975h2zBc="
     },
     "bytes": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
       "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
     },
     "camelcase": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
       "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
     },
     "caseless": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
     },
     "center-align": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
       "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
       "requires": {
         "align-text": "^0.1.3",
         "lazy-cache": "^1.0.3"
       }
     },
     "character-parser": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
       "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
       "requires": {
         "is-regex": "^1.0.3"
       }
     },
     "clean-css": {
       "version": "4.1.11",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz",
       "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=",
       "requires": {
         "source-map": "0.5.x"
       }
     },
     "cliui": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
       "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
       "requires": {
         "center-align": "^0.1.1",
         "right-align": "^0.1.1",
         "wordwrap": "0.0.2"
       }
     },
     "cloudant-follow": {
-      "version": "0.17.0",
-      "resolved": "https://registry.npmjs.org/cloudant-follow/-/cloudant-follow-0.17.0.tgz",
-      "integrity": "sha512-JQ1xvKAHh8rsnSVBjATLCjz/vQw1sWBGadxr2H69yFMwD7hShUGDwwEefdypaxroUJ/w6t1cSwilp/hRUxEW8w==",
+      "version": "0.18.1",
+      "resolved": "https://registry.npmjs.org/cloudant-follow/-/cloudant-follow-0.18.1.tgz",
+      "integrity": "sha512-hflb0VlRrHcSkkvsvCZt6UdjbsGnKjy3d6BA3VV3e+WIXZP63HO6mVtOUd+df5W25OkkaqFM191MqQDW2Y7Ikw==",
       "requires": {
         "browser-request": "~0.3.0",
-        "debug": "^3.0.0",
-        "request": "^2.83.0"
+        "debug": "^4.0.1",
+        "request": "^2.88.0"
       },
       "dependencies": {
         "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "requires": {
-            "ms": "2.0.0"
+            "ms": "^2.1.1"
           }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
         }
       }
     },
-    "co": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
-      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
-    },
     "combined-stream": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
-      "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
+      "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
       "requires": {
         "delayed-stream": "~1.0.0"
       }
     },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
     "connect-multiparty": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/connect-multiparty/-/connect-multiparty-2.1.1.tgz",
-      "integrity": "sha1-bughL9siBNPxNfjBLjr6SV0YH9c=",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/connect-multiparty/-/connect-multiparty-2.2.0.tgz",
+      "integrity": "sha512-zKcpA7cuXGEhuw9Pz7JmVCFmp85jzGLGm/iiagXTwyEAJp4ypLPtRS/V4IGuGb9KjjrgHBs6P/gDCpZHnFzksA==",
       "requires": {
-        "multiparty": "~4.1.4",
+        "http-errors": "~1.7.0",
+        "multiparty": "~4.2.1",
         "on-finished": "~2.3.0",
         "qs": "~6.5.2",
         "type-is": "~1.6.16"
+      },
+      "dependencies": {
+        "http-errors": {
+          "version": "1.7.2",
+          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+          "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+          "requires": {
+            "depd": "~1.1.2",
+            "inherits": "2.0.3",
+            "setprototypeof": "1.1.1",
+            "statuses": ">= 1.5.0 < 2",
+            "toidentifier": "1.0.0"
+          }
+        },
+        "setprototypeof": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+          "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+        }
       }
     },
     "constantinople": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz",
       "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==",
       "requires": {
         "@types/babel-types": "^7.0.0",
         "@types/babylon": "^6.16.2",
         "babel-types": "^6.26.0",
         "babylon": "^6.18.0"
       }
     },
     "content-disposition": {
       "version": "0.5.2",
       "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
       "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
     },
     "content-type": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
       "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
     },
     "cookie": {
       "version": "0.3.1",
       "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
       "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
     },
     "cookie-parser": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz",
-      "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=",
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz",
+      "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==",
       "requires": {
         "cookie": "0.3.1",
         "cookie-signature": "1.0.6"
       }
     },
     "cookie-signature": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
     },
     "core-js": {
       "version": "2.5.7",
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
       "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
     },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
     "crc": {
       "version": "3.4.4",
       "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz",
       "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms="
     },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
       "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
       "requires": {
         "assert-plus": "^1.0.0"
       }
     },
     "debug": {
       "version": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
       "requires": {
         "ms": "2.0.0"
       }
     },
     "decamelize": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
       "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
     },
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
     },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
       "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
     },
     "destroy": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
     },
     "doctypes": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
       "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk="
     },
     "ecc-jsbn": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
-      "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
-      "optional": true,
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
       "requires": {
-        "jsbn": "~0.1.0"
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
       }
     },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
     },
     "encodeurl": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
     },
     "errorhandler": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.0.tgz",
       "integrity": "sha1-6rpkyl1UKjEayUX1gt78M2Fl2fQ=",
       "requires": {
         "accepts": "~1.3.3",
         "escape-html": "~1.0.3"
       }
     },
     "errs": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/errs/-/errs-0.3.2.tgz",
       "integrity": "sha1-eYCZstvTfKK8dJ5TinwTB9C1BJk="
     },
     "escape-html": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
     },
     "esutils": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
       "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
     },
     "etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
     },
     "express": {
-      "version": "4.16.3",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
-      "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
+      "version": "4.16.4",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+      "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
       "requires": {
         "accepts": "~1.3.5",
         "array-flatten": "1.1.1",
-        "body-parser": "1.18.2",
+        "body-parser": "1.18.3",
         "content-disposition": "0.5.2",
         "content-type": "~1.0.4",
         "cookie": "0.3.1",
         "cookie-signature": "1.0.6",
         "debug": "2.6.9",
         "depd": "~1.1.2",
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "etag": "~1.8.1",
         "finalhandler": "1.1.1",
         "fresh": "0.5.2",
         "merge-descriptors": "1.0.1",
         "methods": "~1.1.2",
         "on-finished": "~2.3.0",
         "parseurl": "~1.3.2",
         "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.3",
-        "qs": "6.5.1",
+        "proxy-addr": "~2.0.4",
+        "qs": "6.5.2",
         "range-parser": "~1.2.0",
-        "safe-buffer": "5.1.1",
+        "safe-buffer": "5.1.2",
         "send": "0.16.2",
         "serve-static": "1.13.2",
         "setprototypeof": "1.1.0",
         "statuses": "~1.4.0",
         "type-is": "~1.6.16",
         "utils-merge": "1.0.1",
         "vary": "~1.1.2"
       },
       "dependencies": {
-        "body-parser": {
-          "version": "1.18.2",
-          "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
-          "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
-          "requires": {
-            "bytes": "3.0.0",
-            "content-type": "~1.0.4",
-            "debug": "2.6.9",
-            "depd": "~1.1.1",
-            "http-errors": "~1.6.2",
-            "iconv-lite": "0.4.19",
-            "on-finished": "~2.3.0",
-            "qs": "6.5.1",
-            "raw-body": "2.3.2",
-            "type-is": "~1.6.15"
-          }
-        },
-        "iconv-lite": {
-          "version": "0.4.19",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
-          "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
-        },
-        "qs": {
-          "version": "6.5.1",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
-          "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
-        },
-        "raw-body": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
-          "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
-          "requires": {
-            "bytes": "3.0.0",
-            "http-errors": "1.6.2",
-            "iconv-lite": "0.4.19",
-            "unpipe": "1.0.0"
-          },
-          "dependencies": {
-            "depd": {
-              "version": "1.1.1",
-              "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
-              "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
-            },
-            "http-errors": {
-              "version": "1.6.2",
-              "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
-              "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
-              "requires": {
-                "depd": "1.1.1",
-                "inherits": "2.0.3",
-                "setprototypeof": "1.0.3",
-                "statuses": ">= 1.3.1 < 2"
-              }
-            },
-            "setprototypeof": {
-              "version": "1.0.3",
-              "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
-              "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
-            }
-          }
-        },
-        "safe-buffer": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
-          "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
-        },
         "statuses": {
           "version": "1.4.0",
           "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
           "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
         }
       }
     },
     "express-session": {
       "version": "1.15.6",
       "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz",
       "integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==",
       "requires": {
         "cookie": "0.3.1",
         "cookie-signature": "1.0.6",
         "crc": "3.4.4",
         "debug": "2.6.9",
         "depd": "~1.1.1",
         "on-headers": "~1.0.1",
         "parseurl": "~1.3.2",
         "uid-safe": "~2.1.5",
         "utils-merge": "1.0.1"
       }
     },
     "extend": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
-      "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
     },
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
       "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
     },
     "fast-deep-equal": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
     },
     "fast-json-stable-stringify": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
       "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
     },
     "fd-slicer": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
-      "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+      "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
       "requires": {
         "pend": "~1.2.0"
       }
     },
     "finalhandler": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
       "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
       "requires": {
         "debug": "2.6.9",
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "on-finished": "~2.3.0",
         "parseurl": "~1.3.2",
         "statuses": "~1.4.0",
         "unpipe": "~1.0.0"
       },
       "dependencies": {
         "statuses": {
           "version": "1.4.0",
           "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
           "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
         }
       }
     },
     "forever-agent": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
       "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
     },
     "form-data": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
-      "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
       "requires": {
         "asynckit": "^0.4.0",
-        "combined-stream": "1.0.6",
+        "combined-stream": "^1.0.6",
         "mime-types": "^2.1.12"
       }
     },
     "forwarded": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
       "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
     },
     "fresh": {
       "version": "0.5.2",
       "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
       "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
     },
     "function-bind": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
       "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
     },
     "getpass": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
       "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
       "requires": {
         "assert-plus": "^1.0.0"
       }
     },
     "har-schema": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
       "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
     },
     "har-validator": {
-      "version": "5.0.3",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
-      "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
       "requires": {
-        "ajv": "^5.1.0",
+        "ajv": "^6.5.5",
         "har-schema": "^2.0.0"
       }
     },
     "has": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
       "requires": {
         "function-bind": "^1.1.1"
       }
     },
     "http-errors": {
       "version": "1.6.3",
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
       "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
       "requires": {
         "depd": "~1.1.2",
         "inherits": "2.0.3",
         "setprototypeof": "1.1.0",
         "statuses": ">= 1.4.0 < 2"
       }
     },
     "http-signature": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
       "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
       "requires": {
         "assert-plus": "^1.0.0",
         "jsprim": "^1.2.2",
         "sshpk": "^1.7.0"
       }
     },
     "iconv-lite": {
       "version": "0.4.23",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
       "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
       "requires": {
         "safer-buffer": ">= 2.1.2 < 3"
       }
     },
     "inherits": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
     },
     "ipaddr.js": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
-      "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
+      "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
     },
     "is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
       "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
     },
     "is-expression": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
       "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
       "requires": {
         "acorn": "~4.0.2",
         "object-assign": "^4.0.1"
       },
       "dependencies": {
         "acorn": {
           "version": "4.0.13",
           "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
           "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
         }
       }
     },
     "is-promise": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
       "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
     },
     "is-regex": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
       "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
       "requires": {
         "has": "^1.0.1"
       }
     },
     "is-typedarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
     },
     "isstream": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
     },
     "js-stringify": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
       "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
     },
     "jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
-      "optional": true
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
     },
     "json-schema": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
       "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
     },
     "json-schema-traverse": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
     },
     "json-stringify-safe": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
     },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
       "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
       "requires": {
         "assert-plus": "1.0.0",
         "extsprintf": "1.3.0",
         "json-schema": "0.2.3",
         "verror": "1.10.0"
       }
     },
     "jstransformer": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
       "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
       "requires": {
         "is-promise": "^2.0.0",
         "promise": "^7.0.1"
       }
     },
     "kind-of": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
       "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
       "requires": {
         "is-buffer": "^1.1.5"
       }
     },
     "lazy-cache": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
       "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
     },
     "lockfile": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz",
       "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==",
       "requires": {
         "signal-exit": "^3.0.2"
       }
     },
     "lodash": {
       "version": "4.17.10",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
       "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
     },
     "lodash.isempty": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
       "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4="
     },
     "longest": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
       "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
     },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
     },
     "merge-descriptors": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
       "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
     },
     "method-override": {
-      "version": "2.3.10",
-      "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz",
-      "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz",
+      "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==",
       "requires": {
-        "debug": "2.6.9",
+        "debug": "3.1.0",
         "methods": "~1.1.2",
         "parseurl": "~1.3.2",
         "vary": "~1.1.2"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
       }
     },
     "methods": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
       "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
     },
     "mime": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
       "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
     },
     "mime-db": {
       "version": "1.33.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
       "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
     },
     "mime-types": {
       "version": "2.1.18",
       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
       "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
       "requires": {
         "mime-db": "~1.33.0"
       }
     },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
       "requires": {
         "brace-expansion": "^1.1.7"
       }
     },
     "morgan": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz",
-      "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=",
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
+      "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
       "requires": {
         "basic-auth": "~2.0.0",
         "debug": "2.6.9",
-        "depd": "~1.1.1",
+        "depd": "~1.1.2",
         "on-finished": "~2.3.0",
         "on-headers": "~1.0.1"
       }
     },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
     "multiparty": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.1.4.tgz",
-      "integrity": "sha1-TJbcvcEeP3kX4WFeZAtLUCK+ZP0=",
-      "requires": {
-        "fd-slicer": "~1.0.1",
-        "safe-buffer": "5.1.2"
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.1.tgz",
+      "integrity": "sha512-AvESCnNoQlZiOfP9R4mxN8M9csy2L16EIbWIkt3l4FuGti9kXBS8QVzlfyg4HEnarJhrzZilgNFlZtqmoiAIIA==",
+      "requires": {
+        "fd-slicer": "1.1.0",
+        "http-errors": "~1.7.0",
+        "safe-buffer": "5.1.2",
+        "uid-safe": "2.1.5"
+      },
+      "dependencies": {
+        "http-errors": {
+          "version": "1.7.2",
+          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+          "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+          "requires": {
+            "depd": "~1.1.2",
+            "inherits": "2.0.3",
+            "setprototypeof": "1.1.1",
+            "statuses": ">= 1.5.0 < 2",
+            "toidentifier": "1.0.0"
+          }
+        },
+        "setprototypeof": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+          "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+        }
       }
     },
     "nano": {
-      "version": "6.4.4",
-      "resolved": "https://registry.npmjs.org/nano/-/nano-6.4.4.tgz",
-      "integrity": "sha512-7sldMrZI1ZH8QE29PnzohxLfR67WNVzMKLa7EMl3x9Hr+0G+YpOUCq50qZ9G66APrjcb0Of2BTOZLNBCutZGag==",
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/nano/-/nano-8.0.0.tgz",
+      "integrity": "sha512-NpBzSEkfQ6Amc1n0ySa8OiOtz7Q6F/kT9YUARmcJFwSiX8scKU4V6riP8Q80lQR5A8VT5h3Mk2+YZJHQ65IfxA==",
       "requires": {
-        "cloudant-follow": "~0.17.0",
+        "@types/request": "^2.47.1",
+        "cloudant-follow": "^0.18.0",
         "debug": "^2.2.0",
         "errs": "^0.3.2",
         "lodash.isempty": "^4.4.0",
         "request": "^2.85.0"
       }
     },
     "negotiator": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
       "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
     },
     "oauth-sign": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
-      "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
     },
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
     },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
       "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
       "requires": {
         "ee-first": "1.1.1"
       }
     },
     "on-headers": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
       "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c="
     },
     "parseurl": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
       "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
     },
     "path-parse": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
       "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME="
     },
     "path-to-regexp": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
     },
     "pend": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
       "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
     },
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
     },
     "promise": {
       "version": "7.3.1",
       "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
       "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
       "requires": {
         "asap": "~2.0.3"
       }
     },
     "proxy-addr": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
-      "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==",
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
+      "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
       "requires": {
         "forwarded": "~0.1.2",
-        "ipaddr.js": "1.6.0"
+        "ipaddr.js": "1.8.0"
       }
     },
+    "psl": {
+      "version": "1.1.31",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
+      "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
+    },
     "pug": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.3.tgz",
       "integrity": "sha1-ccuoJTfJWl6rftBGluQiH1Oqh44=",
       "requires": {
         "pug-code-gen": "^2.0.1",
         "pug-filters": "^3.1.0",
         "pug-lexer": "^4.0.0",
         "pug-linker": "^3.0.5",
         "pug-load": "^2.0.11",
         "pug-parser": "^5.0.0",
         "pug-runtime": "^2.0.4",
         "pug-strip-comments": "^1.0.3"
       }
     },
     "pug-attrs": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.3.tgz",
       "integrity": "sha1-owlflw5kFR972tlX7vVftdeQXRU=",
       "requires": {
         "constantinople": "^3.0.1",
         "js-stringify": "^1.0.1",
         "pug-runtime": "^2.0.4"
       }
     },
     "pug-code-gen": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.1.tgz",
       "integrity": "sha1-CVHsgyJddNjPxHan+Zolm199BQw=",
       "requires": {
         "constantinople": "^3.0.1",
         "doctypes": "^1.1.0",
         "js-stringify": "^1.0.1",
         "pug-attrs": "^2.0.3",
         "pug-error": "^1.3.2",
         "pug-runtime": "^2.0.4",
         "void-elements": "^2.0.1",
         "with": "^5.0.0"
       }
     },
     "pug-error": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.2.tgz",
       "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY="
     },
     "pug-filters": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.0.tgz",
       "integrity": "sha1-JxZVVbwEwjbkqisDZiRt+gIbYm4=",
       "requires": {
         "clean-css": "^4.1.11",
         "constantinople": "^3.0.1",
         "jstransformer": "1.0.0",
         "pug-error": "^1.3.2",
         "pug-walk": "^1.1.7",
         "resolve": "^1.1.6",
         "uglify-js": "^2.6.1"
       }
     },
     "pug-lexer": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.0.0.tgz",
       "integrity": "sha1-IQwYRX7y4XYCQnQMXmR715TOwng=",
       "requires": {
         "character-parser": "^2.1.1",
         "is-expression": "^3.0.0",
         "pug-error": "^1.3.2"
       }
     },
     "pug-linker": {
       "version": "3.0.5",
       "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.5.tgz",
       "integrity": "sha1-npp65ABWgtAn3uuWsAD4juuDoC8=",
       "requires": {
         "pug-error": "^1.3.2",
         "pug-walk": "^1.1.7"
       }
     },
     "pug-load": {
       "version": "2.0.11",
       "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.11.tgz",
       "integrity": "sha1-5kjlftET/iwfRdV4WOorrWvAFSc=",
       "requires": {
         "object-assign": "^4.1.0",
         "pug-walk": "^1.1.7"
       }
     },
     "pug-parser": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.0.tgz",
       "integrity": "sha1-45Stmz/KkxI5QK/4hcBuRKt+aOQ=",
       "requires": {
         "pug-error": "^1.3.2",
         "token-stream": "0.0.1"
       }
     },
     "pug-runtime": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.4.tgz",
       "integrity": "sha1-4XjhvaaKsujArPybztLFT9iM61g="
     },
     "pug-strip-comments": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz",
       "integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=",
       "requires": {
         "pug-error": "^1.3.2"
       }
     },
     "pug-walk": {
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.7.tgz",
       "integrity": "sha1-wA1cUSi6xYBr7BXSt+fNq+QlMfM="
     },
     "punycode": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
     },
     "qs": {
       "version": "6.5.2",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
       "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
     },
     "random-bytes": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
       "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
     },
     "range-parser": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
       "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
     },
     "raw-body": {
       "version": "2.3.3",
       "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
       "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
       "requires": {
         "bytes": "3.0.0",
         "http-errors": "1.6.3",
         "iconv-lite": "0.4.23",
         "unpipe": "1.0.0"
       }
     },
     "recursive-readdir": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
       "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==",
       "requires": {
         "minimatch": "3.0.4"
       }
     },
     "regenerator-runtime": {
       "version": "0.11.1",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
       "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
     },
     "repeat-string": {
       "version": "1.6.1",
       "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
       "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
     },
     "request": {
-      "version": "2.87.0",
-      "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
-      "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
       "requires": {
         "aws-sign2": "~0.7.0",
-        "aws4": "^1.6.0",
+        "aws4": "^1.8.0",
         "caseless": "~0.12.0",
-        "combined-stream": "~1.0.5",
-        "extend": "~3.0.1",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
         "forever-agent": "~0.6.1",
-        "form-data": "~2.3.1",
-        "har-validator": "~5.0.3",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.0",
         "http-signature": "~1.2.0",
         "is-typedarray": "~1.0.0",
         "isstream": "~0.1.2",
         "json-stringify-safe": "~5.0.1",
-        "mime-types": "~2.1.17",
-        "oauth-sign": "~0.8.2",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
         "performance-now": "^2.1.0",
-        "qs": "~6.5.1",
-        "safe-buffer": "^5.1.1",
-        "tough-cookie": "~2.3.3",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.4.3",
         "tunnel-agent": "^0.6.0",
-        "uuid": "^3.1.0"
+        "uuid": "^3.3.2"
+      },
+      "dependencies": {
+        "mime-db": {
+          "version": "1.38.0",
+          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
+          "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
+        },
+        "mime-types": {
+          "version": "2.1.22",
+          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
+          "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
+          "requires": {
+            "mime-db": "~1.38.0"
+          }
+        }
       }
     },
     "resolve": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
       "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
       "requires": {
         "path-parse": "^1.0.5"
       }
     },
     "right-align": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
       "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
       "requires": {
         "align-text": "^0.1.1"
       }
     },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
       "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "send": {
       "version": "0.16.2",
       "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
       "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
       "requires": {
         "debug": "2.6.9",
         "depd": "~1.1.2",
         "destroy": "~1.0.4",
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "etag": "~1.8.1",
         "fresh": "0.5.2",
         "http-errors": "~1.6.2",
         "mime": "1.4.1",
         "ms": "2.0.0",
         "on-finished": "~2.3.0",
         "range-parser": "~1.2.0",
         "statuses": "~1.4.0"
       },
       "dependencies": {
         "statuses": {
           "version": "1.4.0",
           "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
           "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
         }
       }
     },
     "serve-favicon": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz",
       "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=",
       "requires": {
         "etag": "~1.8.1",
         "fresh": "0.5.2",
         "ms": "2.1.1",
         "parseurl": "~1.3.2",
         "safe-buffer": "5.1.1"
       },
       "dependencies": {
         "ms": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
           "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
         },
         "safe-buffer": {
           "version": "5.1.1",
           "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
           "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
         }
       }
     },
     "serve-static": {
       "version": "1.13.2",
       "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
       "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
       "requires": {
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "parseurl": "~1.3.2",
         "send": "0.16.2"
       }
     },
     "setprototypeof": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
       "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
     },
     "signal-exit": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
       "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
     },
     "source-map": {
       "version": "0.5.7",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
       "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
     },
     "sshpk": {
-      "version": "1.14.2",
-      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
-      "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
       "requires": {
         "asn1": "~0.2.3",
         "assert-plus": "^1.0.0",
         "bcrypt-pbkdf": "^1.0.0",
         "dashdash": "^1.12.0",
         "ecc-jsbn": "~0.1.1",
         "getpass": "^0.1.1",
         "jsbn": "~0.1.0",
         "safer-buffer": "^2.0.2",
         "tweetnacl": "~0.14.0"
       }
     },
     "statuses": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
       "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
     },
     "to-fast-properties": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
       "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
     },
+    "toidentifier": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+    },
     "token-stream": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz",
       "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo="
     },
     "tough-cookie": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
-      "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
       "requires": {
+        "psl": "^1.1.24",
         "punycode": "^1.4.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+        }
       }
     },
     "tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
       "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
       "requires": {
         "safe-buffer": "^5.0.1"
       }
     },
     "tweetnacl": {
       "version": "0.14.5",
       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
-      "optional": true
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
     },
     "type-is": {
       "version": "1.6.16",
       "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
       "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
       "requires": {
         "media-typer": "0.3.0",
         "mime-types": "~2.1.18"
       }
     },
     "uglify-js": {
       "version": "2.8.29",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
       "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
       "requires": {
         "source-map": "~0.5.1",
         "uglify-to-browserify": "~1.0.0",
         "yargs": "~3.10.0"
       }
     },
     "uglify-to-browserify": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
       "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
       "optional": true
     },
     "uid-safe": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
       "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
       "requires": {
         "random-bytes": "~1.0.0"
       }
     },
     "unpipe": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
       "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
     },
+    "uri-js": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
     "utils-merge": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
       "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
     },
     "uuid": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
       "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
     },
     "vary": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
       "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
     },
     "verror": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
       "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
       "requires": {
         "assert-plus": "^1.0.0",
         "core-util-is": "1.0.2",
         "extsprintf": "^1.2.0"
       }
     },
     "void-elements": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
       "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
     },
     "window-size": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
       "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
     },
     "with": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz",
       "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=",
       "requires": {
         "acorn": "^3.1.0",
         "acorn-globals": "^3.0.0"
       }
     },
     "wordwrap": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
       "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
     },
     "yargs": {
       "version": "3.10.0",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
       "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
       "requires": {
         "camelcase": "^1.0.2",
         "cliui": "^2.1.0",
         "decamelize": "^1.0.0",
         "window-size": "0.1.0"
       }
     }
   }
 }
diff --git a/desuto-viewer/Desuto-webviewer/package.json b/desuto-viewer/Desuto-webviewer/package.json
index 6e4a02c..e6cd461 100644
--- a/desuto-viewer/Desuto-webviewer/package.json
+++ b/desuto-viewer/Desuto-webviewer/package.json
@@ -1,24 +1,24 @@
 {
   "name": "slide-viewer-backend",
   "version": "0.0.2",
   "private": true,
   "scripts": {
     "start": "node app.js"
   },
   "dependencies": {
-    "body-parser": "^1.16.0",
-    "connect-multiparty": "^2.0.0",
-    "cookie-parser": "^1.4.3",
+    "body-parser": "^1.18.3",
+    "connect-multiparty": "^2.2.0",
+    "cookie-parser": "^1.4.4",
     "errorhandler": "^1.5.0",
-    "express": "^4.14.0",
-    "express-session": "^1.14.2",
-    "lockfile": "^1.0.3",
-    "method-override": "^2.3.7",
-    "morgan": "^1.7.0",
-    "nano": "^6.2.0",
-    "pug": "^2.0.0-beta6",
-    "recursive-readdir": "^2.1.1",
-    "serve-favicon": "^2.3.2",
-    "serve-static": "^1.11.1"
+    "express": "^4.16.4",
+    "express-session": "^1.15.6",
+    "lockfile": "^1.0.4",
+    "method-override": "^3.0.0",
+    "morgan": "^1.9.1",
+    "nano": "^8.0.0",
+    "pug": "^2.0.3",
+    "recursive-readdir": "^2.2.2",
+    "serve-favicon": "^2.5.0",
+    "serve-static": "^1.13.2"
   }
 }
diff --git a/desuto-viewer/Desuto-webviewer/public/js/app-main.js b/desuto-viewer/Desuto-webviewer/public/js/app-main.js
index 575e8b9..87dbfe5 100644
--- a/desuto-viewer/Desuto-webviewer/public/js/app-main.js
+++ b/desuto-viewer/Desuto-webviewer/public/js/app-main.js
@@ -1,686 +1,685 @@
 /* jshint undef: false, curly: false, latedef: false */
 
 /* Document ready execution */
 
 /* Global "annotating" mode variable */
 var annotating = false;
 
 /* Default variables */
 var initialOpacity = 33;
 var tooltipOffset = 10;
 var refMag = 40;
 var oneXZoom;
 var pixelsPerMeter = 0.5e6;
 
 /* State variables */
 var saving = false;
 var aboveShape = false;
 
 /* SVG Editor variables */
 var canvas;
 
 var svgEditContainer = "<div id='svg-overlay'>" +
     "<div id='svg_editor'>" +
     "<div id='workarea'>" +
     "<div id='svgcanvas'>" +
     "</div>" +
     "</div>" +
     "</div>" +
     "</div>";
 
 /* Define OpenSeadragon options */
 var options = {
     id: "openseadragon",
     prefixUrl: "img/",
     showNavigator: true,
     zoomInButton: "zoom-in",
     zoomOutButton: "zoom-out",
     homeButton: "home",
     autoHideControls: false,
     minZoomImageRatio: 1,
     maxZoomPixelRatio: 1
 };
 
 /* Get currently edited image */
 var image = getParameterByName("image");
 
 /* If image is null, get default */
 if (image === null || image === "")
     image = defaultImage;
 
 /* ID for CouchDB */
 var id = image + "-" + annotator;
 
 /* Viewer */
 var viewer;
 
 /* Viewer imagingHelper */
 var imagingHelper;
 
 /* Viewr inputHook */
 var inputHook;
 
 /* Feature viewer variables */
 var featureViewer;
 var featureImagingHelper;
 
 /* Synchronize the 2 OpenSeadragon viewers */
 function onImageViewChanged(event) {
     if (typeof featureImagingHelper !== "undefined" && featureImagingHelper !== null)
         featureImagingHelper.setView(event.viewportWidth, event.viewportHeight, event.viewportCenter, true);
 }
 
 /* Set Image for viewer */
 function setImage(image, options) {
     options.tileSources = config.iipDeepZoomBaseURL + config.iipImageDir + image + config.iipSuffix;
 }
 
 /* Set Overlay for viewer */
 function setOverlay(image, options) {
-    options.tileSources = config.iipDeepZoomBaseURL + image + config.iipSuffix;
+    options.tileSources = config.iipDeepZoomBaseURL + config.iipOverlaysDir + image + config.iipSuffix;
 }
 
 /* Toggle shorthand method */
 function toggle() {
     annotating = !annotating;
     toggleEditor(annotating);
 }
 
 /* Toggle the editor between annotation and exploration */
 function toggleEditor(annotating) {
 
     if (annotating) {
 
         // Highlight the fact that we are in annotating mode
         $("#openseadragon-container").css("border", "1px solid black");
         $("#locks").show();
 
         // Deselect any currently highlighted element
         $("svg g *[id^='svg_']").each(function(index, shape) {
             $(shape).attr("stroke-opacity", "1.0");
         });
         aboveShape = false;
         $("#annotation-tooltip").hide();
 
         // Toggle toolbars
         $("#tools-viewer").hide();
         $("#tools-drawing-container").show();
 
         $("#toggle-annotation").text("Stop Annotating");
 
         // Enable context menu
         $('#workarea').enableContextMenu();
 
         // Disable mouse navigation & navigator on viewer
         viewer.setMouseNavEnabled(false);
         $("#openseadragon .navigator").css("pointer-events", "none");
 
         // Select freehand tool
         $('#tool_fhpath').trigger('click');
 
     } else {
 
         // Remove border and locks
         $("#openseadragon-container").css("border", "1px solid transparent");
         $("#locks").hide();
 
 
         // Toggle toolbars
         $("#tools-drawing-container").hide();
         $("#tools-viewer").show();
 
         $("#toggle-annotation").text("Start Annotating");
 
         // Disable context menu
         $('#workarea').disableContextMenu();
 
         // Enable mouse navigation & navigator on viewer
         viewer.setMouseNavEnabled(true);
         $("#openseadragon .navigator").css("pointer-events", "all");
 
         // Stop annotating specific steps
         // Pathologists only
         if (typeof svgEditor !== 'undefined')
             svgEditor.canvas.clearSelection();
     }
 
     if (typeof change !== "undefined" && change)
         annotating = !annotating;
 }
 
 // Synchronize with a remote CouchDB
 function sync() {
     var opts = {
         live: true,
         retry: true
     };
 
     // Sync DBs
     db.sync(remoteCouch, opts)
         .on('error', function(err) {
             syncError();
         })
         .on('change', function(info) {
-            console.log('pouchdb - changed : ' + info)
+            console.log('pouchdb - changed : ' + JSON.stringify(info.change.docs.map((doc) => doc._id)))
         })
         .on('denied', function(info) {
             console.log('pouchdb - denied : ' + info)
         }).
         on('paused', function(err){
             $("#sync").hide();
-            console.log('pouchdb - paused : ' + err)
+            console.log('pouchdb - paused : ' + ((err) ? err : 'ok'))
         }).
         on('active', function(){
             //$("#sync").show();
             console.log('pouchdb - active')
         }).
         on('complete', function(info){
             console.log('pouchdb - complete : ' + info)
         });
 
     // Listen to changes
     db.changes({
         since: 'now',
         live: true,
         include_docs: true
     }).on('change', function(change){
 
             var reload = change.id == id;
 
             // Check if patch preview needs to be reloaded
             var reloadPatch = false
-            if(typeof canvas.getSelectedElems() !== 'undefined' && canvas.getSelectedElems().length === 1) {
+            if(typeof canvas !== 'undefined' && typeof canvas.getSelectedElems() !== 'undefined' && canvas.getSelectedElems().length === 1) {
                 var selectedElement = svgEditor.canvas.getSelectedElems()[0];
                 var changedElement = null;
 
                 if(typeof selectedElement !== "undefined" && selectedElement != null){
                     change.doc.annotations.forEach(function(annotation){
                         if(selectedElement.id == annotation.attr.id) {
                             changedElement = annotation;
                         }
                     });
 
                     if(changedElement !== null){
-
                         if(!compareObjects(changedElement, getJSONforSVG(selectedElement)))
                             reloadPatch = true;
                     }
                 }
 
             }
 
             if(reload){
                 $("#sync").show();
                 loadAnnotations(reloadPatch);
             }
         }
     );
 }
 
 // There was some form or error syncing to remote
 function syncError() {
     console.log('error syncing db');
 }
 
 // Load annotations
 function loadAnnotations(reloadPatch) {
 
     // Remove elements
     //$("#svgcontent g [id]").remove();
 
     if (!saving) {
         // Get image's annotations
         db.get(id).then(function(doc) {
 
             if(doc.annotations){
                 // Global method
                 var annotations = doc.annotations;
                 var annotationIDs = [];
                 // Add / Update the SVG element
                 $.each(annotations, function(index, annotation) {
 
                     // Only load annotations of current user
                     if(annotation.attr["histopatho-annotator"] === annotator){
                         // Pathologists only
                         if(typeof(canvas) !== 'undefined'){
                             canvas.addSvgElementFromJson(annotation);
                         } else {
                             if( $("#svgcontent g #" + annotation.attr.id).length > 0){
                                 addSvgElementFromJsonSimple(annotation);
                             }else{
                                 $("#svgcontent g").append(addSvgElementFromJsonSimple(annotation));
                             }
                         }
                     }
 
                     annotationIDs.push(annotation.attr.id);
 
                     // Load annotation text
-                    if(typeof canvas.getSelectedElems() !== 'undefined' && canvas.getSelectedElems().length === 1){
+                    if(typeof canvas !== 'undefined' && typeof canvas.getSelectedElems() !== 'undefined' && canvas.getSelectedElems().length === 1){
                         var selectedElement = svgEditor.canvas.getSelectedElems()[0];
                         if(typeof selectedElement !== 'undefined'
                             && selectedElement !== null
                             && selectedElement.getAttribute('id') === annotation.attr.id){
 
                             $("#annotation").val(annotation.attr["histopatho-annotation"]);
 
                             if(typeof reloadPatch !== "undefined" && reloadPatch)
                                 loadPatchPreview(selectedElement);
                         }
                     }
                 });
 
                 // Remove deleted elements
                 $("#svgcontent g [id]").each(function(index) {
                     var isThere = _.contains(annotationIDs, $(this).attr("id"));
                     if (!isThere) {
                         $(this).remove();
                     }
                 });
                 // Update selectors
 
                 // Pathologists only
-                if(typeof(canvas) !== 'undefined'
-                    && canvas.selectorManager !== null
-                    && canvas.selectorManager.selectors !== null){
-                    $.each(canvas.selectorManager.selectors, function(index, element) {
-                        if(element.selectedElement !== null)
-                            element.resize();
-                    });
+                if(typeof(canvas) !== 'undefined' &&
+                    canvas.selectorManager !== null &&
+                    canvas.selectorManager.selectors !== null){
+                        $.each(canvas.selectorManager.selectors, function(index, element) {
+                            if(element.selectedElement !== null)
+                                element.resize();
+                        });
                 }
 
             }
         }).catch(function(err) {
             console.log(err.stack);
         });
     }
 
     saving = false;
 }
 
 // Destroy feature viewer
 function destroyFeatureViewer() {
     if (typeof featureViewer !== "undefined" && featureViewer !== null) {
         featureViewer.destroy();
         featureViewer = null;
     }
 }
 
 // Load feature viewer
 function loadFeatureViewer(feature) {
 
     // Activate correct LI
     $(".feature-link").removeClass("active");
     $(".feature-link[href=#" + feature + "]").addClass("active");
 
     // Did we select "none" ?
     if (feature === "none") {
         destroyFeatureViewer();
         return;
     }
 
     // Feature viewer options
     var featureOptions = {
         id: "openseadragon-features",
         prefixUrl: "img/",
         showNavigator: false,
         showNavigationControl: false
     };
 
     // Set image
     featureImageName = config.iipOverlaysDir + getParameterByName('image') + '/' + feature + config.iipFeatureImageExtension;
     setOverlay(featureImageName, featureOptions);
 
     // Destroy existing viewer
     destroyFeatureViewer();
 
     // Create viewer
     featureViewer = new OpenSeadragon(featureOptions);
     featureImagingHelper = featureViewer.activateImagingHelper();
 
     // Raise image changed event on open
     featureViewer.addHandler('open', function() {
         imagingHelper._raiseImageViewChanged();
         updateOpacity($("#feature-opacity").val());
     });
 }
 
 // Update opacity and label
 function updateOpacity(opacity) {
     $("#feature-opacity-label").text(opacity + "%");
     $("#openseadragon-features").css("opacity", opacity / 100);
 }
 
 // Position tooltip next to cursor
 function positionTooltip(x, y) {
     $("#annotation-tooltip").css({
         left: x + tooltipOffset + 'px',
         top: y + tooltipOffset + 'px'
     });
 }
 
 /* Set the width of the side navigation to 250px */
 function openNav(menu) {
     $('#' + menu).css('width', '300px');
 }
 
 /* Set the width of the side navigation to 0 */
 function closeNav(menu) {
     $('#' + menu).css('width', '0');
 }
 
 // On mouse hover over SVG element, log it to console
 $(document).on("mouseenter", "svg g *", function(event) {
     if (!annotating) {
         $(event.target).attr("stroke-opacity", "0.7");
         aboveShape = true;
 
         var annotationText = $(event.target).attr("histopatho-annotation");
         var annotatorText  = "(" + $(event.target).attr("histopatho-annotator") + ")";
 
         var textToShow;
 
         if (annotationText !== null && annotationText !== "") {
             textToShow = annotationText + "<br />" + annotatorText;
         }else{
             textToShow = annotatorText;
         }
 
         $("#annotation-tooltip div").html(textToShow);
         $("#annotation-tooltip").show();
 
         positionTooltip(event.pageX, event.pageY);
     }
 });
 
 // On mouse leave from SVG element
 $(document).on("mouseleave", "svg g *", function(event) {
     if (!annotating) {
         $(event.target).attr("stroke-opacity", "1.0");
         aboveShape = false;
         $("#annotation-tooltip").hide();
     }
 });
 
 // On mouse move inside of and SVG element, show annotation
 $(document).on("mousemove", "svg g *", function(event) {
     if (!annotating && aboveShape) {
         positionTooltip(event.pageX, event.pageY);
         //console.log('positioning at ' + event.pageX + " - " + event.pageY);
     }
 });
 
 /* Document ready */
 $(function() {
 
     var svgNode, overlay;
 
     // Current caption
     var currentCaption;
 
     // Set right image
     setImage(image, options);
 
     // Activate viewer
     viewer = new OpenSeadragon(options);
 
     // Enable imaging helper on viewer
     imagingHelper = viewer.activateImagingHelper({
         onImageViewChanged: onImageViewChanged
     });
 
     // Fancybox
     $("[data-fancybox]").fancybox({
         iframe:{
             scrolling : 'yes'
         }
     });
 
     /* WTF - This was used to manually sort entries for the user tests */
     /*
     $("#imagesets div:first ul").html(
         $("#imagesets div:first ul li").sort(function(a,b){
             return $(a).find("a").text() > $(b).find("a").text();
         })
     );
     */
 
     // Activate correct LI
     $(".image-link").removeClass("active");
     $(".image-link[href='?image=" + image + "']").addClass("active");
 
     // Zoom @ 1x button
     $("#zoom-1x").click(function(event) {
         viewer.viewport.zoomTo(1 * oneXZoom, null, false);
         event.preventDefault();
     });
 
     // Zoom @ 5x button
     $("#zoom-5x").click(function(event) {
         viewer.viewport.zoomTo(5 * oneXZoom, null, false);
         event.preventDefault();
     });
 
     // Zoom @ 10x button
     $("#zoom-10x").click(function(event) {
         viewer.viewport.zoomTo(10 * oneXZoom, null, false);
         event.preventDefault();
     });
 
     // Zoom @ 20x button
     $("#zoom-20x").click(function(event) {
         viewer.viewport.zoomTo(20 * oneXZoom, null, false);
         event.preventDefault();
     });
 
     // Zoom @ 40x button
     $("#zoom-40x").click(function(event) {
         viewer.viewport.zoomTo(40 * oneXZoom, null, false);
         event.preventDefault();
     });
 
     // Drop down menu
     if($('select[name="normal"]').length > 0)
         $('select[name="normal"]').on('change', function() {
             svgEditor.canvas.setColor('stroke', $('select[name="normal"]').val(), false);
 
             var e = document.getElementById("normal");
             var userAnnotation = e.options[e.selectedIndex].text;
             $('#annotation').val(userAnnotation);
             //console.log(userAnnotation);
         });
 
     // Caption update
     $('#annotation').change(function(event){
 
         var annotationAttribute = 'histopatho-annotation';
 
         console.log('new value : ' + $(this).val());
 
         var svgElement = svgEditor.canvas.getSelectedElems()[0];
 
         if($(svgElement).attr(annotationAttribute) !== $(this).val().replace( /\n/g, '<br \\>')){
             $(svgElement).attr(annotationAttribute, $(this).val().replace( /\n/g, '<br \\>'));
         }
 
         svgEditor.canvas.runExtensions('elementChanged', {
             elems: [svgElement]
         });
     });
 
     /*
      // Init color picker
      // Pathologists only
      if($('select[name="colorpicker"]').length > 0)
      $('select[name="colorpicker"]').simplecolorpicker({
      theme: 'fontawesome'
      }).on('change', function() {
      svgEditor.canvas.setColor('stroke', $('select[name="colorpicker"]').val(), false);
      });
      */
 
     // On annotation button click, toggle
     $("#toggle-annotation").click(function(event) {
         toggle();
         $("#annotation-menu button").blur();
     });
 
     // On ESC, toggle annotation mode
     $(document).bind('keydown', 'esc', function(event) {
         if (typeof svgEditor !== 'undefined') {
             toggle();
         }
         event.preventDefault();
         return false;
     });
 
     // On feature link click, load feature overlay
     $(".feature-link").click(function(event) {
         loadFeatureViewer($(this).attr("href").substr(1));
     });
 
     // On feature opacity slide, adjust opacity of feature viewer
     $("#feature-opacity").on("input", function() {
         var value = $(this).val();
         updateOpacity(value);
     });
 
     // Initialize the opacity slider
     $("#feature-opacity").val(initialOpacity);
     updateOpacity($("#feature-opacity").val());
 
     // Accordion
     $("#imagesets").accordion({
         collapsible: true,
         heightStyle: 'content'
     });
 
     $("#imagesets").on("accordioncreate", function (event, ui) {
         var i = 0;
         $("#imagesets h3").each(function(index, element){
             if(image.startsWith($(element).text())){
                 console.log('we are in ' + $(element).text());
                 $("#imagesets").accordion("option", "active", i);
             }
             i++;
         });
     });
 
     // When viewer is opened
     viewer.addHandler('open', function() {
 
         // Zoom on selected portion (if given)
         if(getParameterByName("x") !== "" && getParameterByName("y") !== "" && getParameterByName("size") !== ""){
 
             var x = parseInt(getParameterByName("x"));
             var y = parseInt(getParameterByName("y"));
             var size = parseInt(getParameterByName("size"));
 
             var upperLeft = new OpenSeadragon.Point(x, y);
             var viewerPoint = viewer.viewport.imageToViewportCoordinates(upperLeft);
             var viewerSize  = viewer.viewport.imageToViewportCoordinates(new OpenSeadragon.Point(size, size));
 
             // TODO - Fix once x & y are in the correct order!
             viewer.viewport.fitBoundsWithConstraints(new OpenSeadragon.Rect(viewerPoint.y, viewerPoint.x, viewerSize.x, viewerSize.y), false);
         }
 
         // Check when image is fully loaded
         viewer.world.getItemAt(0).addHandler('fully-loaded-change', function(event){
             console.log('fully loaded : ' + event.fullyLoaded);
             if (remoteCouch) {
                 setTimeout(function(){
                     sync();
                 }, 1000);
             }
             viewer.world.getItemAt(0).removeAllHandlers('fully-loaded-change');
         });
 
         // Calculate the reference zoom for the magnification buttons (10x, 20x, 40x, ...)
         // Get slide magnification (objective-power)
         var originalImageName = count(image, '\\.') === 2 ? image.substr(0, image.lastIndexOf('.')) : image;
 
         $.get(config.slideMagURL + config.iipUploadedDir + encodeURIComponent(originalImageName), function (data) {
             if(data && data !== "None"){
                 var magnification = parseInt(data);
                 refMag = magnification;
                 oneXZoom = calculateReferenceZoom(viewer.viewport, viewer.world, magnification);
 
                 // Hide unused buttons
                 if(magnification < 40)
                     $("#zoom-40x").hide();
 
                 if(magnification < 20)
                     $("#zoom-20x").hide();
 
                 if(magnification < 10)
                     $("#zoom-10x").hide();
 
                 if(magnification < 5)
                     $("#zoom-5x").hide();
             }else{
                 oneXZoom = calculateReferenceZoom(viewer.viewport, viewer.world, refMag, false);
                 console.log("failed getting magnification level");
             }
-        }).fail(function(e){
+        }, 'text').fail(function(e){
             oneXZoom = calculateReferenceZoom(viewer.viewport, viewer.world, refMag, false);
             console.log("failed getting magnification level");
         });
 
         // Initialize editor (if available)
         // Pathologists only
         if (typeof svgEditor !== 'undefined') {
 
             // Append SVG overlay element to SVG canvas element
             $("#openseadragon > .openseadragon-container > .openseadragon-canvas").append(svgEditContainer);
 
             // Initialize the SVG editor
             svgEditor.init();
             canvas = svgEditor.canvas;
 
             // Add SVG overlay to OSD (based on SVG-edit element)
             overlay = viewer.svgOverlay(document.getElementById("svgroot"));
 
             // Trigger color dropdown "change"
             $('select[name="normal"]').trigger('change');
         } else {
             overlay = viewer.svgOverlay();
         }
 
         svgNode = overlay.node();
 
         // If there is a remote CouchDB instance, start syncing
         loadAnnotations();
 
         // Put editor in correct mode
         toggleEditor(annotating);
 
         // If feature is not null, load the second viewer
         if (location.hash) {
             loadFeatureViewer(location.hash.substr(1));
         }
     });
 
     // Get slide scale (pixels per meter)
     var originalImageName = count(image, '\\.') === 2 ? image.substr(0, image.lastIndexOf('.')) : image;
 
     $.get(config.slidePxMURL + config.iipUploadedDir + encodeURIComponent(originalImageName), function(data){
 
         if(data !== null && data !== "None")
             pixelsPerMeter = parseFloat(data);
 
         // Add scale bar to OSD
         viewer.scalebar({
             pixelsPerMeter: pixelsPerMeter
         });
 
         viewer.scalebar();
 
-    }).fail(function(){
+    }, 'text').fail(function(){
         console.log("failed to get pixels per meter")
     });
 
 });
 
 function count(s1, letter) {
     return ( s1.match( RegExp(letter,'g') ) || [] ).length;
 }
diff --git a/desuto-viewer/Desuto-webviewer/public/js/config/config.js b/desuto-viewer/Desuto-webviewer/public/js/config/config.js
index 6cb304b..f701a4a 100644
--- a/desuto-viewer/Desuto-webviewer/public/js/config/config.js
+++ b/desuto-viewer/Desuto-webviewer/public/js/config/config.js
@@ -1,31 +1,26 @@
 var config = {
 
     // CouchDB
-    couchDBRootURL: 'http://pathology.hevs.ch:5984/',
+    couchDBRootURL: 'http://localhost/couchdb/',
     couchDBName: 'histopatho',
 
     // Hosts & URLs
-    retrievalInterfaceRootURL: 'http://fast.hevs.ch/desutoret/',
-    paradiseRootURL: 'http://faster.hevs.ch/',
-    iipRootURL: 'http://pathology.hevs.ch/iipsrv/iipsrv.fcgi',
-    slidePropertiesRootURL: 'http://pathology.hevs.ch/',
+    iipRootURL: 'http://localhost/iipsrv/iipsrv.fcgi',
+    slidePropertiesRootURL: 'http://localhost/',
 
     // IIP
-    iipBaseDir: '/mnt/nas2/results/IntermediateResults/Desuto/SlideViewerData/',
+    iipBaseDir: '/slideviewerdata/',
     iipFeatureImageExtension: '.tif',
     iipSuffix: '.dzi',
     iipPatchSize: 224,
-}
-
-// ParaDISE
-config.globalSearchURL = config.paradiseRootURL + 'ParaDISEWSKhresmoi/resources/searchResource/searchImages';
+};
 
 // IIP
 config.iipDeepZoomBaseURL = config.iipRootURL + '?DeepZoom=';
 config.iipUploadedDir = config.iipBaseDir + 'uploaded/';
 config.iipImageDir = config.iipBaseDir + "converted/";
 config.iipOverlaysDir = config.iipBaseDir + 'overlays/';
 
 // Slide properties
 config.slidePxMURL  = config.slidePropertiesRootURL + 'slide_properties/pixels_m/';
 config.slideMagURL  = config.slidePropertiesRootURL + 'slide_properties/magnification/';
\ No newline at end of file
diff --git a/desuto-viewer/Desuto-webviewer/public/js/config/config.js b/desuto-viewer/Desuto-webviewer/public/js/config/config.tmpl.js
similarity index 50%
copy from desuto-viewer/Desuto-webviewer/public/js/config/config.js
copy to desuto-viewer/Desuto-webviewer/public/js/config/config.tmpl.js
index 6cb304b..c31428c 100644
--- a/desuto-viewer/Desuto-webviewer/public/js/config/config.js
+++ b/desuto-viewer/Desuto-webviewer/public/js/config/config.tmpl.js
@@ -1,31 +1,26 @@
 var config = {
 
     // CouchDB
-    couchDBRootURL: 'http://pathology.hevs.ch:5984/',
-    couchDBName: 'histopatho',
+    couchDBRootURL: '$COUCHDB_ROOT_URL',
+    couchDBName: '$COUCHDB_DB_NAME',
 
     // Hosts & URLs
-    retrievalInterfaceRootURL: 'http://fast.hevs.ch/desutoret/',
-    paradiseRootURL: 'http://faster.hevs.ch/',
-    iipRootURL: 'http://pathology.hevs.ch/iipsrv/iipsrv.fcgi',
-    slidePropertiesRootURL: 'http://pathology.hevs.ch/',
+    iipRootURL: '$IIP_ROOT_URL',
+    slidePropertiesRootURL: '$SLIDEPROPS_ROOT_URL',
 
     // IIP
-    iipBaseDir: '/mnt/nas2/results/IntermediateResults/Desuto/SlideViewerData/',
+    iipBaseDir: '$WSI_BASE_DIR',
     iipFeatureImageExtension: '.tif',
     iipSuffix: '.dzi',
     iipPatchSize: 224,
-}
-
-// ParaDISE
-config.globalSearchURL = config.paradiseRootURL + 'ParaDISEWSKhresmoi/resources/searchResource/searchImages';
+};
 
 // IIP
 config.iipDeepZoomBaseURL = config.iipRootURL + '?DeepZoom=';
 config.iipUploadedDir = config.iipBaseDir + 'uploaded/';
 config.iipImageDir = config.iipBaseDir + "converted/";
 config.iipOverlaysDir = config.iipBaseDir + 'overlays/';
 
 // Slide properties
 config.slidePxMURL  = config.slidePropertiesRootURL + 'slide_properties/pixels_m/';
 config.slideMagURL  = config.slidePropertiesRootURL + 'slide_properties/magnification/';
\ No newline at end of file
diff --git a/desuto-viewer/Desuto-webviewer/public/js/polyfills/pathseg.js b/desuto-viewer/Desuto-webviewer/public/js/polyfills/pathseg.js
index f4974d0..7beeeb3 100644
--- a/desuto-viewer/Desuto-webviewer/public/js/polyfills/pathseg.js
+++ b/desuto-viewer/Desuto-webviewer/public/js/polyfills/pathseg.js
@@ -1,818 +1,858 @@
 // SVGPathSeg API polyfill
 // https://github.com/progers/pathseg
 //
 // This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
 // SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
 // changes which were implemented in Firefox 43 and Chrome 46.
 
 (function() { "use strict";
     if (!("SVGPathSeg" in window)) {
         // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
         window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
             this.pathSegType = type;
             this.pathSegTypeAsLetter = typeAsLetter;
             this._owningPathSegList = owningPathSegList;
         }
 
         window.SVGPathSeg.prototype.classname = "SVGPathSeg";
 
         window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
         window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
         window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
         window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
         window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
         window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
         window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
         window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
         window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
         window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
         window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
         window.SVGPathSeg.PATHSEG_ARC_REL = 11;
         window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
         window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
         window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
         window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
         window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
         window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
         window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
         window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
 
         // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
         window.SVGPathSeg.prototype._segmentChanged = function() {
             if (this._owningPathSegList)
                 this._owningPathSegList.segmentChanged(this);
         }
 
         window.SVGPathSegClosePath = function(owningPathSegList) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList);
         }
         window.SVGPathSegClosePath.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegClosePath.prototype.toString = function() { return "[object SVGPathSegClosePath]"; }
         window.SVGPathSegClosePath.prototype._asPathString = function() { return this.pathSegTypeAsLetter; }
         window.SVGPathSegClosePath.prototype.clone = function() { return new window.SVGPathSegClosePath(undefined); }
 
         window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList);
             this._x = x;
             this._y = y;
         }
         window.SVGPathSegMovetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegMovetoAbs.prototype.toString = function() { return "[object SVGPathSegMovetoAbs]"; }
         window.SVGPathSegMovetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
         window.SVGPathSegMovetoAbs.prototype.clone = function() { return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y); }
         Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList);
             this._x = x;
             this._y = y;
         }
         window.SVGPathSegMovetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegMovetoRel.prototype.toString = function() { return "[object SVGPathSegMovetoRel]"; }
         window.SVGPathSegMovetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
         window.SVGPathSegMovetoRel.prototype.clone = function() { return new window.SVGPathSegMovetoRel(undefined, this._x, this._y); }
         Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList);
             this._x = x;
             this._y = y;
         }
         window.SVGPathSegLinetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegLinetoAbs.prototype.toString = function() { return "[object SVGPathSegLinetoAbs]"; }
         window.SVGPathSegLinetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
         window.SVGPathSegLinetoAbs.prototype.clone = function() { return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y); }
         Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList);
             this._x = x;
             this._y = y;
         }
         window.SVGPathSegLinetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegLinetoRel.prototype.toString = function() { return "[object SVGPathSegLinetoRel]"; }
         window.SVGPathSegLinetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
         window.SVGPathSegLinetoRel.prototype.clone = function() { return new window.SVGPathSegLinetoRel(undefined, this._x, this._y); }
         Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoCubicAbs = function(owningPathSegList, x, y, x1, y1, x2, y2) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList);
             this._x = x;
             this._y = y;
             this._x1 = x1;
             this._y1 = y1;
             this._x2 = x2;
             this._y2 = y2;
         }
         window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoCubicAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicAbs]"; }
         window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoCubicAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
         Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoCubicRel = function(owningPathSegList, x, y, x1, y1, x2, y2) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList);
             this._x = x;
             this._y = y;
             this._x1 = x1;
             this._y1 = y1;
             this._x2 = x2;
             this._y2 = y2;
         }
         window.SVGPathSegCurvetoCubicRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoCubicRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicRel]"; }
         window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoCubicRel.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
         Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoQuadraticAbs = function(owningPathSegList, x, y, x1, y1) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList);
             this._x = x;
             this._y = y;
             this._x1 = x1;
             this._y1 = y1;
         }
         window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticAbs]"; }
         window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoQuadraticRel = function(owningPathSegList, x, y, x1, y1) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList);
             this._x = x;
             this._y = y;
             this._x1 = x1;
             this._y1 = y1;
         }
         window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticRel]"; }
         window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegArcAbs = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList);
             this._x = x;
             this._y = y;
             this._r1 = r1;
             this._r2 = r2;
             this._angle = angle;
             this._largeArcFlag = largeArcFlag;
             this._sweepFlag = sweepFlag;
         }
         window.SVGPathSegArcAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegArcAbs.prototype.toString = function() { return "[object SVGPathSegArcAbs]"; }
         window.SVGPathSegArcAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
         window.SVGPathSegArcAbs.prototype.clone = function() { return new window.SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
         Object.defineProperty(window.SVGPathSegArcAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcAbs.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcAbs.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcAbs.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegArcRel = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList);
             this._x = x;
             this._y = y;
             this._r1 = r1;
             this._r2 = r2;
             this._angle = angle;
             this._largeArcFlag = largeArcFlag;
             this._sweepFlag = sweepFlag;
         }
         window.SVGPathSegArcRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegArcRel.prototype.toString = function() { return "[object SVGPathSegArcRel]"; }
         window.SVGPathSegArcRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
         window.SVGPathSegArcRel.prototype.clone = function() { return new window.SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
         Object.defineProperty(window.SVGPathSegArcRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcRel.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcRel.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcRel.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcRel.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegArcRel.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList);
             this._x = x;
         }
         window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalAbs]"; }
         window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
         window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function() { return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x); }
         Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList);
             this._x = x;
         }
         window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegLinetoHorizontalRel.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalRel]"; }
         window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
         window.SVGPathSegLinetoHorizontalRel.prototype.clone = function() { return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x); }
         Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList);
             this._y = y;
         }
         window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegLinetoVerticalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalAbs]"; }
         window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
         window.SVGPathSegLinetoVerticalAbs.prototype.clone = function() { return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y); }
         Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList);
             this._y = y;
         }
         window.SVGPathSegLinetoVerticalRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegLinetoVerticalRel.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalRel]"; }
         window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
         window.SVGPathSegLinetoVerticalRel.prototype.clone = function() { return new window.SVGPathSegLinetoVerticalRel(undefined, this._y); }
         Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoCubicSmoothAbs = function(owningPathSegList, x, y, x2, y2) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList);
             this._x = x;
             this._y = y;
             this._x2 = x2;
             this._y2 = y2;
         }
         window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothAbs]"; }
         window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoCubicSmoothRel = function(owningPathSegList, x, y, x2, y2) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList);
             this._x = x;
             this._y = y;
             this._x2 = x2;
             this._y2 = y2;
         }
         window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothRel]"; }
         window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoQuadraticSmoothAbs = function(owningPathSegList, x, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList);
             this._x = x;
             this._y = y;
         }
         window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothAbs]"; }
         window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         window.SVGPathSegCurvetoQuadraticSmoothRel = function(owningPathSegList, x, y) {
             window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList);
             this._x = x;
             this._y = y;
         }
         window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
         window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothRel]"; }
         window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
         window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
         Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
 
         // Add createSVGPathSeg* functions to window.SVGPathElement.
         // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-Interfacewindow.SVGPathElement.
         window.SVGPathElement.prototype.createSVGPathSegClosePath = function() { return new window.SVGPathSegClosePath(undefined); }
         window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) { return new window.SVGPathSegMovetoAbs(undefined, x, y); }
         window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) { return new window.SVGPathSegMovetoRel(undefined, x, y); }
         window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) { return new window.SVGPathSegLinetoAbs(undefined, x, y); }
         window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) { return new window.SVGPathSegLinetoRel(undefined, x, y); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(x, y, x1, y1, x2, y2) { return new window.SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(x, y, x1, y1, x2, y2) { return new window.SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(x, y, x1, y1) { return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(x, y, x1, y1) { return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }
         window.SVGPathElement.prototype.createSVGPathSegArcAbs = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new window.SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
         window.SVGPathElement.prototype.createSVGPathSegArcRel = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new window.SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
         window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(x) { return new window.SVGPathSegLinetoHorizontalAbs(undefined, x); }
         window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(x) { return new window.SVGPathSegLinetoHorizontalRel(undefined, x); }
         window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(y) { return new window.SVGPathSegLinetoVerticalAbs(undefined, y); }
         window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(y) { return new window.SVGPathSegLinetoVerticalRel(undefined, y); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(x, y, x2, y2) { return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(x, y, x2, y2) { return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(x, y) { return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }
         window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(x, y) { return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }
+
+        if (!("getPathSegAtLength" in window.SVGPathElement.prototype)) {
+            // Add getPathSegAtLength to SVGPathElement.
+            // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
+            // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
+            window.SVGPathElement.prototype.getPathSegAtLength = function(distance) {
+                if (distance === undefined || !isFinite(distance))
+                    throw "Invalid arguments.";
+
+                var measurementElement = document.createElementNS("http://www.w3.org/2000/svg", "path");
+                measurementElement.setAttribute("d", this.getAttribute("d"));
+                var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;
+
+                // If the path is empty, return 0.
+                if (lastPathSegment <= 0)
+                    return 0;
+
+                do {
+                    measurementElement.pathSegList.removeItem(lastPathSegment);
+                    if (distance > measurementElement.getTotalLength())
+                        break;
+                    lastPathSegment--;
+                } while (lastPathSegment > 0);
+                return lastPathSegment;
+            }
+        }
     }
 
-    if (!("SVGPathSegList" in window)) {
+    // Checking for SVGPathSegList in window checks for the case of an implementation without the
+    // SVGPathSegList API.
+    // The second check for appendItem is specific to Firefox 59+ which removed only parts of the
+    // SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API
+    // so the polyfill data (i.e., _list) is used throughout.
+    if (!("SVGPathSegList" in window) || !("appendItem" in window.SVGPathSegList.prototype)) {
         // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
         window.SVGPathSegList = function(pathElement) {
             this._pathElement = pathElement;
             this._list = this._parsePath(this._pathElement.getAttribute("d"));
 
             // Use a MutationObserver to catch changes to the path's "d" attribute.
             this._mutationObserverConfig = { "attributes": true, "attributeFilter": ["d"] };
             this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
             this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
         }
 
         window.SVGPathSegList.prototype.classname = "SVGPathSegList";
 
         Object.defineProperty(window.SVGPathSegList.prototype, "numberOfItems", {
             get: function() {
                 this._checkPathSynchronizedToList();
                 return this._list.length;
             },
             enumerable: true
         });
 
+        // The length property was not specified but was in Firefox 58.
+        Object.defineProperty(window.SVGPathSegList.prototype, "length", {
+            get: function() {
+                this._checkPathSynchronizedToList();
+                return this._list.length;
+            },
+            enumerable: true
+        });
+
         // Add the pathSegList accessors to window.SVGPathElement.
         // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
         Object.defineProperty(window.SVGPathElement.prototype, "pathSegList", {
             get: function() {
                 if (!this._pathSegList)
                     this._pathSegList = new window.SVGPathSegList(this);
                 return this._pathSegList;
             },
             enumerable: true
         });
         // FIXME: The following are not implemented and simply return window.SVGPathElement.pathSegList.
         Object.defineProperty(window.SVGPathElement.prototype, "normalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
         Object.defineProperty(window.SVGPathElement.prototype, "animatedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
         Object.defineProperty(window.SVGPathElement.prototype, "animatedNormalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
 
         // Process any pending mutations to the path element and update the list as needed.
         // This should be the first call of all public functions and is needed because
         // MutationObservers are not synchronous so we can have pending asynchronous mutations.
         window.SVGPathSegList.prototype._checkPathSynchronizedToList = function() {
             this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
         }
 
         window.SVGPathSegList.prototype._updateListFromPathMutations = function(mutationRecords) {
             if (!this._pathElement)
                 return;
             var hasPathMutations = false;
             mutationRecords.forEach(function(record) {
                 if (record.attributeName == "d")
                     hasPathMutations = true;
             });
             if (hasPathMutations)
                 this._list = this._parsePath(this._pathElement.getAttribute("d"));
         }
 
         // Serialize the list and update the path's 'd' attribute.
         window.SVGPathSegList.prototype._writeListToPath = function() {
             this._pathElementMutationObserver.disconnect();
             this._pathElement.setAttribute("d", window.SVGPathSegList._pathSegArrayAsString(this._list));
             this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
         }
 
         // When a path segment changes the list needs to be synchronized back to the path element.
         window.SVGPathSegList.prototype.segmentChanged = function(pathSeg) {
             this._writeListToPath();
         }
 
         window.SVGPathSegList.prototype.clear = function() {
             this._checkPathSynchronizedToList();
 
             this._list.forEach(function(pathSeg) {
                 pathSeg._owningPathSegList = null;
             });
             this._list = [];
             this._writeListToPath();
         }
 
         window.SVGPathSegList.prototype.initialize = function(newItem) {
             this._checkPathSynchronizedToList();
 
             this._list = [newItem];
             newItem._owningPathSegList = this;
             this._writeListToPath();
             return newItem;
         }
 
         window.SVGPathSegList.prototype._checkValidIndex = function(index) {
             if (isNaN(index) || index < 0 || index >= this.numberOfItems)
                 throw "INDEX_SIZE_ERR";
         }
 
         window.SVGPathSegList.prototype.getItem = function(index) {
             this._checkPathSynchronizedToList();
 
             this._checkValidIndex(index);
             return this._list[index];
         }
 
         window.SVGPathSegList.prototype.insertItemBefore = function(newItem, index) {
             this._checkPathSynchronizedToList();
 
             // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
             if (index > this.numberOfItems)
                 index = this.numberOfItems;
             if (newItem._owningPathSegList) {
                 // SVG2 spec says to make a copy.
                 newItem = newItem.clone();
             }
             this._list.splice(index, 0, newItem);
             newItem._owningPathSegList = this;
             this._writeListToPath();
             return newItem;
         }
 
         window.SVGPathSegList.prototype.replaceItem = function(newItem, index) {
             this._checkPathSynchronizedToList();
 
             if (newItem._owningPathSegList) {
                 // SVG2 spec says to make a copy.
                 newItem = newItem.clone();
             }
             this._checkValidIndex(index);
             this._list[index] = newItem;
             newItem._owningPathSegList = this;
             this._writeListToPath();
             return newItem;
         }
 
         window.SVGPathSegList.prototype.removeItem = function(index) {
             this._checkPathSynchronizedToList();
 
             this._checkValidIndex(index);
             var item = this._list[index];
             this._list.splice(index, 1);
             this._writeListToPath();
             return item;
         }
 
         window.SVGPathSegList.prototype.appendItem = function(newItem) {
             this._checkPathSynchronizedToList();
 
             if (newItem._owningPathSegList) {
                 // SVG2 spec says to make a copy.
                 newItem = newItem.clone();
             }
             this._list.push(newItem);
             newItem._owningPathSegList = this;
             // TODO: Optimize this to just append to the existing attribute.
             this._writeListToPath();
             return newItem;
         }
 
         window.SVGPathSegList._pathSegArrayAsString = function(pathSegArray) {
             var string = "";
             var first = true;
             pathSegArray.forEach(function(pathSeg) {
                 if (first) {
                     first = false;
                     string += pathSeg._asPathString();
                 } else {
                     string += " " + pathSeg._asPathString();
                 }
             });
             return string;
         }
 
         // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
         window.SVGPathSegList.prototype._parsePath = function(string) {
             if (!string || string.length == 0)
                 return [];
 
             var owningPathSegList = this;
 
             var Builder = function() {
                 this.pathSegList = [];
             }
 
             Builder.prototype.appendSegment = function(pathSeg) {
                 this.pathSegList.push(pathSeg);
             }
 
             var Source = function(string) {
                 this._string = string;
                 this._currentIndex = 0;
                 this._endIndex = this._string.length;
                 this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
 
                 this._skipOptionalSpaces();
             }
 
             Source.prototype._isCurrentSpace = function() {
                 var character = this._string[this._currentIndex];
                 return character <= " " && (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f");
             }
 
             Source.prototype._skipOptionalSpaces = function() {
                 while (this._currentIndex < this._endIndex && this._isCurrentSpace())
                     this._currentIndex++;
                 return this._currentIndex < this._endIndex;
             }
 
             Source.prototype._skipOptionalSpacesOrDelimiter = function() {
                 if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ",")
                     return false;
                 if (this._skipOptionalSpaces()) {
                     if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") {
                         this._currentIndex++;
                         this._skipOptionalSpaces();
                     }
                 }
                 return this._currentIndex < this._endIndex;
             }
 
             Source.prototype.hasMoreData = function() {
                 return this._currentIndex < this._endIndex;
             }
 
             Source.prototype.peekSegmentType = function() {
                 var lookahead = this._string[this._currentIndex];
                 return this._pathSegTypeFromChar(lookahead);
             }
 
             Source.prototype._pathSegTypeFromChar = function(lookahead) {
                 switch (lookahead) {
-                case "Z":
-                case "z":
-                    return window.SVGPathSeg.PATHSEG_CLOSEPATH;
-                case "M":
-                    return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
-                case "m":
-                    return window.SVGPathSeg.PATHSEG_MOVETO_REL;
-                case "L":
-                    return window.SVGPathSeg.PATHSEG_LINETO_ABS;
-                case "l":
-                    return window.SVGPathSeg.PATHSEG_LINETO_REL;
-                case "C":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
-                case "c":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
-                case "Q":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
-                case "q":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
-                case "A":
-                    return window.SVGPathSeg.PATHSEG_ARC_ABS;
-                case "a":
-                    return window.SVGPathSeg.PATHSEG_ARC_REL;
-                case "H":
-                    return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
-                case "h":
-                    return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
-                case "V":
-                    return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
-                case "v":
-                    return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
-                case "S":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
-                case "s":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
-                case "T":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
-                case "t":
-                    return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
-                default:
-                    return window.SVGPathSeg.PATHSEG_UNKNOWN;
+                    case "Z":
+                    case "z":
+                        return window.SVGPathSeg.PATHSEG_CLOSEPATH;
+                    case "M":
+                        return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
+                    case "m":
+                        return window.SVGPathSeg.PATHSEG_MOVETO_REL;
+                    case "L":
+                        return window.SVGPathSeg.PATHSEG_LINETO_ABS;
+                    case "l":
+                        return window.SVGPathSeg.PATHSEG_LINETO_REL;
+                    case "C":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
+                    case "c":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
+                    case "Q":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
+                    case "q":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
+                    case "A":
+                        return window.SVGPathSeg.PATHSEG_ARC_ABS;
+                    case "a":
+                        return window.SVGPathSeg.PATHSEG_ARC_REL;
+                    case "H":
+                        return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
+                    case "h":
+                        return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
+                    case "V":
+                        return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
+                    case "v":
+                        return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
+                    case "S":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
+                    case "s":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
+                    case "T":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
+                    case "t":
+                        return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
+                    default:
+                        return window.SVGPathSeg.PATHSEG_UNKNOWN;
                 }
             }
 
             Source.prototype._nextCommandHelper = function(lookahead, previousCommand) {
                 // Check for remaining coordinates in the current command.
                 if ((lookahead == "+" || lookahead == "-" || lookahead == "." || (lookahead >= "0" && lookahead <= "9")) && previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH) {
                     if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS)
                         return window.SVGPathSeg.PATHSEG_LINETO_ABS;
                     if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL)
                         return window.SVGPathSeg.PATHSEG_LINETO_REL;
                     return previousCommand;
                 }
                 return window.SVGPathSeg.PATHSEG_UNKNOWN;
             }
 
             Source.prototype.initialCommandIsMoveTo = function() {
                 // If the path is empty it is still valid, so return true.
                 if (!this.hasMoreData())
                     return true;
                 var command = this.peekSegmentType();
                 // Path must start with moveTo.
                 return command == window.SVGPathSeg.PATHSEG_MOVETO_ABS || command == window.SVGPathSeg.PATHSEG_MOVETO_REL;
             }
 
             // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
             // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
             Source.prototype._parseNumber = function() {
                 var exponent = 0;
                 var integer = 0;
                 var frac = 1;
                 var decimal = 0;
                 var sign = 1;
                 var expsign = 1;
 
                 var startIndex = this._currentIndex;
 
                 this._skipOptionalSpaces();
 
                 // Read the sign.
                 if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+")
                     this._currentIndex++;
                 else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") {
                     this._currentIndex++;
                     sign = -1;
                 }
 
                 if (this._currentIndex == this._endIndex || ((this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") && this._string.charAt(this._currentIndex) != "."))
-                    // The first character of a number must be one of [0-9+-.].
+                // The first character of a number must be one of [0-9+-.].
                     return undefined;
 
                 // Read the integer part, build right-to-left.
                 var startIntPartIndex = this._currentIndex;
                 while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
                     this._currentIndex++; // Advance to first non-digit.
 
                 if (this._currentIndex != startIntPartIndex) {
                     var scanIntPartIndex = this._currentIndex - 1;
                     var multiplier = 1;
                     while (scanIntPartIndex >= startIntPartIndex) {
                         integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0");
                         multiplier *= 10;
                     }
                 }
 
                 // Read the decimals.
                 if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") {
                     this._currentIndex++;
 
                     // There must be a least one digit following the .
                     if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
                         return undefined;
                     while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
                         frac *= 10;
                         decimal += (this._string.charAt(this._currentIndex) - "0") / frac;
                         this._currentIndex += 1;
                     }
                 }
 
                 // Read the exponent part.
                 if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") && (this._string.charAt(this._currentIndex + 1) != "x" && this._string.charAt(this._currentIndex + 1) != "m")) {
                     this._currentIndex++;
 
                     // Read the sign of the exponent.
                     if (this._string.charAt(this._currentIndex) == "+") {
                         this._currentIndex++;
                     } else if (this._string.charAt(this._currentIndex) == "-") {
                         this._currentIndex++;
                         expsign = -1;
                     }
 
                     // There must be an exponent.
                     if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
                         return undefined;
 
                     while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
                         exponent *= 10;
                         exponent += (this._string.charAt(this._currentIndex) - "0");
                         this._currentIndex++;
                     }
                 }
 
                 var number = integer + decimal;
                 number *= sign;
 
                 if (exponent)
                     number *= Math.pow(10, expsign * exponent);
 
                 if (startIndex == this._currentIndex)
                     return undefined;
 
                 this._skipOptionalSpacesOrDelimiter();
 
                 return number;
             }
 
             Source.prototype._parseArcFlag = function() {
                 if (this._currentIndex >= this._endIndex)
                     return undefined;
                 var flag = false;
                 var flagChar = this._string.charAt(this._currentIndex++);
                 if (flagChar == "0")
                     flag = false;
                 else if (flagChar == "1")
                     flag = true;
                 else
                     return undefined;
 
                 this._skipOptionalSpacesOrDelimiter();
                 return flag;
             }
 
             Source.prototype.parseSegment = function() {
                 var lookahead = this._string[this._currentIndex];
                 var command = this._pathSegTypeFromChar(lookahead);
                 if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
                     // Possibly an implicit command. Not allowed if this is the first command.
                     if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN)
                         return null;
                     command = this._nextCommandHelper(lookahead, this._previousCommand);
                     if (command == window.SVGPathSeg.PATHSEG_UNKNOWN)
                         return null;
                 } else {
                     this._currentIndex++;
                 }
 
                 this._previousCommand = command;
 
                 switch (command) {
-                case window.SVGPathSeg.PATHSEG_MOVETO_REL:
-                    return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
-                    return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_LINETO_REL:
-                    return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_LINETO_ABS:
-                    return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
-                    return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
-                    return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
-                    return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
-                    return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_CLOSEPATH:
-                    this._skipOptionalSpaces();
-                    return new window.SVGPathSegClosePath(owningPathSegList);
-                case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
-                    var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
-                case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
-                    var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
-                case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
-                    var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
-                case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
-                    var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
-                case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
-                    var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
-                case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
-                    var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
-                case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
-                    return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
-                    return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
-                case window.SVGPathSeg.PATHSEG_ARC_REL:
-                    var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
-                case window.SVGPathSeg.PATHSEG_ARC_ABS:
-                    var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
-                    return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
-                default:
-                    throw "Unknown path seg type."
+                    case window.SVGPathSeg.PATHSEG_MOVETO_REL:
+                        return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
+                        return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_LINETO_REL:
+                        return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_LINETO_ABS:
+                        return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
+                        return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
+                        return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
+                        return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
+                        return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_CLOSEPATH:
+                        this._skipOptionalSpaces();
+                        return new window.SVGPathSegClosePath(owningPathSegList);
+                    case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
+                        var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+                    case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
+                        var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+                    case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+                        var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
+                    case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+                        var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
+                    case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
+                        var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
+                    case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
+                        var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
+                    case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+                        return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+                        return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+                    case window.SVGPathSeg.PATHSEG_ARC_REL:
+                        var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+                    case window.SVGPathSeg.PATHSEG_ARC_ABS:
+                        var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
+                        return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+                    default:
+                        throw "Unknown path seg type."
                 }
             }
 
             var builder = new Builder();
             var source = new Source(string);
 
             if (!source.initialCommandIsMoveTo())
                 return [];
             while (source.hasMoreData()) {
                 var pathSeg = source.parseSegment();
                 if (!pathSeg)
                     return [];
                 builder.appendSegment(pathSeg);
             }
 
             return builder.pathSegList;
         }
     }
-}());
+}());
\ No newline at end of file
diff --git a/desuto-viewer/Desuto-webviewer/public/js/svg-edit/svgutils.js b/desuto-viewer/Desuto-webviewer/public/js/svg-edit/svgutils.js
index df4af39..911458b 100644
--- a/desuto-viewer/Desuto-webviewer/public/js/svg-edit/svgutils.js
+++ b/desuto-viewer/Desuto-webviewer/public/js/svg-edit/svgutils.js
@@ -1,703 +1,703 @@
 /*globals $, svgedit, unescape, DOMParser, ActiveXObject, getStrokedBBox*/
 /*jslint vars: true, eqeq: true, bitwise: true, continue: true, forin: true*/
 /**
  * Package: svgedit.utilities
  *
  * Licensed under the MIT License
  *
  * Copyright(c) 2010 Alexis Deveria
  * Copyright(c) 2010 Jeff Schiller
  */
 
 // Dependencies:
 // 1) jQuery
 // 2) browser.js
 // 3) svgtransformlist.js
 // 4) units.js
 
 (function(undef) {'use strict';
 
 if (!svgedit.utilities) {
 	svgedit.utilities = {};
 }
 
 // Constants
 
 // String used to encode base64.
 var KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
 var NS = svgedit.NS;
 
 // Much faster than running getBBox() every time
 var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use';
 var visElems_arr = visElems.split(',');
 //var hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath';
 
 var editorContext_ = null;
 var domdoc_ = null;
 var domcontainer_ = null;
 var svgroot_ = null;
 
 svgedit.utilities.init = function(editorContext) {
 	editorContext_ = editorContext;
 	domdoc_ = editorContext.getDOMDocument();
 	domcontainer_ = editorContext.getDOMContainer();
 	svgroot_ = editorContext.getSVGRoot();
 };
 
 // Function: svgedit.utilities.toXml
 // Converts characters in a string to XML-friendly entities.
 //
 // Example: '&' becomes '&amp;'
 //
 // Parameters:
 // str - The string to be converted
 //
 // Returns:
 // The converted string
 svgedit.utilities.toXml = function(str) {
 	// &apos; is ok in XML, but not HTML
 	// &gt; does not normally need escaping, though it can if within a CDATA expression (and preceded by "]]")
 	return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/, '&#x27;');
 };
 
 // Function: svgedit.utilities.fromXml
 // Converts XML entities in a string to single characters.
 // Example: '&amp;' becomes '&'
 //
 // Parameters:
 // str - The string to be converted
 //
 // Returns:
 // The converted string
 svgedit.utilities.fromXml = function(str) {
 	return $('<p/>').html(str).text();
 };
 
 // This code was written by Tyler Akins and has been placed in the
 // public domain.  It would be nice if you left this header intact.
 // Base64 code from Tyler Akins -- http://rumkin.com
 
 // schiller: Removed string concatenation in favour of Array.join() optimization,
 //				also precalculate the size of the array needed.
 
 // Function: svgedit.utilities.encode64
 // Converts a string to base64
 svgedit.utilities.encode64 = function(input) {
 	// base64 strings are 4/3 larger than the original string
 	input = svgedit.utilities.encodeUTF8(input); // convert non-ASCII characters
 	// input = svgedit.utilities.convertToXMLReferences(input);
 	if (window.btoa) {
 		return window.btoa(input); // Use native if available
     }
     var output = [];
 	output.length = Math.floor( (input.length + 2) / 3 ) * 4;
 	var chr1, chr2, chr3;
 	var enc1, enc2, enc3, enc4;
 	var i = 0, p = 0;
 
 	do {
 		chr1 = input.charCodeAt(i++);
 		chr2 = input.charCodeAt(i++);
 		chr3 = input.charCodeAt(i++);
 
 		enc1 = chr1 >> 2;
 		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
 		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
 		enc4 = chr3 & 63;
 
 		if (isNaN(chr2)) {
 			enc3 = enc4 = 64;
 		} else if (isNaN(chr3)) {
 			enc4 = 64;
 		}
 
 		output[p++] = KEYSTR.charAt(enc1);
 		output[p++] = KEYSTR.charAt(enc2);
 		output[p++] = KEYSTR.charAt(enc3);
 		output[p++] = KEYSTR.charAt(enc4);
 	} while (i < input.length);
 
 	return output.join('');
 };
 
 // Function: svgedit.utilities.decode64
 // Converts a string from base64
 svgedit.utilities.decode64 = function(input) {
 	if(window.atob) {
         return svgedit.utilities.decodeUTF8(window.atob(input));
     }
 	var output = '';
 	var chr1, chr2, chr3 = '';
 	var enc1, enc2, enc3, enc4 = '';
 	var i = 0;
 
 	// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
 	input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
 
 	do {
 		enc1 = KEYSTR.indexOf(input.charAt(i++));
 		enc2 = KEYSTR.indexOf(input.charAt(i++));
 		enc3 = KEYSTR.indexOf(input.charAt(i++));
 		enc4 = KEYSTR.indexOf(input.charAt(i++));
 
 		chr1 = (enc1 << 2) | (enc2 >> 4);
 		chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
 		chr3 = ((enc3 & 3) << 6) | enc4;
 
 		output = output + String.fromCharCode(chr1);
 
 		if (enc3 != 64) {
 			output = output + String.fromCharCode(chr2);
 		}
 		if (enc4 != 64) {
 			output = output + String.fromCharCode(chr3);
 		}
 
 		chr1 = chr2 = chr3 = '';
 		enc1 = enc2 = enc3 = enc4 = '';
 
 	} while (i < input.length);
     return svgedit.utilities.decodeUTF8(output);
 };
 
 svgedit.utilities.decodeUTF8 = function (argString) {
     return decodeURIComponent(escape(argString));
 };
 
 // codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded
 svgedit.utilities.encodeUTF8 = function (argString) {
   return unescape(encodeURIComponent(argString));
 };
 
 // Function: svgedit.utilities.convertToXMLReferences
 // Converts a string to use XML references
 svgedit.utilities.convertToXMLReferences = function(input) {
 	var n,
 		output = '';
 	for (n = 0; n < input.length; n++){
 		var c = input.charCodeAt(n);
 		if (c < 128) {
 			output += input[n];
 		} else if(c > 127) {
 			output += ('&#' + c + ';');
 		}
 	}
 	return output;
 };
 
 // Function: svgedit.utilities.text2xml
 // Cross-browser compatible method of converting a string to an XML tree
 // found this function here: http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f
 svgedit.utilities.text2xml = function(sXML) {
 	if(sXML.indexOf('<svg:svg') >= 0) {
 		sXML = sXML.replace(/<(\/?)svg:/g, '<$1').replace('xmlns:svg', 'xmlns');
 	}
 
 	var out, dXML;
 	try{
 		dXML = (window.DOMParser)?new DOMParser():new ActiveXObject('Microsoft.XMLDOM');
 		dXML.async = false;
 	} catch(e){
 		throw new Error('XML Parser could not be instantiated');
 	}
 	try{
 		if (dXML.loadXML) {
 			out = (dXML.loadXML(sXML)) ? dXML : false;
 		}
 		else {
 			out = dXML.parseFromString(sXML, 'text/xml');
 		}
 	}
 	catch(e2){ throw new Error('Error parsing XML string'); }
 	return out;
 };
 
 // Function: svgedit.utilities.bboxToObj
 // Converts a SVGRect into an object.
 //
 // Parameters:
 // bbox - a SVGRect
 //
 // Returns:
 // An object with properties names x, y, width, height.
 svgedit.utilities.bboxToObj = function(bbox) {
 	return {
 		x: bbox.x,
 		y: bbox.y,
 		width: bbox.width,
 		height: bbox.height
 	};
 };
 
 // Function: svgedit.utilities.walkTree
 // Walks the tree and executes the callback on each element in a top-down fashion
 //
 // Parameters:
 // elem - DOM element to traverse
 // cbFn - Callback function to run on each element
 svgedit.utilities.walkTree = function(elem, cbFn){
 	if (elem && elem.nodeType == 1) {
 		cbFn(elem);
 		var i = elem.childNodes.length;
 		while (i--) {
 			svgedit.utilities.walkTree(elem.childNodes.item(i), cbFn);
 		}
 	}
 };
 
 // Function: svgedit.utilities.walkTreePost
 // Walks the tree and executes the callback on each element in a depth-first fashion
 // TODO: FIXME: Shouldn't this be calling walkTreePost?
 //
 // Parameters:
 // elem - DOM element to traverse
 // cbFn - Callback function to run on each element
 svgedit.utilities.walkTreePost = function(elem, cbFn) {
 	if (elem && elem.nodeType == 1) {
 		var i = elem.childNodes.length;
 		while (i--) {
 			svgedit.utilities.walkTree(elem.childNodes.item(i), cbFn);
 		}
 		cbFn(elem);
 	}
 };
 
 // Function: svgedit.utilities.getUrlFromAttr
 // Extracts the URL from the url(...) syntax of some attributes.
 // Three variants:
 //  * <circle fill="url(someFile.svg#foo)" />
 //  * <circle fill="url('someFile.svg#foo')" />
 //  * <circle fill='url("someFile.svg#foo")' />
 //
 // Parameters:
 // attrVal - The attribute value as a string
 //
 // Returns:
 // String with just the URL, like someFile.svg#foo
 svgedit.utilities.getUrlFromAttr = function(attrVal) {
 	if (attrVal) {
 		// url("#somegrad")
 		if (attrVal.indexOf('url("') === 0) {
 			return attrVal.substring(5, attrVal.indexOf('"',6));
 		}
 		// url('#somegrad')
 		if (attrVal.indexOf("url('") === 0) {
 			return attrVal.substring(5, attrVal.indexOf("'",6));
 		}
 		if (attrVal.indexOf("url(") === 0) {
 			return attrVal.substring(4, attrVal.indexOf(')'));
 		}
 	}
 	return null;
 };
 
 // Function: svgedit.utilities.getHref
 // Returns the given element's xlink:href value
 svgedit.utilities.getHref = function(elem) {
 	return elem.getAttributeNS(NS.XLINK, 'href');
 };
 
 // Function: svgedit.utilities.setHref
 // Sets the given element's xlink:href value
 svgedit.utilities.setHref = function(elem, val) {
 	elem.setAttributeNS(NS.XLINK, 'xlink:href', val);
 };
 
 // Function: findDefs
 //
 // Returns:
 // The document's <defs> element, create it first if necessary
 svgedit.utilities.findDefs = function() {
 	var svgElement = editorContext_.getSVGContent();
 	var defs = svgElement.getElementsByTagNameNS(NS.SVG, 'defs');
 	if (defs.length > 0) {
 		defs = defs[0];
 	} else {
 		defs = svgElement.ownerDocument.createElementNS(NS.SVG, 'defs');
 		if (svgElement.firstChild) {
 			// first child is a comment, so call nextSibling
 			svgElement.insertBefore(defs, svgElement.firstChild.nextSibling);
 		} else {
 			svgElement.appendChild(defs);
 		}
 	}
 	return defs;
 };
 
 // TODO(codedread): Consider moving the next to functions to bbox.js
 
 // Function: svgedit.utilities.getPathBBox
 // Get correct BBox for a path in Webkit
 // Converted from code found here:
 // http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
 //
 // Parameters:
 // path - The path DOM element to get the BBox for
 //
 // Returns:
 // A BBox-like object
 svgedit.utilities.getPathBBox = function(path) {
 	var seglist = path.pathSegList;
 	var tot = seglist.numberOfItems;
 
 	var bounds = [[], []];
 	var start = seglist.getItem(0);
 	var P0 = [start.x , start.y];
 
 	var i;
 	for (i = 0; i < tot; i++) {
 		var seg = seglist.getItem(i);
 
 		if(seg.x === undef) {continue;}
 
 		// Add actual points to limits
 		bounds[0].push(P0[0]);
 		bounds[1].push(P0[1]);
 
 		if (seg.x1) {
 			var P1 = [seg.x1, seg.y1],
 				P2 = [seg.x2, seg.y2],
 				P3 = [seg.x, seg.y];
 
 			var j;
 			for (j = 0; j < 2; j++) {
 
 				var calc = function(t) {
 					return Math.pow(1-t,3) * P0[j]
 						+ 3 * Math.pow(1-t,2) * t * P1[j]
 						+ 3 * (1-t) * Math.pow(t, 2) * P2[j]
 						+ Math.pow(t,3) * P3[j];
 				};
 
 				var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j];
 				var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];
 				var c = 3 * P1[j] - 3 * P0[j];
 
 				if (a == 0) {
 					if (b == 0) {
 						continue;
 					}
 					var t = -c / b;
 					if (0 < t && t < 1) {
 						bounds[j].push(calc(t));
 					}
 					continue;
 				}
 				var b2ac = Math.pow(b,2) - 4 * c * a;
 				if (b2ac < 0) {continue;}
 				var t1 = (-b + Math.sqrt(b2ac))/(2 * a);
 				if (0 < t1 && t1 < 1) {bounds[j].push(calc(t1));}
 				var t2 = (-b - Math.sqrt(b2ac))/(2 * a);
 				if (0 < t2 && t2 < 1) {bounds[j].push(calc(t2));}
 			}
 			P0 = P3;
 		} else {
 			bounds[0].push(seg.x);
 			bounds[1].push(seg.y);
 		}
 	}
 
 	var x = Math.min.apply(null, bounds[0]);
 	var w = Math.max.apply(null, bounds[0]) - x;
 	var y = Math.min.apply(null, bounds[1]);
 	var h = Math.max.apply(null, bounds[1]) - y;
 	return {
 		'x': x,
 		'y': y,
 		'width': w,
 		'height': h
 	};
 };
 
 // Function: groupBBFix
 // Get the given/selected element's bounding box object, checking for
 // horizontal/vertical lines (see issue 717)
 // Note that performance is currently terrible, so some way to improve would
 // be great.
 //
 // Parameters:
 // selected - Container or <use> DOM element
 function groupBBFix(selected) {
 	if(svgedit.browser.supportsHVLineContainerBBox()) {
 		try { return selected.getBBox();} catch(e){}
 	}
 	var ref = $.data(selected, 'ref');
 	var matched = null;
 	var ret, copy;
 
 	if(ref) {
 		copy = $(ref).children().clone().attr('visibility', 'hidden');
 		$(svgroot_).append(copy);
 		matched = copy.filter('line, path');
 	} else {
 		matched = $(selected).find('line, path');
 	}
 
 	var issue = false;
 	if(matched.length) {
 		matched.each(function() {
 			var bb = this.getBBox();
 			if(!bb.width || !bb.height) {
 				issue = true;
 			}
 		});
 		if(issue) {
 			var elems = ref ? copy : $(selected).children();
 			ret = getStrokedBBox(elems); // getStrokedBBox defined in svgcanvas
 		} else {
 			ret = selected.getBBox();
 		}
 	} else {
 		ret = selected.getBBox();
 	}
 	if(ref) {
 		copy.remove();
 	}
 	return ret;
 }
 
 // Function: svgedit.utilities.getBBox
 // Get the given/selected element's bounding box object, convert it to be more
 // usable when necessary
 //
 // Parameters:
 // elem - Optional DOM element to get the BBox for
 svgedit.utilities.getBBox = function(elem) {
 	var selected = elem || editorContext_.geSelectedElements()[0];
 	if (elem.nodeType != 1) {return null;}
 	var ret = null;
 	var elname = selected.nodeName;
 
 	switch ( elname ) {
 	case 'text':
 		if(selected.textContent === '') {
 			selected.textContent = 'a'; // Some character needed for the selector to use.
 			ret = selected.getBBox();
 			selected.textContent = '';
 		} else {
 			try { ret = selected.getBBox();} catch(e){}
 		}
 		break;
 	case 'path':
-                //ROGERMOD - Try using the standard BBox method, the other doesn't work
-                //with a scaled & offset SVG element
+		//ROGERMOD - Try using the standard BBox method, the other doesn't work
+		//with a scaled & offset SVG element
 		/*if(!svgedit.browser.supportsPathBBox()) {
 			ret = svgedit.utilities.getPathBBox(selected);
 		} else {
 			try { ret = selected.getBBox();} catch(e2){}
 		}*/
-                ret = selected.getBBox();
+		ret = selected.getBBox();
 		break;
 	case 'g':
 	case 'a':
 		ret = groupBBFix(selected);
 		break;
 	default:
 
 		if(elname === 'use') {
 			ret = groupBBFix(selected, true);
 		}
 		if(elname === 'use' || ( elname === 'foreignObject' && svgedit.browser.isWebkit() ) ) {
 			if(!ret) {ret = selected.getBBox();}
 			// This is resolved in later versions of webkit, perhaps we should
 			// have a featured detection for correct 'use' behavior?
 			// ——————————
 			//if(!svgedit.browser.isWebkit()) {
 				var bb = {};
 				bb.width = ret.width;
 				bb.height = ret.height;
 				bb.x = ret.x + parseFloat(selected.getAttribute('x')||0);
 				bb.y = ret.y + parseFloat(selected.getAttribute('y')||0);
 				ret = bb;
 			//}
 		} else if(~visElems_arr.indexOf(elname)) {
 			try { ret = selected.getBBox();}
 			catch(e3) {
 				// Check if element is child of a foreignObject
 				var fo = $(selected).closest('foreignObject');
 				if(fo.length) {
 					try {
 						ret = fo[0].getBBox();
 					} catch(e4) {
 						ret = null;
 					}
 				} else {
 					ret = null;
 				}
 			}
 		}
 	}
 	if(ret) {
 		ret = svgedit.utilities.bboxToObj(ret);
 	}
 
 	// get the bounding box from the DOM (which is in that element's coordinate system)
 	return ret;
 };
 
 // Function: svgedit.utilities.getRotationAngle
 // Get the rotation angle of the given/selected DOM element
 //
 // Parameters:
 // elem - Optional DOM element to get the angle for
 // to_rad - Boolean that when true returns the value in radians rather than degrees
 //
 // Returns:
 // Float with the angle in degrees or radians
 svgedit.utilities.getRotationAngle = function(elem, to_rad) {
 	var selected = elem || editorContext_.getSelectedElements()[0];
 	// find the rotation transform (if any) and set it
 	var tlist = svgedit.transformlist.getTransformList(selected);
 	if(!tlist) {return 0;} // <svg> elements have no tlist
 	var N = tlist.numberOfItems;
 	var i;
 	for (i = 0; i < N; ++i) {
 		var xform = tlist.getItem(i);
 		if (xform.type == 4) {
 			return to_rad ? xform.angle * Math.PI / 180.0 : xform.angle;
 		}
 	}
 	return 0.0;
 };
 
 // Function getRefElem
 // Get the reference element associated with the given attribute value
 //
 // Parameters:
 // attrVal - The attribute value as a string
 svgedit.utilities.getRefElem = function(attrVal) {
 	return svgedit.utilities.getElem(svgedit.utilities.getUrlFromAttr(attrVal).substr(1));
 };
 
 // Function: getElem
 // Get a DOM element by ID within the SVG root element.
 //
 // Parameters:
 // id - String with the element's new ID
 if (svgedit.browser.supportsSelectors()) {
 	svgedit.utilities.getElem = function(id) {
 		// querySelector lookup
 		return svgroot_.querySelector('#'+id);
 	};
 } else if (svgedit.browser.supportsXpath()) {
 	svgedit.utilities.getElem = function(id) {
 		// xpath lookup
 		return domdoc_.evaluate(
 			'svg:svg[@id="svgroot"]//svg:*[@id="'+id+'"]',
 			domcontainer_,
 			function() { return svgedit.NS.SVG; },
 			9,
 			null).singleNodeValue;
 	};
 } else {
 	svgedit.utilities.getElem = function(id) {
 		// jQuery lookup: twice as slow as xpath in FF
 		return $(svgroot_).find('[id=' + id + ']')[0];
 	};
 }
 
 // Function: assignAttributes
 // Assigns multiple attributes to an element.
 //
 // Parameters:
 // node - DOM element to apply new attribute values to
 // attrs - Object with attribute keys/values
 // suspendLength - Optional integer of milliseconds to suspend redraw
 // unitCheck - Boolean to indicate the need to use svgedit.units.setUnitAttr
 svgedit.utilities.assignAttributes = function(node, attrs, suspendLength, unitCheck) {
 	if(!suspendLength) {suspendLength = 0;}
 	// Opera has a problem with suspendRedraw() apparently
 	var handle = null;
 	//if (!svgedit.browser.isOpera()) {svgroot_.suspendRedraw(suspendLength);}
 
 	var i;
 	for (i in attrs) {
 		var ns = (i.substr(0,4) === 'xml:' ? NS.XML :
 			i.substr(0,6) === 'xlink:' ? NS.XLINK : null);
 
 		if(ns) {
 			node.setAttributeNS(ns, i, attrs[i]);
 		} else if(!unitCheck) {
 			node.setAttribute(i, attrs[i]);
 		} else {
 			svgedit.units.setUnitAttr(node, i, attrs[i]);
 		}
 	}
 	//if (!svgedit.browser.isOpera()) {svgroot_.unsuspendRedraw(handle);}
 };
 
 // Function: cleanupElement
 // Remove unneeded (default) attributes, makes resulting SVG smaller
 //
 // Parameters:
 // element - DOM element to clean up
 svgedit.utilities.cleanupElement = function(element) {
 	//var handle = svgroot_.suspendRedraw(60);
 	var defaults = {
 		'fill-opacity':1,
 		'stop-opacity':1,
 		'opacity':1,
 		'stroke':'none',
 		'stroke-dasharray':'none',
 		'stroke-linejoin':'miter',
 		'stroke-linecap':'butt',
 		'stroke-opacity':1,
 		'stroke-width':1,
 		'rx':0,
 		'ry':0
 	};
 
 	var attr;
 	for (attr in defaults) {
 		var val = defaults[attr];
 		if(element.getAttribute(attr) == val || attr === "opacity") { //ROGERMOD - Don't save opacity change
 			element.removeAttribute(attr);
 		}
 	}
 
 	//svgroot_.unsuspendRedraw(handle);
 };
 
 // Function: snapToGrid
 // round value to for snapping
 // NOTE: This function did not move to svgutils.js since it depends on curConfig.
 svgedit.utilities.snapToGrid = function(value) {
 	var stepSize = editorContext_.getSnappingStep();
 	var unit = editorContext_.getBaseUnit();
 	if (unit !== "px") {
 		stepSize *= svgedit.units.getTypeMap()[unit];
 	}
 	value = Math.round(value/stepSize)*stepSize;
 	return value;
 };
 
 svgedit.utilities.preg_quote = function (str, delimiter) {
   // From: http://phpjs.org/functions
   return String(str).replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&');
 };
 
 /**
 * @param {string} globalCheck A global which can be used to determine if the script is already loaded
 * @param {array} scripts An array of scripts to preload (in order)
 * @param {function} cb The callback to execute upon load.
 */
 svgedit.utilities.executeAfterLoads = function (globalCheck, scripts, cb) {
 	return function () {
 		var args = arguments;
 		function endCallback () {
 			cb.apply(null, args);
 		}
 		if (window[globalCheck]) {
 			endCallback();
 		}
 		else {
 			scripts.reduceRight(function (oldFunc, script) {
 				return function () {
 					$.getScript(script, oldFunc);
 				};
 			}, endCallback)();
 		}
 	};
 };
 
 }());
diff --git a/desuto-viewer/Desuto-webviewer/public/js/utils.js b/desuto-viewer/Desuto-webviewer/public/js/utils.js
index b88f522..9a6f75f 100644
--- a/desuto-viewer/Desuto-webviewer/public/js/utils.js
+++ b/desuto-viewer/Desuto-webviewer/public/js/utils.js
@@ -1,545 +1,486 @@
 var performingSearch = false;
 var round_digits = 5;
 
 // Get URL parameter
 function getParameterByName(name) {
     name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
     var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
             results = regex.exec(location.search);
     return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
 }
 
 // Transform SVG element into JSON
 function getJSONforSVG(element, image) {
     var svgJson = {};
 
     //Element
     svgJson.element = element.tagName;
 
     //Attr
     svgJson.attr = {};
 
     //ID
     svgJson.attr.id = element.id + "#" + element.tagName;
 
     //Attributes
     var attributes = element.attributes;
     $.each(attributes, function (index, attribute) {
         svgJson.attr[attribute.name] = attribute.value;
     });
 
     return svgJson;
 }
 
 // Print out CouchDB contents
 function printAnnotations() {
     db.allDocs({include_docs: true, descending: true}, function (err, doc) {
         //redrawTodosUI(doc.rows);
         $.each(doc.rows, function (index, element) {
             console.log(JSON.stringify(element, null, 2));
         });
     });
 }
 
 // Convert a color name to corresponding HEX code
 function colourNameToHex(colour)
 {
     var colours = {"aliceblue": "#f0f8ff", "antiquewhite": "#faebd7", "aqua": "#00ffff", "aquamarine": "#7fffd4", "azure": "#f0ffff",
         "beige": "#f5f5dc", "bisque": "#ffe4c4", "black": "#000000", "blanchedalmond": "#ffebcd", "blue": "#0000ff", "blueviolet": "#8a2be2", "brown": "#a52a2a", "burlywood": "#deb887",
         "cadetblue": "#5f9ea0", "chartreuse": "#7fff00", "chocolate": "#d2691e", "coral": "#ff7f50", "cornflowerblue": "#6495ed", "cornsilk": "#fff8dc", "crimson": "#dc143c", "cyan": "#00ffff",
         "darkblue": "#00008b", "darkcyan": "#008b8b", "darkgoldenrod": "#b8860b", "darkgray": "#a9a9a9", "darkgreen": "#006400", "darkkhaki": "#bdb76b", "darkmagenta": "#8b008b", "darkolivegreen": "#556b2f",
         "darkorange": "#ff8c00", "darkorchid": "#9932cc", "darkred": "#8b0000", "darksalmon": "#e9967a", "darkseagreen": "#8fbc8f", "darkslateblue": "#483d8b", "darkslategray": "#2f4f4f", "darkturquoise": "#00ced1",
         "darkviolet": "#9400d3", "deeppink": "#ff1493", "deepskyblue": "#00bfff", "dimgray": "#696969", "dodgerblue": "#1e90ff",
         "firebrick": "#b22222", "floralwhite": "#fffaf0", "forestgreen": "#228b22", "fuchsia": "#ff00ff",
         "gainsboro": "#dcdcdc", "ghostwhite": "#f8f8ff", "gold": "#ffd700", "goldenrod": "#daa520", "gray": "#808080", "green": "#008000", "greenyellow": "#adff2f",
         "honeydew": "#f0fff0", "hotpink": "#ff69b4",
         "indianred ": "#cd5c5c", "indigo": "#4b0082", "ivory": "#fffff0", "khaki": "#f0e68c",
         "lavender": "#e6e6fa", "lavenderblush": "#fff0f5", "lawngreen": "#7cfc00", "lemonchiffon": "#fffacd", "lightblue": "#add8e6", "lightcoral": "#f08080", "lightcyan": "#e0ffff", "lightgoldenrodyellow": "#fafad2",
         "lightgrey": "#d3d3d3", "lightgreen": "#90ee90", "lightpink": "#ffb6c1", "lightsalmon": "#ffa07a", "lightseagreen": "#20b2aa", "lightskyblue": "#87cefa", "lightslategray": "#778899", "lightsteelblue": "#b0c4de",
         "lightyellow": "#ffffe0", "lime": "#00ff00", "limegreen": "#32cd32", "linen": "#faf0e6",
         "magenta": "#ff00ff", "maroon": "#800000", "mediumaquamarine": "#66cdaa", "mediumblue": "#0000cd", "mediumorchid": "#ba55d3", "mediumpurple": "#9370d8", "mediumseagreen": "#3cb371", "mediumslateblue": "#7b68ee",
         "mediumspringgreen": "#00fa9a", "mediumturquoise": "#48d1cc", "mediumvioletred": "#c71585", "midnightblue": "#191970", "mintcream": "#f5fffa", "mistyrose": "#ffe4e1", "moccasin": "#ffe4b5",
         "navajowhite": "#ffdead", "navy": "#000080",
         "oldlace": "#fdf5e6", "olive": "#808000", "olivedrab": "#6b8e23", "orange": "#ffa500", "orangered": "#ff4500", "orchid": "#da70d6",
         "palegoldenrod": "#eee8aa", "palegreen": "#98fb98", "paleturquoise": "#afeeee", "palevioletred": "#d87093", "papayawhip": "#ffefd5", "peachpuff": "#ffdab9", "peru": "#cd853f", "pink": "#ffc0cb", "plum": "#dda0dd", "powderblue": "#b0e0e6", "purple": "#800080",
         "red": "#ff0000", "rosybrown": "#bc8f8f", "royalblue": "#4169e1",
         "saddlebrown": "#8b4513", "salmon": "#fa8072", "sandybrown": "#f4a460", "seagreen": "#2e8b57", "seashell": "#fff5ee", "sienna": "#a0522d", "silver": "#c0c0c0", "skyblue": "#87ceeb", "slateblue": "#6a5acd", "slategray": "#708090", "snow": "#fffafa", "springgreen": "#00ff7f", "steelblue": "#4682b4",
         "tan": "#d2b48c", "teal": "#008080", "thistle": "#d8bfd8", "tomato": "#ff6347", "turquoise": "#40e0d0",
         "violet": "#ee82ee",
         "wheat": "#f5deb3", "white": "#ffffff", "whitesmoke": "#f5f5f5",
         "yellow": "#ffff00", "yellowgreen": "#9acd32"};
 
     // Already hex - return it
     if (colour.substr(0,1) === "#")
         return colour;
 
     // Return correct hex
     if (typeof colours[colour.toLowerCase()] != 'undefined')
         return colours[colour.toLowerCase()];
 
     return false;
 }
 
 function calculateReferenceZoom(viewport, world, refMag, realMagAvailable) {
 
     var oneXZoom;
 
     // If no reference is given, assume the max zoom is 40x and go from there
     if(typeof realMagAvailable !== "undefined" && !realMagAvailable){
         var fortyXZoom = viewport.getMaxZoom();
         oneXZoom = fortyXZoom / refMag;
     }else{
         // Figure out all the sizes
         var contentWidth = world.getItemAt(0).viewportToImageCoordinates(world.getHomeBounds().width).x;
         var contentHeight = world.getItemAt(0).viewportToImageCoordinates(world.getHomeBounds().height).x;
 
         var containerWidth = viewport.containerSize.x;
         var containerHeight = viewport.containerSize.y;
 
         var aspectRatio;
 
         var canvasRatio = containerHeight / containerWidth;
         aspectRatio = contentHeight / contentWidth;
 
         if (aspectRatio > canvasRatio) {
             oneXZoom = (contentWidth / containerWidth) / refMag;
         } else {
             oneXZoom = (contentHeight / containerHeight) / refMag;
         }
     }
 
 //        console.log("content : " + contentWidth + "," + contentHeight);
 //        console.log("displayed : " + displayedWidth + "," + displayedHeight);
 //        console.log("zoom : " + viewer.viewport.getZoom());
 
     return oneXZoom;
 }
 
 // Function: addSvgElementFromJson
 // Create a new SVG element based on the given object keys/values and add it to the current layer
 // The element will be ran through cleanupElement before being returned
 //
 // Parameters:
 // data - Object with the following keys/values:
 // * element - tag name of the SVG element to create
 // * attr - Object with attributes key-values to assign to the new element
 //
 // Returns: The new element
 function addSvgElementFromJsonSimple(data) {
   var NS = svgedit.NS;
   var svgdoc = window.document;
   var shape = $("#svgcontent g #"+ data.attr.id).get(0);
   if (!shape) {
     shape = svgdoc.createElementNS(NS.SVG, data.element);
   }
   svgedit.utilities.assignAttributes(shape, data.attr, 100);
   svgedit.utilities.cleanupElement(shape);
 
   return shape;
-};
+}
 
 function getPatch(viewer, x, y, width, height){
     var viewportPointTL = new OpenSeadragon.Point(x,y);
     var viewPortPointBR = new OpenSeadragon.Point(x + width, y + height);
 
     var imagePointTL = viewer.viewport.viewportToImageCoordinates(viewportPointTL);
     var imagePointBR = viewer.viewport.viewportToImageCoordinates(viewPortPointBR);
 
     var imageWidth = imagingHelper.imgWidth;
     var imageHeight = imagingHelper.imgHeight;
 
     var realX = imagePointTL.x;
     var realY = imagePointTL.y;
 
     var realWidth = imagePointBR.x - imagePointTL.x;
     var realHeight = imagePointBR.y - imagePointTL.y;
 
     //console.log("Need to analyze area starting at [" + realX + "," + realY + "], width=" + realWidth + ", height=" + realHeight);
 
     var proportionalX = realX / imageWidth;
     var proportionalY = realY / imageHeight;
     var proportionalWidth = realWidth / imageWidth;
     var proportionalHeight = realHeight / imageHeight;
 
     var region = proportionalX + ',' + proportionalY + ',' + proportionalWidth + ',' + proportionalHeight;
 
     var url = config.iipRootURL + '?FIF=' + config.iipImageDir + image + '&WID=' + config.iipPatchSize + '&RGN=' + region + '&CVT=jpeg'
 
     return url;
 }
 
+SVGElement.prototype.getTransformToElement =
+  SVGElement.prototype.getTransformToElement || function(elem)
+  {
+      return elem.getScreenCTM().inverse().multiply(this.getScreenCTM());
+  };
+
+function get_metrics(el) {
+    function pointToLineDist(A, B, P) {
+        var nL = Math.sqrt((B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y));
+        return Math.abs((P.x - A.x) * (B.y - A.y) - (P.y - A.y) * (B.x - A.x)) / nL;
+    }
+
+    function dist(point1, point2) {
+        var xs = 0,
+          ys = 0;
+        xs = point2.x - point1.x;
+        xs = xs * xs;
+        ys = point2.y - point1.y;
+        ys = ys * ys;
+        return Math.sqrt(xs + ys);
+    }
+    var b = el.getBBox(),
+      objDOM = el,
+      svgDOM = objDOM.ownerSVGElement;
+    // Get the local to global matrix
+    var matrix = svgDOM.getTransformToElement(objDOM).inverse(),
+      oldp = [[b.x, b.y], [b.x + b.width, b.y], [b.x + b.width, b.y + b.height], [b.x, b.y + b.height]],
+      pt, newp = [],
+      obj = {},
+      i, pos = Number.POSITIVE_INFINITY,
+      neg = Number.NEGATIVE_INFINITY,
+      minX = pos,
+      minY = pos,
+      maxX = neg,
+      maxY = neg;
+
+    for (i = 0; i < 4; i++) {
+        pt = svgDOM.createSVGPoint();
+        pt.x = oldp[i][0];
+        pt.y = oldp[i][1];
+        newp[i] = pt.matrixTransform(matrix);
+        if (newp[i].x < minX) minX = newp[i].x;
+        if (newp[i].y < minY) minY = newp[i].y;
+        if (newp[i].x > maxX) maxX = newp[i].x;
+        if (newp[i].y > maxY) maxY = newp[i].y;
+    }
+    // The next refers to the transformed object itself, not bbox
+    // newp[0] - newp[3] are the transformed object's corner
+    // points in clockwise order starting from top left corner
+    obj.newp = newp; // array of corner points
+    obj.width = pointToLineDist(newp[1], newp[2], newp[0]) || 0;
+    obj.height = pointToLineDist(newp[2], newp[3], newp[0]) || 0;
+    obj.toplen = dist(newp[0], newp[1]);
+    obj.rightlen = dist(newp[1], newp[2]);
+    obj.bottomlen = dist(newp[2], newp[3]);
+    obj.leftlen = dist(newp[3], newp[0]);
+    // The next refers to the transformed object's bounding box
+    obj.BBx = minX;
+    obj.BBy = minY;
+    obj.BBx2 = maxX;
+    obj.BBy2 = maxY;
+    obj.BBwidth = maxX - minX;
+    obj.BBheight = maxY - minY;
+    return obj;
+}
+
 function loadPatchPreview(svgElement){
 
     if(!svgElement)
         return;
 
     try{
 
-        var bbox = svgedit.utilities.getBBox(svgElement);
-
-        var patchURL = getPatch(viewer, bbox.x, bbox.y, bbox.width, bbox.height);
+        var bboxObj = svgedit.utilities.getBBox(document.querySelector('#selectorParentGroup #selectorGroup0'));
 
-        $("#annotation-patch img#patch-preview").attr('src', patchURL);
-
-        var finalRetrievalURL = config.retrievalInterfaceRootURL;
-
-        var caption = $("#annotation").val();
+        var bbox = svgElement.getBBox();
+        var ctm = svgElement.getCTM();
 
-        if(caption)
-            finalRetrievalURL += "caption/" + encodeURIComponent(caption) + "/";
+        //var transform = bbox.createSVGTransform();
+        //transform.setMatrix(ctm);
+        //bbox.transform.baseVal.initialize(transform);
 
-        var relevantImages = [patchURL];
-        var searchParameters = {"relevantImages" : relevantImages};
-        finalRetrievalURL += 'images/' + encodeURIComponent(JSON.stringify(searchParameters));
+        bbox = svgedit.utilities.bboxToObj(bbox);
 
-        // Define dataset to search in!
-        var dataset = image.substr(0, image.indexOf("/"));
+        let metrics = get_metrics(svgElement);
 
-        finalRetrievalURL += '/dataset/' + dataset;
+        let angle = svgedit.utilities.getRotationAngle(svgElement);
 
-        // Add magnification
-        finalRetrievalURL += '/magnification/' + getCurrentClosestX();
+        var patchURL = getPatch(viewer, bbox.x, bbox.y, bbox.width, bbox.height);
 
-        var magnification = 5;
-        if(svgEditor.canvas.getSelectedElems().length > 0){
-            magnification = $(svgEditor.canvas.getSelectedElems()[0]).attr("histopatho-zoom");
-            if(magnification == null)
-                magnification = getCurrentX();
-        }
+        $("#annotation-patch img#patch-preview").attr('src', patchURL);
 
-        //$("#annotation-patch a").data('src', finalRetrievalURL);
-        $("#search-similar").data('src', finalRetrievalURL);
+        var caption = $("#annotation").val();
 
         // Figure out the pixel size
         var pixelBBox = viewer.viewport.viewportToImageRectangle(new OpenSeadragon.Rect(bbox.left, bbox.top, bbox.width, bbox.height));
         var mmBBox = {};
 
         // Figure out in mm
         for (var prop in pixelBBox){
             mmBBox[prop] = pixelBBox[prop] / pixelsPerMeter * 1000;
         }
 
         var area = bbox.width * bbox.height;
         $("#annotation-stats div").html("<span>Size (bbox) : " + mmBBox.width.toFixed(2) + "x" + mmBBox.height.toFixed(2) + "mm</span>");
-
-        // Update Search caption
-        $("#similar-patches-magnification").text(getClosestX(magnification) + 'x');
-
-        // Perform search
-        performSearch(caption, relevantImages, magnification);
     }catch (e){
         console.log(e);
     }
-
-    function performSearch(caption, relevantImages, magnification){
-
-        $("#patches-loader").show();
-
-        $("#similar-patches").empty();
-
-        // Define dataset to search in!
-        var dataset = image.substr(0, image.indexOf("/"));
-
-        // TODO - Harmonize this in the JSON files
-        // Define separator for indices name
-        var separator = "_";
-
-        var closestX = getClosestX(magnification);
-        var visualIndices = [dataset + "100" + separator + closestX +"x" + separator + "cedd"];
-        var maxResults = 1000;
-        var maxShownResults = 20;
-
-        if(!performingSearch) {
-
-            performingSearch = true;
-
-            //Perform search and insert images
-            $.getJSON(config.globalSearchURL, {
-                "caption-indices": JSON.stringify([]),
-                "visual-indices": JSON.stringify(visualIndices),
-                "caption-query": caption,
-                "relevant-images": JSON.stringify(relevantImages),
-                "irrelevant-images": JSON.stringify([]),
-                "modality-filter": "NONE",
-                "use-image-captions": "false",
-                "maximum-results": maxResults + '',
-                "caption-search": false + '',
-                "visual-search": true + ''
-            }, function (data) {
-
-                var results = data.results;
-
-                if (typeof (results) !== 'undefined') {
-                    var data_length = results.length;
-                    var resultImages = getResultsArray(results);
-                } else {
-                    resultImages = [];
-                }
-
-                var sameImagePatches = resultImages.filter(function(image){
-                    var currentImageName = getParameterByName('image');
-                    currentImageName = currentImageName.substr(currentImageName.indexOf('/') + 1);
-                    return image.indexOf(currentImageName) > 0;
-                });
-
-                sameImagePatches = sameImagePatches.splice(0, maxShownResults);
-
-                if(sameImagePatches.length > 0){
-                    sameImagePatches.forEach(function (image) {
-
-                        var finalRetrievalURL = config.retrievalInterfaceRootURL;
-
-                        var relevantImages = [image];
-                        var searchParameters = {"relevantImages" : relevantImages};
-                        finalRetrievalURL += 'images/' + encodeURIComponent(JSON.stringify(searchParameters));
-
-                        var x = getCoordinate("x", image);
-                        var y = getCoordinate("y", image);
-                        var size = getPatchSize(image);
-                        $("#similar-patches").append($("<img>").attr("src", image).attr("title", "X : " + x + ", Y : " + y).addClass("little-result").click(function(){
-                            panToPatch(x, y, size);
-                        }));
-                    });
-                }else{
-                    $("#similar-patches").append($("<p>None found</p>"));
-                }
-
-
-                // Fancybox
-                $("[data-fancybox]").fancybox({
-                    iframe:{
-                        scrolling : 'yes'
-                    }
-                });
-
-                $("#patches-loader").hide();
-                performingSearch = false;
-
-            }).fail(function () { //Problem contacting the server
-                performingSearch = false;
-                $("#similar-patches").empty();
-                $("#patches-loader").hide();
-            });
-        }
-    }
-
-    /* Fill results array for display */
-    function getResultsArray(results) {
-        var resultImages = [];
-
-        var data_length = results.length;
-
-        for (var i = 0; i < data_length; i++) {
-            resultImages.push(results[i]["imageURL"]);
-        }
-
-        return resultImages;
-    }
 }
 
 function panToPatch(x, y, size){
 
     var upperLeft = new OpenSeadragon.Point(x, y);
     var viewerPoint = viewer.viewport.imageToViewportCoordinates(upperLeft);
     var viewerSize  = viewer.viewport.imageToViewportCoordinates(new OpenSeadragon.Point(size, size));
 
     // TODO - Fix this once x & y are correct!
     viewer.viewport.fitBoundsWithConstraints(new OpenSeadragon.Rect(viewerPoint.y, viewerPoint.x, viewerSize.x, viewerSize.y), false);
 }
 
 function getPatchSize(url) {
     var patchSize = config.iipPatchSize;
 
     // Figure out magnification adjustment
     re = new RegExp("/([0-9]+)X/", "g");
     matches = re.exec(url);
 
     var patchMagnification = parseInt(matches[1]);
 
     if(patchMagnification < refMag)
         patchSize = patchSize * (refMag / patchMagnification);
 
     return patchSize;
 }
 
 function getCoordinate(dimension, url){
 
     // Figure out coord
     var re = new RegExp("_" + dimension + "([0-9]+)", "g");
     var matches = re.exec(url);
 
     var coord = parseInt(matches[1]);
 
     // Figure out magnification adjustment
     re = new RegExp("/([0-9]+)X/", "g");
     matches = re.exec(url);
 
     var patchMagnification = parseInt(matches[1]);
 
     if(patchMagnification < refMag)
         coord = coord * (refMag / patchMagnification);
 
     return coord;
 }
 
 function getX(magnification){
     return magnification / oneXZoom;
 }
 
 function getClosestX(x){
     var closestX = closest(x, [5,10,20,40]);
     console.log("Current : " + x + ", Closest : " + closestX);
     return closestX;
 }
 
 function getCurrentX(){
     return getX(viewer.viewport.getZoom());
 }
 
 function getCurrentClosestX(){
     return getClosestX(getCurrentX());
 }
 
 function closest (num, arr) {
     var curr = arr[0];
     var diff = Math.abs (num - curr);
     for (var val = 0; val < arr.length; val++) {
         var newdiff = Math.abs (num - arr[val]);
         if (newdiff < diff) {
             diff = newdiff;
             curr = arr[val];
         }
     }
     return curr;
 }
 
 function simplifyURL(url){
     var url = url.substr(url.lastIndexOf('/') + 1);
     url = url.replace(/_[a-z]+_x[0-9]+_y[0-9]+/g, '');
     if(url.indexOf('&') !== -1)
         url = url.substr(0, url.indexOf('&'));
     if(url.indexOf('.') !== -1)
         url = url.substr(0, url.indexOf('.'));
     url = decodeURIComponent(url);
 
     return url;
 }
 
 function compareObjects(o1, o2){
     for(var p in o1){
         if(o1.hasOwnProperty(p)){
             if(o1[p] !== o2[p]){
                 return false;
             }
         }
     }
     for(var p in o2){
         if(o2.hasOwnProperty(p)){
             if(o1[p] !== o2[p]){
                 return false;
             }
         }
     }
     return true;
 };
 
 // Internal recursive comparison function for `isEqual`.
 function compareObjects(a, b, aStack, bStack) {
     // Identical objects are equal. `0 === -0`, but they aren't identical.
     // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
     if (a === b) return a !== 0 || 1 / a === 1 / b;
     // A strict comparison is necessary because `null == undefined`.
     if (a == null || b == null) return a === b;
     // Unwrap any wrapped objects.
     if (a instanceof _) a = a._wrapped;
     if (b instanceof _) b = b._wrapped;
     // Compare `[[Class]]` names.
     var className = toString.call(a);
     if (className !== toString.call(b)) return false;
     switch (className) {
         // Strings, numbers, regular expressions, dates, and booleans are compared by value.
         case '[object RegExp]':
         // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
         case '[object String]':
             // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
             // equivalent to `new String("5")`.
             if(!isNumber(a) || !isNumber(b))
                 return '' + a === '' + b;
             else
                 return parseFloat(a).toFixed(round_digits) === parseFloat(b).toFixed(round_digits);
         case '[object Number]':
             // `NaN`s are equivalent, but non-reflexive.
             // Object(NaN) is equivalent to NaN
             if (+a !== +a) return +b !== +b;
             // An `egal` comparison is performed for other numeric values.
             return +a === 0 ? 1 / +a === 1 / b : +a === +b;
         case '[object Date]':
         case '[object Boolean]':
             // Coerce dates and booleans to numeric primitive values. Dates are compared by their
             // millisecond representations. Note that invalid dates with millisecond representations
             // of `NaN` are not equivalent.
             return +a === +b;
     }
 
     var areArrays = className === '[object Array]';
     if (!areArrays) {
         if (typeof a != 'object' || typeof b != 'object') return false;
 
         // Objects with different constructors are not equivalent, but `Object`s or `Array`s
         // from different frames are.
         var aCtor = a.constructor, bCtor = b.constructor;
         if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
             _.isFunction(bCtor) && bCtor instanceof bCtor)
             && ('constructor' in a && 'constructor' in b)) {
             return false;
         }
     }
     // Assume equality for cyclic structures. The algorithm for detecting cyclic
     // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
 
     // Initializing stack of traversed objects.
     // It's done here since we only need them for objects and arrays comparison.
     aStack = aStack || [];
     bStack = bStack || [];
     var length = aStack.length;
     while (length--) {
         // Linear search. Performance is inversely proportional to the number of
         // unique nested structures.
         if (aStack[length] === a) return bStack[length] === b;
     }
 
     // Add the first object to the stack of traversed objects.
     aStack.push(a);
     bStack.push(b);
 
     // Recursively compare objects and arrays.
     if (areArrays) {
         // Compare array lengths to determine if a deep comparison is necessary.
         length = a.length;
         if (length !== b.length) return false;
         // Deep compare the contents, ignoring non-numeric properties.
         while (length--) {
             if (!eq(a[length], b[length], aStack, bStack)) return false;
         }
     } else {
         // Deep compare objects.
         var keys = _.keys(a), key;
         length = keys.length;
         // Ensure that both objects contain the same number of properties before comparing deep equality.
         if (_.keys(b).length !== length) return false;
         while (length--) {
             // Deep compare each member
             key = keys[length];
             if (!(_.has(b, key) && compareObjects(a[key], b[key], aStack, bStack)))
                 return false;
         }
     }
     // Remove the first object from the stack of traversed objects.
     aStack.pop();
     bStack.pop();
     return true;
 };
 
 function isNumber(n) {
     return !isNaN(parseFloat(n)) && isFinite(n);
 }
diff --git a/desuto-viewer/Desuto-webviewer/public/stylesheets/theme.css b/desuto-viewer/Desuto-webviewer/public/stylesheets/theme.css
index c3c790b..7ab2f07 100644
--- a/desuto-viewer/Desuto-webviewer/public/stylesheets/theme.css
+++ b/desuto-viewer/Desuto-webviewer/public/stylesheets/theme.css
@@ -1,635 +1,631 @@
 /*
     Created on : Apr 28, 2015, 10:06:04 AM
     Author     : sro
 */
 html, body{
     font-family:Helvetica, Arial, sans-serif;
     margin-top: 0px;
     margin:0px;
     height:100%;
     min-height: 100%;
 }
 
 nav{
     margin-bottom: 0px !important;
 }
 
 .clear{
     clear:both;
 }
 
 .centered{
   text-align: center;
 }
 
 #maincontainer{
     height:calc(100% - 52px);
     width: 100%;
     min-width: 800px;
     position: absolute;
 }
 
 #container{
     float:left;
     width:100%;
     height: 100%;
     overflow: hidden;
 }
 
 #left{
     padding-right: 1em;
     margin-right: 320px;
     height:80%;
 }
 
 #annotation-details{
     position: absolute;
     top: 0em;
     right: 120px;
     width: 200px;
 }
 
 #annotation-details p{
     margin-top:.75em;
     margin-bottom:.25em;
 }
 
 #annotation-details hr{
     margin: 5px 0;
     border-top-color: #ccc;
 }
 
 #toggle-annotation{
     float: left;
 }
 
 #sync{
     float: left;
     margin-left: 1em;
 }
 
 #footer{
   clear:both;
   width:100%;
   padding: 0 0.5em;
   font-size: smaller;
 }
 
 #image-list, #feature-list{
     padding: 1em;
 }
 
 #image-list ul li, #feature-list ul li {
   font-size: smaller;
   padding:0.15em 0;
 }
 
 /*#image-list{
     margin-left: -310px;
     overflow-x: auto;
     white-space: nowrap;
 }
 
 #feature-list{
     margin-left:-150px;
     overflow-x: auto;
 }*/
 
 #sidenavMenu{
     text-align: center;
     position:absolute;
     top: 0;
     right: 0;
     width: 120px;
 }
 
 #sidenavMenu div{
     cursor: pointer;
 }
 
 #sidenavMenu div:hover{
     text-decoration: underline;
 }
 
 #sidenavMenu i{
     margin: 1em 0;
     margin-right: 0.5em;
 }
 
 #openseadragon{
     position: relative;
 }
 
 #openseadragon-features{
     pointer-events: none; /*feature overlay should NOT react to any events*/
     z-index:2;
 }
 
 #svg-overlay{
     position:absolute;
     z-index:3;
 }
 
 #openseadragon .navigator{
     z-index: 4;
 }
 
 #feature-opacity{
     width:100px;
 }
 
 #feature-opacity-label{
     vertical-align: super;
     font-size:smaller;
 }
 
 #image-list h2, #feature-list h2{
     margin-top:0.5em;
 }
 
 ul#image-list-entries, ul#feature-list-entries{
     list-style-type: none;
     padding-left:0em;
 }
 
 li a.active{
     color:#D21038;
 }
 
 /* Annotation button */
 
 #annotation-menu{
     float:left;
     margin-left:0.1em;
     line-height:38px;
     text-align:center;
 }
 
 #annotation-menu button{
     font-size:larger;
 }
 
 /* Container for toolbars */
 
 #toolbar-div{
     z-index:1;
     margin:0.5em 0em;
     margin-bottom: 0.1em;
     height:38px;
 }
 
 /* Viewing tools */
 
 #tools-viewer{
     float:right;
     height:38px;
     line-height: 37px;
     margin-right: 0.5em;
 }
 
 #tools-viewer .fa{
     font-size:1.2em;
 }
 
 #tools-viewer .toolbar-button{
     color:black;
     padding:0 0.25em;
     display:inline-block;
     position:relative;
 }
 
 /* Drawing tools */
 
 #tools-drawing-container{
     float:right;
     margin-right: 0.5em;
     display: none;
 }
 
 #tools-drawing {
     float:right;
     /*position: absolute;
     border-right: none;
     top:6px;
     left: 0px;
     padding-left: 2px;*/
     /*background: #D0D0D0; /* Needed so flyout icons don't appear on the left */
     z-index: 2;
 }
 
 #tools-drawing *{
     box-sizing: content-box !important;
 }
 
 #tools-drawing .tool_button, #tools-drawing .tool_button_current{
     display:inline-block;
 }
 
 /* Where the annotation is written */
 
 #annotation-container{
     display:none;
     margin: 0.0em;
     width:100%;
 }
 
 #annotation-container .float{
     float:left;
 }
 
 #annotation-text{
     /*width:65%;*/
     width:100%;
 }
 
 #annotation-stats{
     /*display:none;*/
 }
 
 #annotation-patch img{
     max-width: 200px;
     max-height: 200px;
 }
 
 /*.fancybox-slide--iframe .fancybox-content {
     width  : 800px;
     height : 600px;
     max-width  : 80%;
     max-height : 80%;
     margin: 0;
 }*/
 
 #annotation-tooltip{
     display:none;
     position: absolute;
     top:0;
     left:0;
     background-color: rgba(0,0,0,0.7);
     color:white;
     padding:0.5em 0.75em;
     font-size: smaller;
     border-radius: 8px;
     z-index : 5;
 }
 
 #annotation{
     margin-top:0.25em;
     width:98%;
     height:3em;
     resize: vertical;
     font-family: Helvetica, Arial, sans-serif;
 }
 
 #normal{
     padding:0px;
     margin: 9px 0px;
     height: 20px;
 }
 
 /* Color picker */
 
 .simplecolorpicker.inline{
     padding:0px;
     height: 38px;
 }
 
 .simplecolorpicker.inline .color{
     margin:0px;
     margin-right: 5px;
     margin-top: 8px;
 }
 
 /* SVG Editor */
 
 /* Remove text underline in toolbar icons */
 
 .tool_button:hover,
 .push_button:hover,
 .buttonup:hover,
 .buttondown,
 .tool_button_current,
 .push_button_pressed
 {
 	/*background-color: #ffc !important;*/
         border:1px dashed black;
 }
 
 .tool_button_current,
 .push_button_pressed,
 .buttondown {
 	/*background-color: #f4e284 !important;*/
         border:1px solid black !important;
 	/*-webkit-box-shadow: inset 1px 1px 2px rgba(0,0,0,0.4), 1px 1px  0 white  !important;
 	-moz-box-shadow: inset 1px 1px 2px rgba(0,0,0,0.4), 1px 1px  0 white  !important;
 	box-shadow: inset 1px 1px 2px rgba(0,0,0,0.4), 1px 1px  0 white  !important;*/
 }
 
 .toolbar-button{
     text-decoration: none !important;
 }
 
 .toolbar_button button {
 	border:1px solid #dedede;
 	line-height:130%;
 	float: left;
 	background: #E8E8E8 none;
 	padding:5px 10px 5px 7px; /* Firefox */
 	line-height:17px; /* Safari */
 	margin: 5px 20px 0 0;
 	border: 1px #808080 solid;
 	border-top-color: #FFF;
 	border-left-color: #FFF;
 	border-radius: 5px;
 	-moz-border-radius: 5px;
 	-webkit-border-radius: 5px;
 }
 
 .toolbar_button button:hover {
 	border: 1px #e0a874 solid;
 	border-top-color: #fcd9ba;
 	border-left-color: #fcd9ba;
 	background-color: #FFC;
 }
 .toolbar_button button:active {
 	background-color: #F4E284;
 	border-left: 1px solid #663300;
 	border-top: 1px solid #663300;
 }
 
 .toolbar_button button .svg_icon {
 	margin: 0 3px -3px 0 !important;
 	padding: 0;
 	border: none;
 	width: 16px;
 	height: 16px;
 }
 
 #tools_left .tool_button,
 #tools_left .tool_button_current {
 	position: relative;
 	z-index: 11;
 }
 
 .tool_button,
 .push_button,
 .tool_button_current,
 .push_button_pressed
 {
 	height: 24px;
 	width: 24px;
 	margin: 2px 2px 4px 2px;
 	padding: 3px;
 	/*-webkit-box-shadow: inset 1px 1px 2px white, 1px 1px 1px rgba(0,0,0,0.3);
 	moz-box-shadow: inset 1px 1px 2px white, 1px 1px 1px rgba(0,0,0,0.3);
 	box-shadow: inset 1px 1px 2px white, 1px 1px 1px rgba(0,0,0,0.3);*/
 	background-color: #fff;
         border: 1px solid transparent;
 	cursor: pointer;
 	border-radius: 3px;
 	-moz-border-radius: 3px;
 	-webkit-border-radius: 3px;
 }
 
 #menu-top{
     margin-bottom: 1em;
 }
 
 /* Generic context menu styles */
 .contextMenu {
 	position: absolute;
 	z-index: 99999;
 	border: solid 1px rgba(0,0,0,.33);
 	background: rgba(255,255,255,.95);
 	padding: 5px 0;
 	margin: 0px;
         /* ROGERMOD - fix contextmenu position */
         margin-top:-58px;
         margin-left: -10px;
 	display: none;
 	font: 12px/15px Lucida Sans, Helvetica, Verdana, sans-serif;
 	border-radius: 5px;
 	-moz-border-radius: 5px;
 	-moz-box-shadow: 2px 5px 10px rgba(0,0,0,.3);
 	-webkit-box-shadow: 2px 5px 10px rgba(0,0,0,.3);
 	box-shadow: 2px 5px 10px rgba(0,0,0,.3);
 }
 
 .contextMenu LI {
 	list-style: none;
 	padding: 0px;
 	margin: 0px;
 }
 
 .contextMenu .shortcut {
 	width: 115px;
 	text-align:right;
 	float:right;
 }
 
 .contextMenu A {
 	-moz-user-select: none;
 	-webkit-user-select: none;
 	color: #222;
 	text-decoration: none;
 	display: block;
 	line-height: 20px;
 	height: 20px;
 	background-position: 6px center;
 	background-repeat: no-repeat;
 	outline: none;
 	padding: 0px 15px 1px 20px;
 }
 
 .contextMenu LI.hover A {
 	background-color: #2e5dea;
 	color: white;
 	cursor: default;
 }
 
 .contextMenu LI.disabled A {
 	color: #999;
 }
 
 .contextMenu LI.hover.disabled A {
 	background-color: transparent;
 }
 
 .contextMenu LI.separator {
 	border-top: solid 1px #E3E3E3;
 	padding-top: 5px;
 	margin-top: 5px;
 }
 
 /* Sizing */
 
 #openseadragon-container{
     width: 100%;
     height: 100%;
     position: relative;
     border: 1px solid transparent;
 }
 
 #openseadragon-container *{
     outline: none;
 }
 
 #locks{
     display: none;
 }
 
 #locks i{
     position: absolute;
     padding: 10px;
     z-index:100;
 }
 
 #tl-lock{
     top:0;
     left:0;
     background-color: rgba(255,255,255,.5);
 }
 
 #tl-lock span{
     font-family: Helvetica, Arial, sans-serif;
     font-weight: bold;
     padding-left: .5em;
 }
 
 #tr-lock{
     top:0;
     right:0;
 }
 
 #bl-lock{
     bottom:0;
     left:0;
 }
 
 #br-lock{
     bottom:0;
     right:0;
 }
 
 #openseadragon, #openseadragon-features{
     position:absolute;
 }
 
 #openseadragon, #openseadragon-features, #workarea{
     width:100%;
     height:100%;
 }
 
 #svg-overlay, #svg_editor, #svgcanvas, #svgroot{
     width:100%;
     height:100%;
 }
 
 #svg-overlay{
 
 }
 
 #svgcanvas{
 
 }
 
 #svgroot{
     display: inline-block;
     position: absolute;
 }
 
+#selectorGrip_rotate, #selectorGrip_rotateconnector{
+    display: none;
+}
+
 /* The side navigation menu */
 .sidenav {
     height: 100%; /* 100% Full-height */
     width: 0; /* 0 width - change this with JavaScript */
     position: fixed; /* Stay in place */
     z-index: 10; /* Stay on top */
     top: 0;
     right: 0;
     background-color: rgba(255,255,255,0.95); /* Black*/
     border-left:1px solid grey;
     overflow-x: hidden; /* Disable horizontal scroll */
     transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
 }
 
 .sidenav .ui-state-focus{
     outline: none;
 }
 
 .sidenav h3{
     font-size: medium;
     cursor: pointer;
 }
 
 .sidenav .ui-accordion-content{
     max-height: 650px;
 }
 
 /* The navigation menu links */
 .sidenav a {
     text-decoration: none;
     color: #818181;
     display: block;
     transition: 0.3s
 }
 
 /* When you mouse over the navigation links, change their color */
 .sidenav a:hover, .offcanvas a:focus{
     color: #0E0E0E;
 }
 
 /* Position and style the close button (top right corner) */
 .sidenav .closebtn {
     position: absolute;
     top: 0;
     right: 25px;
     font-size: 36px;
     margin-left: 50px;
 }
 
-#similar-patches{
-    max-height: 272px;
-    overflow-y: auto;
-}
-
-#similar-patches a{
-    display: inline-block;
-    outline: none;
-}
-
 /* Little search result */
 .little-result{
     max-height: 85px !important;
     max-width: 85px !important;
     margin: 3px !important;
     cursor: pointer;
 }
 
 .unselectable{
     pointer-events: none;
 
     -webkit-user-select: none; /* Chrome/Safari */
     -moz-user-select: none; /* Firefox */
     -ms-user-select: none; /* IE10+ */
 
     /* Rules below not implemented in browsers yet */
     -o-user-select: none;
     user-select: none;
 
     cursor: default;
 }
 
 .no-cursor{
     pointer-events: none;
 }
 
 /* Style page content - use this if you want to push the page content to the right when you open the side navigation */
 /*#maincontainer {
     transition: margin-left .5s;
     padding: 20px;
 }*/
 
 /* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
 @media screen and (max-height: 450px) {
     .sidenav {padding-top: 15px;}
     .sidenav a {font-size: 18px;}
 }
+
+
diff --git a/desuto-viewer/Desuto-webviewer/routes/api.js b/desuto-viewer/Desuto-webviewer/routes/api.js
index b268622..fe6128b 100644
--- a/desuto-viewer/Desuto-webviewer/routes/api.js
+++ b/desuto-viewer/Desuto-webviewer/routes/api.js
@@ -1,145 +1,145 @@
-var config = require('../config.json');
+var config = require('../config.js');
 
 var nano = require('nano')({
         url: config.couchDBRootURL,
         parseUrl: false
     }),
     util = require('util'),
     fs = require('fs'),
     resumable = require('../utils/resumable-node.js')(config.tempDir),
     spawn = require('child_process').spawn,
     exec = require('child_process').exec,
     lockfile = require('lockfile');
 
 // Login call
 exports.login = function(req, res) {
     var username = req.body.username;
     var userpass = req.body.password;
 
     nano.auth(username, userpass, function(err, body, headers) {
 
         // Error happened
         if (err) {
             if (err.statusCode) {
                 res.status(err.statusCode).send(err.reason);
             } else {
                 console.log(err.stack);
                 res.status(503).send("Database connection problem");
             }
             return;
         }
 
         // Get cookie and send it to client
         if (headers && headers['set-cookie']) {
             res.cookie(headers['set-cookie']);
         }
 
         var response = {};
         response.message = 'Logged in!';
         response.redirect = req.session.redirectTo ? req.session.redirectTo : '/';
 
         // Send success message
         res.send(response);
     });
 };
 
 // Logout call
 exports.logout = function(req, res) {
     // The CouchDB cookie name is AuthSession
     res.clearCookie('AuthSession');
     res.send('Logged out!');
 };
 
 // Upload call
 exports.upload = function(req, res) {
 
     resumable.post(req, function(status, filename, original_filename, identifier) {
         console.log('POST', status, original_filename, identifier);
         /*res.send(status, {
          // NOTE: Uncomment this funciton to enable cross-domain request.
          //'Access-Control-Allow-Origin': '*'
          });*/
         res.send(status);
 
         // When upload is finished, reassemble the file
         if (status === 'done') {
 
             var subfolder = typeof req.query.destination !== "undefined" ? req.query.destination : 'other'
 
             var path = config.baseDir + config.uploadedDir + subfolder + '/' + filename;
             var convertedpath = config.baseDir + config.convertedDir + subfolder + '/' + filename;
             var lockpath = config.baseDir + config.uploadedDir + subfolder + '/' + filename + ".lock";
 
             try {
                 fs.mkdirSync(config.baseDir + config.uploadedDir + subfolder);
             } catch (err) {
                 if(err.code !== 'EEXIST') throw err;
             }
 
             try {
                 fs.mkdirSync(config.baseDir + config.convertedDir + subfolder);
             } catch (err) {
                 if(err.code !== 'EEXIST') throw err;
             }
 
             // Create a lock file
             lockfile.lock(lockpath, function(err) {
 
                 // Already locked
                 if (err != null)
                     return;
 
                 // Not locked, proceed
                 var stream = fs.createWriteStream(path);
                 resumable.write(identifier, stream);
                 stream.on('finish', function() {
 
                     // Finished uploading the file
                     console.log('Done writing ' + identifier);
 
                     // Call UNIX script - Run VIPS docker container for converting the image
                     var cmd = spawn('vips', [
                      'extract_band',
                      path,
                      convertedpath + '.tif[tile,pyramid,compression=deflate,tile-width=256,tile-height=256,bigtiff]',
                      '0',
                      '--n',
                      '3'
                      ]);
 
                      // Process stdout
                      cmd.stdout.on('data', function(output){
                      console.log(output.toString());
                      });
 
                      // End of command
                      cmd.on('close', function(){
                      console.log('Finished converting ' + identifier);
                      });
 
                      //Error handling
                      cmd.stderr.on('data', function(err){
                      console.log(err.toString());
                      });
 
                     // Delete uploaded splits
                     resumable.clean(identifier);
 
                     // Unlock
                     lockfile.unlock(lockpath, function(err) {
                         console.log('Lockfile exception');
                     });
 
                 });
             });
         }
     });
 };
 
 // Handle status checks on chunks through Resumable.js
 exports.uploadCheck = function(req, res) {
     resumable.get(req, function(status, filename, original_filename, identifier) {
         console.log('GET', status);
         res.send((status === 'found' ? 200 : 404), status);
     });
 };
diff --git a/desuto-viewer/Desuto-webviewer/routes/index.js b/desuto-viewer/Desuto-webviewer/routes/index.js
index 5038aa5..34cba43 100644
--- a/desuto-viewer/Desuto-webviewer/routes/index.js
+++ b/desuto-viewer/Desuto-webviewer/routes/index.js
@@ -1,83 +1,86 @@
 var db = require('../utils/db');
 var admin = 'pathologists';
+var config = require('../config');
 
 /*
  * GET home page.
  */
 exports.index = function(req, res){
 
     var theUser;
     var theImages;
     var theImagesets;
     var title;
 
     function featuresCallback(features){
         res.render('viewer', { title: title, user: theUser.name, roles: theUser.roles, images: theImages, imagesets: theImagesets, features: features});
     }
 
     function imageCallback(images){
 
         theImages = images;
         theImagesets = Object.keys(images).sort();
 
         // Go to default image if none is defined
-        if(!req.query.image){
+        if(!req.query.image && images){
             res.redirect('/?image=' + theImages[theImagesets[0]][0]);
             return;
         }
 
         db.getFeatures(req, featuresCallback);
     }
 
     function userCallback(user){
         theUser = user;
 
         if(user.roles.indexOf(admin) > -1){
             title = 'SlideViewer - Pathologist'
         } else {
             title = 'SlideViewer - User'
         }
 
         db.getImages(req, imageCallback);
     }
 
     db.getUser(req, userCallback);
 };
 
 /* Render login page */
 exports.login = function(req, res){
 
     function callback(logged){
         if(logged){
             res.redirect('/logout')
         } else {
             res.render('login', {title: 'Slide Viewer - Login'})
         }
     }
 
+    console.log(config);
+
     db.isLogged(req, callback);
 };
 
 /* Render logout page */
 exports.logout = function(req, res){
 
     function callback(user){
         res.render('logout', {title: 'Slide Viewer - Logout', user: user.name, roles: user.roles})
     }
 
     db.getUser(req, callback);
 }
 
 /* Render upload page */
 exports.upload = function(req, res){
 
     function callback(user){
         if(user.roles.indexOf('pathologists') > -1){
             res.render('upload', {title: 'Slide Viewer - Upload'});
         }else{
             res.redirect('/');
         }
     }
 
     db.getUser(req, callback);
 }
diff --git a/desuto-viewer/Desuto-webviewer/utils/db.js b/desuto-viewer/Desuto-webviewer/utils/db.js
index 5915838..4031503 100644
--- a/desuto-viewer/Desuto-webviewer/utils/db.js
+++ b/desuto-viewer/Desuto-webviewer/utils/db.js
@@ -1,152 +1,156 @@
 /* DB utility functions */
-var config = require('../config.json'),
+var config = require('../config.js'),
     util = require('util'),
     fs = require('fs'),
     path = require('path'),
     recursive = require('recursive-readdir'),
     imagesBasePath = config.baseDir + config.convertedDir,
     overlaysBasePath = config.baseDir + config.overlaysDir;
 
 /* Login check */
 exports.isLogged = function(req, callback) {
 
     function usercallback(user) {
         if (user === null) {
             callback(false);
         } else {
             callback(true, user);
         }
     }
 
     exports.getUser(req, usercallback);
 };
 
 /* Get user */
 exports.getUser = function(req, callback) {
     // get cookie from request
     var auth = req.cookies['AuthSession'];
 
     // no cookie, not logged in
     if (auth === null) {
         callback(null);
         return;
     }
 
     // get CouchDB object
     var nano = require('nano')({
         url: config.couchDBRootURL,
         cookie: 'AuthSession=' + auth
     });
 
     // get current session
     nano.session(function(err, session) {
         if (err || session.userCtx.name === null) {
             callback(null);
             return;
         }
 
         console.log('user is %s and has these roles: %j', session.userCtx.name, session.userCtx.roles);
 
         callback(session.userCtx);
     });
 };
 
 /* Get images - beta version using the filesystem */
 exports.getImages = function(req, callback) {
     var images = {};
 
     recursive(imagesBasePath, function(err, files){
         console.log(files);
-        files.forEach(function (file) {
-            subdir = file.replace(imagesBasePath, '')
-            subdir = subdir.substring(0, subdir.indexOf('/'))
+        let images = [];
 
-            if(typeof images[subdir] === "undefined")
-                images[subdir] = [];
+        if(files){
+            files.forEach(function (file) {
+                subdir = file.replace(imagesBasePath, '');
+                subdir = subdir.substring(0, subdir.indexOf('/'));
 
-            images[subdir].push(file.replace(imagesBasePath, ''));
-        });
+                if(typeof images[subdir] === "undefined")
+                    images[subdir] = [];
 
-        images[subdir].sort(naturalSorter);
+                images[subdir].push(file.replace(imagesBasePath, ''));
+            });
+
+            images[subdir].sort(naturalSorter);
+        }
 
         callback(images);
     });
 };
 
 function naturalSorter(as, bs){
     var a, b, a1, b1, i= 0, n, L,
         rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
     if(as=== bs) return 0;
     a= as.toLowerCase().match(rx);
     b= bs.toLowerCase().match(rx);
     L= a.length;
     while(i<L){
         if(!b[i]) return 1;
         a1= a[i],
             b1= b[i++];
         if(a1!== b1){
             n= a1-b1;
             if(!isNaN(n)) return n;
             return a1>b1? 1:-1;
         }
     }
     return b[i]? -1:0;
 }
 
 /* Get features - beta version using the filesystem */
 exports.getFeatures = function(req, callback) {
     var image = req.query.image;
     var overlays = [];
 
     if (fs.existsSync(overlaysBasePath + image)) {
         var files = fs.readdirSync(overlaysBasePath + image);
 
         for (var i in files) {
             overlays.push(files[i].substr(0, files[i].lastIndexOf('.')));
         }
     }
 
     callback(overlays);
 };
 
 function getDirectories(srcpath) {
     return fs.readdirSync(srcpath).filter(function(file) {
         return fs.statSync(path.join(srcpath, file)).isDirectory();
     });
 }
 
 function endsWith(str, suffix) {
     return str.indexOf(suffix, str.length - suffix.length) !== -1;
 }
 
 /* Get images */
 /*exports.getImages = function(req, callback){
  // get cookie from request
  var auth = req.cookies['AuthSession'];
 
  // no cookie, not logged in
  if (auth === null) {
  callback(null);
  return;
  }
 
  // get CouchDB object
  var nano = require('nano')({
  url: config.dbProtocol + '://' + config.dbHost + ':' + config.dbPort,
  cookie: 'AuthSession=' + auth
  });
 
  // get images
  var histopatho = nano.use('histopatho');
  var images = [];
  histopatho.list(function(err, body){
  if (!err){
  body.rows.forEach(function(doc){
  console.log(doc.id);
  images.push(doc.id);
  });
 
  callback(images);
  }
  });
  }*/
diff --git a/desuto-viewer/Desuto-webviewer/views/login.html b/desuto-viewer/Desuto-webviewer/views/login.html
deleted file mode 100644
index f569111..0000000
--- a/desuto-viewer/Desuto-webviewer/views/login.html
+++ /dev/null
@@ -1 +0,0 @@
-<!DOCTYPE html><html lang="en"><head><title></title><link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"><link rel="stylesheet" href="stylesheets/theme.css"><link rel="stylesheet" href="stylesheets/login.css"></head><body><div class="container"><section class="loginform cf"><h1 class="centered"></h1><form id="loginform" name="login" action="" method="get" accept-charset="utf-8"><ul class="centered"><li><label for="username">User</label><input id="username" type="text" name="username" placeholder="username" required=""></li><li><label for="password">Password</label><input id="password" type="password" name="password" placeholder="password" required=""></li><li><p id="error"></p></li><li><input id="login" type="submit" value="Login"></li></ul></form></section></div><!-- App settings--><script src="js/app-settings.js"></script><!-- jQuery--><script src="//code.jquery.com/jquery-3.1.1.js"></script><!-- Login script--><script src="js/events-login.js"></script></body></html>
\ No newline at end of file
diff --git a/desuto-viewer/Desuto-webviewer/views/logout.html b/desuto-viewer/Desuto-webviewer/views/logout.html
deleted file mode 100644
index a563178..0000000
--- a/desuto-viewer/Desuto-webviewer/views/logout.html
+++ /dev/null
@@ -1 +0,0 @@
-<!DOCTYPE html><html lang="en"><head><title></title><link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"><link rel="stylesheet" href="stylesheets/theme.css"><link rel="stylesheet" href="stylesheets/login.css"></head><body><div class="container"><section class="loginform cf"><h1 class="centered"></h1><!--form(name='login', action='', method='post', accept-charset='utf-8')--><p class="centered" id="user">Logged in as user  ()</p><ul class="centered"><input id="logout" type="submit" value="Logout"></ul></section></div><!-- App settings--><script src="js/app-settings.js"></script><!-- jQuery--><script src="//code.jquery.com/jquery-2.1.3.js"></script><!-- Login script--><script src="js/events-login.js"></script></body></html>
\ No newline at end of file
diff --git a/desuto-viewer/Desuto-webviewer/views/upload.html b/desuto-viewer/Desuto-webviewer/views/upload.html
deleted file mode 100644
index 859ec83..0000000
--- a/desuto-viewer/Desuto-webviewer/views/upload.html
+++ /dev/null
@@ -1 +0,0 @@
-<!DOCTYPE html><html lang="en"><head><title></title><link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"><link rel="stylesheet" href="stylesheets/theme.css"><link rel="stylesheet" href="stylesheets/login.css"><link rel="stylesheet" href="stylesheets/upload.css"></head><body><section class="loginform cf"><h1 class="centered"></h1><div class="resumable-error"> Your browser, unfortunately, is not supported by Resumable.js. The library requires support for <a href="http://www.w3.org/TR/FileAPI/">the HTML5 File API </a>along with <a href="http://www.w3.org/TR/FileAPI/#normalization-of-params">file slicing</a></div><div class="resumable-drop"><span>Drop image files here to upload or </span><a class="resumable-browse">select from your computer</a></div><div class="resumable-progress"><table><tr><td width="100%"><div class="progress-container"><div class="progress-bar"></div></div></td><td class="progress-text" nowrap="nowrap"></td><td class="progress-pause" nowrap="nowrap"><a class="progress-resume-link" href="#" onclick="r.upload(); return(false);"><i class="fa fa-play" title="Resume upload"></i></a><a class="progress-pause-link" href="#" onclick="r.pause(); return(false);"><i class="fa fa-pause" title="Pause upload"></i></a><a class="progress-cancel-link" href="#" onclick="r.cancel(); return(false);"><i class="fa fa-stop" title="Cancel upload"></i></a></td></tr></table><ul class="resumable-list"></ul></div></section><!-- App settings--><script src="js/app-settings.js"></script><!-- Socket.IO--><script src="//cdn.socket.io/socket.io-1.3.5.js"></script><!-- jQuery--><script src="//code.jquery.com/jquery-2.1.3.js"></script><!-- Resumable.js--><script src="js/resumable.js"></script><!-- Upload script--><script src="js/events-upload.js"></script></body></html>
\ No newline at end of file
diff --git a/desuto-viewer/Desuto-webviewer/views/viewer.html b/desuto-viewer/Desuto-webviewer/views/viewer.html
deleted file mode 100644
index a48e5cc..0000000
--- a/desuto-viewer/Desuto-webviewer/views/viewer.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html><html><head><title></title><link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"><link rel="stylesheet" href="stylesheets/jquery.fancybox.min.css"><!-- Latest compiled and minified CSS--><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme--><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><link rel="stylesheet" href="stylesheets/jquery.simplecolorpicker.css"><link rel="stylesheet" href="stylesheets/jquery.simplecolorpicker-fontawesome.css"><link rel="stylesheet" href="stylesheets/theme.css"></head><body><nav class="navbar navbar-default"><div class="container-fluid"><div class="navbar-header"><button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="#">Desuto</a></div><div class="collapse navbar-collapse" id="navbar"><ul class="nav navbar-nav"><li class="active"><a href="#">Home</a></li><li><a href="#about">About</a></li><li><a href="/upload">Upload new images</a></li></ul><ul class="nav navbar-nav navbar-right"><li class="dropdown"><a class="dropdown-toggle" href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="caret"></span></a><ul class="dropdown-menu"><!-- Footer#footer
-  span Logged in as a&nbsp;
-    if roles.indexOf(admin) > -1
-      strong pathologist ()
-    else
-      strong user ()
-    | :
-    a(href='/logout') logout--><li><a href="/logout">Logout</a></li></ul></li></ul></div></div></nav><!-- /.nav-collapse--><div class="container-fluid" id="maincontainer"><!-- Content container--><div id="container"><div id="left"><!-- Navbar (top)--><div id="menu-top"><!-- Toolbar--><div id="toolbar-div"><!-- Pathologists only !--><!-- Drawing tools wrapper--><div id="tools-drawing-container"><span class="title">Draw</span><select id="normal" name="normal"><optgroup label="Regions"><option value="Green" style="background: #229922; color: #FFF"> Ra. Normal</option><option value="Blue" style="background: #222299; color: #FFF"> Rb. Susp. Gleason 3</option><option value="Red" style="background: #992222; color: #FFF"> Rc. Susp. Gleason 3-4</option><option value="Red" style="background: #992222; color: #FFF"> Rd. Susp. Gleason 4</option><option value="Black" style="background: #222222; color: #FFF"> Re. Susp. Gleason 4-5</option><option value="Black" style="background: #222222; color: #FFF"> Rf. Susp. Gleason 5</option></optgroup></select><!--select#colorpicker(name='colorpicker')option(value='#000000') Black
-option(value='#1558ea') Blue
-option(value='#51b749') Green
-option(value='#fbd75b') Yellow
-option(value='#dc2127') Red--><!-- Tools for drawing--><div id="tools-drawing"><!-- <div class="tool_button" id="tool_save" title="Save Tool"></div>--><div class="tool_button" id="tool_select" title="Select Tool"></div><div class="tool_button" id="tool_line" title="Line Tool"></div><div class="tool_button" id="tool_rect" title="Rectangle Tool"></div><div class="tool_button" id="tool_ellipse" title="Ellipse Tool"></div><div class="tool_button" id="tool_fhpath" title="Pencil Tool"></div><!-- <div class="tool_button" id="tool_path" title="Path Tool"></div>--></div></div><!-- Annotation button--><div id="annotation-menu"><button class="btn btn-primary" id="toggle-annotation" title="Press (ESC) to toggle mode">Start Annotating</button></div><!-- Tools for the viewer--><div id="tools-viewer"><span>View</span><a class="toolbar-button" id="zoom-in" href="#zoom-in" title="Zoom In"><i class="fa fa-search-plus"></i></a><a class="toolbar-button" id="zoom-out" href="#zoom-out" title="Zoom Out"><i class="fa fa-search-minus"></i></a><a class="toolbar-button" id="home" href="#home" title="Home"><i class="fa fa-home"></i></a><a class="toolbar-button" id="zoom-1x" href="#zoom-5x" title="Zoom to 5 times"><span><strong>1</strong><small>x</small></span></a><a class="toolbar-button" id="zoom-5x" href="#zoom-5x" title="Zoom to 5 times"><span><strong>5</strong><small>x</small></span></a><a class="toolbar-button" id="zoom-10x" href="#zoom-10x" title="Zoom to 10 times"><span><strong>10</strong><small>x</small></span></a><a class="toolbar-button" id="zoom-20x" href="#zoom-20x" title="Zoom to 20 times"><span><strong>20</strong><small>x</small></span></a><a class="toolbar-button" id="zoom-40x" href="#zoom-40x" title="Zoom to 40 times"><span><strong>40</strong><small>x</small></span></a></div></div></div><!-- Clear floats--><!-- <div class="clear"></div>--><div id="openseadragon-container"><!-- OpenSeadragon--><div id="openseadragon"></div><!-- OpenSeadragon (features)--><div id="openseadragon-features"></div><!-- SVG-Edit--><!-- Is inserted dynamically via JS now--><!-- Context menu--><ul class="contextMenu" id="cmenu_canvas"><li><a href="#cut">Cut</a></li><li><a href="#copy">Copy</a></li><li><a href="#paste">Paste</a></li><li><a href="#paste_in_place">Paste in Place</a></li><li class="separator"><a href="#delete">Delete</a></li><!--<li><a href="#move_front">Bring to Front<span class="shortcut">SHFT+CTRL+]</span></a></li>
-<li><a href="#move_back">Send to Back<span class="shortcut">SHFT+CTRL+[</span></a></li>
---></ul></div></div><!-- Current annotation details--><div id="annotation-details"><h4>Annotation details</h4><!-- Annotations container (temporary solution)--><div id="annotation-container"><div class="float" id="annotation-text"><span>Annotation description text</span><textarea id="annotation" placeholder="Enter annotation here"></textarea></div><div class="float" id="annotation-stats"><span>Characteristics</span><div></div></div><div id="annotation-patch"><p>Preview</p><img src="https://placehold.it/200?text=Preview"><p><a href="javascript:;" data-fancybox>Search for similar regions</a></p></div></div></div><!-- Annotations tooltip--><div id="annotation-tooltip"><div>Annotation placeholder</div></div><!-- Use any element to open the sidenav--><div id="sidenavMenu"><div onclick="openNav(&quot;imagesSidenav&quot;)"><i class="fa fa-image"></i><span>Images</span></div><div onclick="openNav(&quot;featuresSidenav&quot;)"><i class="fa fa-bar-chart"></i><span>Features</span></div></div></div></div><div class="sidenav" id="imagesSidenav"><a class="closebtn" href="javascript:void(0)" onclick="closeNav(&quot;imagesSidenav&quot;)">×</a><!-- Image List--><div id="image-list"><h2>Images</h2><p>Image list</p><ul id="image-list-entries"></ul></div></div><div class="sidenav" id="featuresSidenav"><a class="closebtn" href="javascript:void(0)" onclick="closeNav(&quot;featuresSidenav&quot;)">×</a><!-- Feature List--><div id="feature-list"><h2>Features</h2><p>Feature opacity</p><input id="feature-opacity" type="range" min="0" max="100" step="1"><label id="feature-opacity-label" for="feature-opacity">--%</label><p>Feature list</p><ul id="feature-list-entries"><li><a class="feature-link active" href="#none">none</a></li></ul></div></div><!-- ********************--><!-- Javascript libraries--><!-- ********************--><!-- Values from server--><script>annotator = '';
-defaultImage = '2020-6.bif.tif';<!--| defaultImage = '#{images[0]}';--></script><!-- D3--><!--script(src='js/d3.min.js', charset='utf-8')--><!-- App settings--><script src="js/app-settings.js"></script><!-- jQuery--><script src="//code.jquery.com/jquery-2.1.3.js"></script><!-- jQuery UI--><script src="//code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script><!-- Polyfills--><script src="js/polyfills/pathseg.js"></script><!-- PouchDB--><script src="js/pouchdb/pouchdb-6.1.0.min.js"></script><script src="js/pouchdb/pouchdb.authentication.js"></script><!-- Set up DB--><script src="js/db.js"></script><!-- OpenSeadragon lib--><script src="js/openseadragon/openseadragon.js"></script><script src="js/openseadragon/openseadragon-svg-overlay.js"></script><script src="js/openseadragon/openseadragon-scalebar.js"></script><script src="js/openseadragon/openseadragon-viewerinputhook.js"></script><script src="js/openseadragon/openseadragon-imaginghelper.js"></script><!-- underscore.js--><script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script><!-- qTip--><script src="//cdn.jsdelivr.net/qtip2/2.2.1/jquery.qtip.js"></script><!-- Bootstrap--><script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><!--//////////////////--><!-- jQuery Plugins //--><!--//////////////////--><!-- Fancybox--><script src="js/jquery.fancybox.min.js"></script><!-- Hotkeys--><script src="js/jquery-plugins/jquery.hotkeys.min.js"></script><!-- Load SVG icons from a single file--><script src="js/jquery-plugins/jquery.svgicons.js"></script><!-- jQuery SVG manipulation--><script src="js/jquery-plugins/jquery-svg.js"></script><!-- Context menu--><script src="js/jquery-plugins/jquery.contextMenu.js"></script><!-- Throttled resize--><!-- <script src="js/jquery-plugins/jquery.debouncedresize.js"></script>--><!-- Throttle / Debounce--><script src="js/jquery-plugins/jquery.ba-throttle-debounce.min.js"></script><!-- CouchDB--><script src="js/jquery-plugins/jquery.couch.js"></script><!--//////////////////--><!--    SVG-Edit    //--><!--//////////////////--><!-- Globals--><script src="js/svg-edit/svgedit.js"></script><!-- Browser support check--><script src="js/svg-edit/browser.js"></script><!-- Units--><script src="js/svg-edit/units.js"></script><!-- SVG transformations--><script src="js/svg-edit/svgtransformlist.js"></script><!-- SVG Utils--><script src="js/svg-edit/svgutils.js"></script><!-- Pathologists only !--><!-- Math functions--><script src="js/svg-edit/math.js"></script><!-- Color picker--><script src="js/jquery-plugins/jquery.simplecolorpicker.js"></script><!-- Manage history--><script src="js/svg-edit/history.js"></script><!-- Coordinates system--><script src="js/svg-edit/coords.js"></script><!-- Recalculate (not sure)--><script src="js/svg-edit/recalculate.js"></script><!-- Selection of objects--><script src="js/svg-edit/select.js"></script><!-- Drawing--><script src="js/svg-edit/draw.js"></script><!-- Path definition--><script src="js/svg-edit/path.js"></script><!-- Touch events--><script src="js/svg-edit/touch.js"></script><!-- Sanitize SVG code--><script src="js/svg-edit/sanitize.js"></script><!-- SVG Canvas manipulation--><script src="js/svg-edit/svgcanvas.js"></script><!-- Main code and JS files depening on it //--><!-- Main editor code--><script src="js/svg-editor.js"></script><!--If you do not wish to add extensions by URL, you can load them--><!--by creating the following file and adding by calls to svgEditor.setConfig--><script src="js/svg-edit/config.js"></script><!-- Locale--><script src="js/svg-edit/locale/locale.js"></script><!-- Context menu--><script src="js/svg-edit/contextmenu.js"></script><!-- Utils--><script src="js/utils.js"></script><!-- Main app--><script src="js/app.js"></script></body></html>
\ No newline at end of file
diff --git a/desuto-viewer/Desuto-webviewer/views/viewer.pug b/desuto-viewer/Desuto-webviewer/views/viewer.pug
index 1961e10..aa709be 100644
--- a/desuto-viewer/Desuto-webviewer/views/viewer.pug
+++ b/desuto-viewer/Desuto-webviewer/views/viewer.pug
@@ -1,381 +1,370 @@
 - var admin = 'pathologists'
 - var regions = 'regions'
 doctype html
 html
   head
     title #{title}
     link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css')
     link(rel='stylesheet', href='stylesheets/jquery.fancybox.min.css')
     link(rel='stylesheet', href='//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css')
     // Latest compiled and minified CSS
     link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', integrity='sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u', crossorigin='anonymous')
     // Optional theme
     link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css', integrity='sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp', crossorigin='anonymous')
     if !roles || roles.indexOf(admin) > -1
       link(rel='stylesheet', href='stylesheets/jquery.simplecolorpicker.css')
       link(rel='stylesheet', href='stylesheets/jquery.simplecolorpicker-fontawesome.css')
     link(rel='stylesheet', href='stylesheets/theme.css')
   body
     nav.navbar.navbar-default
       .container-fluid
         .navbar-header
           button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#navbar', aria-expanded='false', aria-controls='navbar')
             span.sr-only Toggle navigation
             span.icon-bar
             span.icon-bar
             span.icon-bar
           a.navbar-brand(href='#') Desuto
         #navbar.collapse.navbar-collapse
           ul.nav.navbar-nav
             li.active
               a(href='#') Home
             li
               a(href='#about') About
             if !roles || roles.indexOf(admin) > -1
               li
                 a(href='/upload') Upload new images
           ul.nav.navbar-nav.navbar-right
             li.dropdown
               a.dropdown-toggle(href='#', data-toggle='dropdown', role='button', aria-haspopup='true', aria-expanded='false')
                 | #{user}
                 span.caret
               ul.dropdown-menu
                 // Footer
                   #footer
                     span Logged in as a&nbsp;
                       if roles.indexOf(admin) > -1
                         strong pathologist (#{user})
                       else
                         strong user (#{user})
                       | :
                       a(href='/logout') logout
                 li
                   a(href='/logout') Logout
     // /.nav-collapse
     #maincontainer.container-fluid
       // Content container
       #container
         #left
           // Navbar (top)
           #menu-top
             // Toolbar
             #toolbar-div
               // Pathologists only !
               if !roles || roles.indexOf(admin) > -1
                 // Drawing tools wrapper
                 #tools-drawing-container
                   span.title Draw
                   if !roles || roles.indexOf(regions) > -1
                     select#normal(name='normal')
                       optgroup(label='Regions')
                         option(value='Green', style='background: #229922; color: #FFF;')  Ra. Normal
                         option(value='Blue', style='background: #222299; color: #FFF;')  Rb. Susp. Gleason 3
                         option(value='Red', style='background: #992222; color: #FFF;')  Rc. Susp. Gleason 3-4
                         option(value='Red', style='background: #992222; color: #FFF;')  Rd. Susp. Gleason 4
                         option(value='Black', style='background: #222222; color: #FFF;')  Re. Susp. Gleason 4-5
                         option(value='Black', style='background: #222222; color: #FFF;')  Rf. Susp. Gleason 5
                   else
                     select#normal(name='normal')
                       optgroup(label='1. Normal')
                         option(value='Green')  1a. Healthy glands
                         option(value='Green')  1b. Basal cells
                         option(value='Green')  1c. Bening glands, athropy
                         option(value='Green')  1d. Bening glands (smaller than normal)
                         option(value='Other')  e. Other
                       optgroup(label='2. Atypical, benign (but maybe suspicious)')
                         option(value='Yellow') 2a. Atypical
                         option(value='Yellow') 2b. PIN
                         option(value='Yellow') 2c. Other
                       optgroup(label='3. Gleason pattern 3')
                         option(value='Blue') 3a. “classic”
                         option(value='Blue') 3b.	“invasive - infiltrating non-neoplastic tissue”
                         option(value='Blue') 3c.	“mucinous lakes”
                         option(value='Blue') 3d.	Other (to be specified in text)
                       optgroup(label='4. Gleason pattern 4')
                         option(value='Red') 4a. “classic"
                         option(value='Red') 4b.	“cribriform”
                         option(value='Red') 4c.	“prostatic ductal adenocarcinoma“
                         option(value='Red') 4d.	“hypernephromatiod”
                         option(value='Red') 4e.	“invasive - infiltrating non-neoplastic tissue”
                         option(value='Red') 4f. “mucinous lakes”
                         option(value='Red') 4g.	Other (to be specified in text)
                       optgroup(label='5. Gleason pattern 5')
                         option(value='Black') 5a.	“classic” (Signet ring-cell like)
                         option(value='Black') 5b.	“cribriform with central necrosis”
                         option(value='Black') 5c.	Other (to be specified in text)
                       optgroup(label='6. Other type of carcinoma')
                         option(value='Purple') 6a.	Neuroendocrine cells (eosinophilic granules)
                         option(value='Purple') 6b.	Small cell carcinoma of prostate (Does NOT assign Gleason grade)
                       optgroup(label='7. Normal other structures')
                         option(value='Purple') 7a.	Necrosis
                         option(value='Purple') 7b.	Stroma
                         option(value='Purple') 7c.	Inflammatory cells, lymphocytes
                         option(value='Purple') 7d.	Inflammatory cells, neutrophils
                         option(value='Purple') 7e.	Vessel
                         option(value='Purple') 7f.	Nerves
                         option(value='Purple') 7g.	Fat
                         option(value='Purple') 7h.	Folding artefact
                         option(value='Purple') 7i.	Scanning artefact
                         option(value='Purple') 7j.	Other (to be specified in text)
                   // Tools for drawing
                   #tools-drawing
                     // <div class="tool_button" id="tool_save" title="Save Tool"></div>
                     #tool_select.tool_button(title='Select Tool')
                     #tool_line.tool_button(title='Line Tool')
                     #tool_rect.tool_button(title='Rectangle Tool')
                     #tool_ellipse.tool_button(title='Ellipse Tool')
                     #tool_fhpath.tool_button(title='Pencil Tool')
                 // Annotation button
                 #annotation-menu
                   button.btn.btn-primary#toggle-annotation(title='Press (ESC) to toggle mode') Start Annotating
                   #sync
                     i.fa.fa-spin.fa-refresh
                     //span &nbsp; Syncing DB...
               // Tools for the viewer
               #tools-viewer
                 span View
                 a#zoom-in.toolbar-button(href='#zoom-in', title='Zoom In')
                   i.fa.fa-search-plus
                 a#zoom-out.toolbar-button(href='#zoom-out', title='Zoom Out')
                   i.fa.fa-search-minus
                 a#home.toolbar-button(href='#home', title='Home')
                   i.fa.fa-home
                 a#zoom-1x.toolbar-button(href='#zoom-5x', title='Zoom to 5 times')
                   span
                     strong 1
                     small x
                 a#zoom-5x.toolbar-button(href='#zoom-5x', title='Zoom to 5 times')
                   span
                     strong 5
                     small x
                 a#zoom-10x.toolbar-button(href='#zoom-10x', title='Zoom to 10 times')
                   span
                     strong 10
                     small x
                 a#zoom-20x.toolbar-button(href='#zoom-20x', title='Zoom to 20 times')
                   span
                     strong 20
                     small x
                 a#zoom-40x.toolbar-button(href='#zoom-40x', title='Zoom to 40 times')
                   span
                     strong 40
                     small x
           // Clear floats
           // <div class="clear"></div>
           #openseadragon-container
             #locks.unselectable
               i#tl-lock.fa.fa-lock
                 span Annotation mode - View locked
               i#tr-lock.fa.fa-lock
               i#bl-lock.fa.fa-lock
               i#br-lock.fa.fa-lock
             // OpenSeadragon
             #openseadragon
             // OpenSeadragon (features)
             #openseadragon-features
             // SVG-Edit
             // Is inserted dynamically via JS now
             // Context menu
             ul#cmenu_canvas.contextMenu
               li
                 a(href='#cut') Cut
               li
                 a(href='#copy') Copy
               li
                 a(href='#paste') Paste
               li
                 a(href='#paste_in_place') Paste in Place
               li.separator
                 a(href='#delete') Delete
 
         // Current annotation details
         #annotation-details
           // Annotations container (temporary solution)
           #annotation-container
             #annotation-text.float
               p
                 strong Annotation description text
               textarea#annotation(placeholder='Enter annotation here')
             #annotation-stats.float
               p
                 strong Characteristics
               div
             #annotation-patch.float
               p
                 strong Selected area
               img#patch-preview(src='https://placehold.it/200?text=Preview')
-              p
-                a#search-similar(href='javascript:;', data-fancybox)
-                  strong
-                    i.fa.fa-external-link
-                    | &nbsp;Search for similar images
-              p
-                strong
-                  small Similar patches in image @&nbsp;
-                    span#similar-patches-magnification
-              #similar-patches
-              i#patches-loader.fa.fa-refresh.fa-spin
 
         // Annotations tooltip
         #annotation-tooltip
           div Annotation placeholder
 
         // Use any element to open the sidenav
         #sidenavMenu
           div(onclick='openNav("imagesSidenav")')
             i.fa.fa-image
             span Images
           div(onclick='openNav("featuresSidenav")')
             i.fa.fa-bar-chart
             span Features
 
     #imagesSidenav.sidenav
       a.closebtn(href='javascript:void(0)', onclick='closeNav("imagesSidenav")') ×
       // Image List
       #image-list
         h2 Images
         #imagesets
           if images && imagesets
             each imageset in imagesets
               h3= imageset
               div
                 ul#image-list-entries
                   each image, index in images[imageset]
                     li
                       a.image-link(href='?image=' + image) #{image.substr(image.indexOf('/') + 1)}
 
     #featuresSidenav.sidenav
       a.closebtn(href='javascript:void(0)', onclick='closeNav("featuresSidenav")') ×
       // Feature List
       #feature-list
         h2 Features
         p Feature opacity
         input#feature-opacity(type='range', min='0', max='100', step='1')
         label#feature-opacity-label(for='feature-opacity') --%
         p Feature list
         ul#feature-list-entries
           li
             a.feature-link.active(href='#none') none
           if features
             each feature in features
               li
                 a.feature-link(href='#' + feature) #{feature}
 
     // ********************
     // Javascript libraries
     // ********************
 
     // Values from server
     script
       | annotator = '#{user}';
       | defaultImage = 'ALABplus4M.tif';
 
     // Configuration (modifiable)
     script(src='js/config/config.js')
 
     // jQuery
     script(src='//code.jquery.com/jquery-2.1.3.js')
     // jQuery UI
     script(src='//code.jquery.com/ui/1.12.1/jquery-ui.min.js')
 
     // Polyfills
     script(src='js/polyfills/pathseg.js')
 
     // PouchDB
     script(src='js/pouchdb/pouchdb-6.2.0.min.js')
     script(src='js/pouchdb/pouchdb.find.min.js')
     script(src='js/pouchdb/pouchdb.authentication.js')
 
     // Set up DB
     script(src='js/db.js')
 
     // OpenSeadragon lib
     script(src='js/openseadragon/openseadragon.js')
     script(src='js/openseadragon/openseadragon-svg-overlay.js')
     script(src='js/openseadragon/openseadragon-scalebar.js')
     script(src='js/openseadragon/openseadragon-viewerinputhook.js')
     script(src='js/openseadragon/openseadragon-imaginghelper.js')
     // underscore.js
     script(src='//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js')
     // qTip
     script(src='//cdn.jsdelivr.net/qtip2/2.2.1/jquery.qtip.js')
     // Bootstrap
     script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js', integrity='sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa', crossorigin='anonymous')
 
     ////////////////////
     // jQuery Plugins //
     ////////////////////
 
     // Fancybox
     script(src='js/jquery.fancybox.min.js')
     // Hotkeys
     script(src='js/jquery-plugins/jquery.hotkeys.min.js')
     // Load SVG icons from a single file
     script(src='js/jquery-plugins/jquery.svgicons.js')
     // jQuery SVG manipulation
     script(src='js/jquery-plugins/jquery-svg.js')
     // Context menu
     script(src='js/jquery-plugins/jquery.contextMenu.js')
     // Throttle / Debounce
     script(src='js/jquery-plugins/jquery.ba-throttle-debounce.min.js')
     // CouchDB
     script(src='js/jquery-plugins/jquery.couch.js')
 
     // Utils
     script(src='js/utils.js')
 
     ////////////////////
     //    SVG-Edit    //
     ////////////////////
 
     // Globals
     script(src='js/svg-edit/svgedit.js')
     // Browser support check
     script(src='js/svg-edit/browser.js')
     // Units
     script(src='js/svg-edit/units.js')
     // SVG transformations
     script(src='js/svg-edit/svgtransformlist.js')
     // SVG Utils
     script(src='js/svg-edit/svgutils.js')
 
     // Pathologists only !
     if !roles || roles.indexOf(admin) > -1
 
       // Math functions
       script(src='js/svg-edit/math.js')
       // Color picker
       script(src='js/jquery-plugins/jquery.simplecolorpicker.js')
       // Manage history
       script(src='js/svg-edit/history.js')
       // Coordinates system
       script(src='js/svg-edit/coords.js')
       // Recalculate (not sure)
       script(src='js/svg-edit/recalculate.js')
       // Selection of objects
       script(src='js/svg-edit/select.js')
       // Drawing
       script(src='js/svg-edit/draw.js')
       // Path definition
       script(src='js/svg-edit/path.js')
       // Touch events
       script(src='js/svg-edit/touch.js')
       // Sanitize SVG code
       script(src='js/svg-edit/sanitize.js')
       // SVG Canvas manipulation
       script(src='js/svg-edit/svgcanvas.js')
 
       // Main code and JS files depening on it //
 
       // Main editor code
       script(src='js/svg-editor.js')
       //If you do not wish to add extensions by URL, you can load them
       //by creating the following file and adding by calls to svgEditor.setConfig
       script(src='js/svg-edit/config.js')
       // Locale
       script(src='js/svg-edit/locale/locale.js')
       // Context menu
       script(src='js/svg-edit/contextmenu.js')
 
     // Main app
     script(src='js/app-main.js')
diff --git a/desuto-viewer/Dockerfile b/desuto-viewer/Dockerfile
index 167849d..f03bf0b 100755
--- a/desuto-viewer/Dockerfile
+++ b/desuto-viewer/Dockerfile
@@ -1,39 +1,31 @@
-FROM node:latest
-ARG COUCHDB_FRONTEND_ROOT_URL
+FROM node:10
+ARG COUCHDB_ROOT_URL
 ARG COUCHDB_BACKEND_ROOT_URL
-ARG PARADISE_ROOT_URL
-ARG RETRIEVAL_INTERFACE_ROOT_URL
+ARG COUCHDB_DB_NAME
 ARG IIP_ROOT_URL
 ARG SLIDEPROPS_ROOT_URL
+ARG WSI_BASE_DIR
 
 # Inform about used servers
-RUN echo "Used servers : ${COUCHDB_FRONTEND_ROOT_URL},${COUCHDB_BACKEND_ROOT_URL},${PARADISE_ROOT_URL},${RETRIEVAL_INTERFACE_ROOT_URL},${IIP_ROOT_URL},${SLIDEPROPS_ROOT_URL}"
+RUN echo "Used variables : CouchDB (Frontend) - ${COUCHDB_ROOT_URL}, CouchDB (Backend) - ${COUCHDB_BACKEND_ROOT_URL}, CouchDB Name - ${COUCHDB_DB_NAME}, IIP - ${IIP_ROOT_URL}, SlideProps - ${SLIDEPROPS_ROOT_URL}, WSI Base Path - ${WSI_BASE_DIR}"
+
+# Install envsubst
+RUN apt-get update && apt-get install -y gettext-base
 
 WORKDIR /usr/src/app
 
 # Copy dependencies file and install them
 COPY ./Desuto-webviewer/package*.json ./
 RUN npm install
 
 # Copy source code (node_modules ignore using .dockerignore file)
 COPY ./Desuto-webviewer ./
 
-# Replace references to servers with the right hostname
-RUN sed -i "s_couchDBRootURL\s*:\s*'.*'_couchDBRootURL: '${COUCHDB_FRONTEND_ROOT_URL}'_g" public/js/config/config.js
-RUN sed -i "s_paradiseRootURL\s*:\s*'.*'_paradiseRootURL: '${PARADISE_ROOT_URL}'_g" public/js/config/config.js
-RUN sed -i "s_retrievalInterfaceRootURL\s*:\s*'.*'_retrievalInterfaceRootURL: '${RETRIEVAL_INTERFACE_ROOT_URL}'_g" public/js/config/config.js
-RUN sed -i "s_iipRootURL\s*:\s*'.*'_iipRootURL: '${IIP_ROOT_URL}'_g" public/js/config/config.js
-RUN sed -i "s_slidePropertiesRootURL\s*:\s*'.*'_slidePropertiesRootURL: '${SLIDEPROPS_ROOT_URL}'_g" public/js/config/config.js
-
-# Replace backend references to servers with the right hostname
-RUN sed -i "s_\"couchDBRootURL\"\s*:\s*\".*\"_\"couchDBRootURL\" : \"${COUCHDB_BACKEND_ROOT_URL}\"_g" config.json
-
-# Replace paths with dockerized paths
-RUN sed -i "s_iipBaseDir\s*:\s*'.*'_iipBaseDir: '/slideviewerdata/'_g" public/js/config/config.js
-RUN sed -i "s_\"baseDir\"\s*:\s*\".*\"_\"baseDir\" : \"/slideviewerdata/\"_g" config.json
+# Run environment variable substitution
+RUN envsubst < public/js/config/config.tmpl.js > public/js/config/config.js
 
 # Expose the app's port
 EXPOSE 3000
 
 # Start the application
 CMD ["npm", "start"]
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
new file mode 100755
index 0000000..017f4c5
--- /dev/null
+++ b/docker-compose.override.yml
@@ -0,0 +1,27 @@
+version: "3"
+services:
+
+  # Node.js server for the Web viewer and annotation tool
+  webviewer:
+    ports:
+      - 3000:3000
+      - 9229:9229
+    command: ["node", "--inspect=0.0.0.0:9229", "app.js"]
+    volumes:
+      - ./desuto-viewer/Desuto-webviewer:/usr/src/app
+
+  # IIPImage server for generating the image patches
+  iipsrv:
+    build: ./desuto-iipsrv
+    volumes:
+        - ${SLIDEVIEWERDATA_LOCAL_PATH}:/slideviewerdata
+
+  # Python server for getting slide properties using openslide
+  slideprops:
+    build: ./desuto-slideproperties
+    volumes:
+        - ${SLIDEVIEWERDATA_LOCAL_PATH}:/slideviewerdata
+
+# Shared volume for uploaded images
+volumes:
+  upload-volume:
diff --git a/docker-compose.yml b/docker-compose.yml
index 070ed60..0fbd8fa 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,116 +1,66 @@
 version: "3"
 services:
 
   # Proxy facade for all services
   proxy:
     build: ./desuto-proxy
     depends_on:
-      - mysql
       - couchdb
-      - uploads
-      - images
-      - paradise-gf
-      - retrieval
       - webviewer
       - iipsrv
       - slideprops
     ports:
       - 80:80
 
-  # MySQL server for storing image information (URLs, modalities, etc.)
-  mysql:
-    image: mariadb
-    restart: always
-    environment:
-      MYSQL_ROOT_PASSWORD: $$MARIA-15-mysql!
-      MYSQL_DATABASE: paradise
-      MYSQL_USER: paradise
-      MYSQL_PASSWORD: $$PWDforParaD1SE!
-    volumes:
-      - ./data/all-dmli-pubmed-info.sql:/docker-entrypoint-initdb.d/dump.sql
-    expose:
-      - 3306
-
   # CouchDB server for storing image annotation data
   couchdb:
     build: ./desuto-couchdb
-    restart: always
-    expose:
-      - 5984
-
-  # nginx server for serving images that are uploaded to the retrieval interface
-  uploads:
-    image: nginx:alpine
-    restart: always
-    volumes:
-      - upload-volume:/usr/share/nginx/html/uploads/:ro
-    expose:
-      - 80
-
-  # nginx server for serving images (patches) contained in the visual indices
-  images:
-    image: nginx:alpine
-    restart: always
-    volumes:
-      - ./data/images/:/usr/share/nginx/html/images/:ro
-    expose:
-      - 80
-
-  # GlassFish application server hosting the ParaDISE engine and WebServices
-  paradise-gf:
-    build: ./paradise-gf
-    volumes:
-      - upload-volume:/uploads/
-      - ./data/paradise-files/:/data/paradise
     environment:
-      - ADMIN_PASSWORD=$$pWd4glassF1SH!
-    expose:
-      - 8080
-      - 4848
+      - COUCHDB_USER=${COUCHDB_ADMIN_USER}
+      - COUCHDB_PASSWORD=${COUCHDB_ADMIN_PASS}
+      - COUCHDB_PROTOCOL=${COUCHDB_PROTOCOL}
+      - COUCHDB_HOST=${COUCHDB_HOST}
+      - COUCHDB_PORT=${COUCHDB_PORT}
+      - COUCHDB_DB_NAME=${COUCHDB_DB_NAME}
+    ports:
+      - 5984:5984
 
-  # Apache server for the retrieval interface
-  retrieval:
-    build:
-      context: ./desuto-retrieval
-      args:
-        - PARADISE_ROOT_URL=${PARADISE_ROOT_URL}
-        - IIP_ROOT_URL=${IIP_ROOT_URL}
-        - VIEWER_ROOT_URL=${VIEWER_ROOT_URL}
-        - SLIDEPROPS_ROOT_URL=${SLIDEPROPS_ROOT_URL}
     restart: always
-    volumes:
-        - ${SLIDEVIEWERDATA_LOCAL_PATH}:/slideviewerdata
-    expose:
-      - 80
 
   # Node.js server for the Web viewer and annotation tool
   webviewer:
     build:
       context: ./desuto-viewer
       args:
-        - RETRIEVAL_INTERFACE_ROOT_URL=${RETRIEVAL_INTERFACE_ROOT_URL}
-        - PARADISE_ROOT_URL=${PARADISE_ROOT_URL}
         - IIP_ROOT_URL=${IIP_ROOT_URL}
         - SLIDEPROPS_ROOT_URL=${SLIDEPROPS_ROOT_URL}
-        - COUCHDB_FRONTEND_ROOT_URL=${COUCHDB_FRONTEND_ROOT_URL}
+        - COUCHDB_ROOT_URL=${COUCHDB_ROOT_URL}
         - COUCHDB_BACKEND_ROOT_URL=${COUCHDB_BACKEND_ROOT_URL}
+        - COUCHDB_DB_NAME=${COUCHDB_DB_NAME}
+        - WSI_BASE_DIR=${WSI_BASE_DIR}
+    environment:
+      - COUCHDB_ROOT_URL=${COUCHDB_ROOT_URL}
+      - COUCHDB_BACKEND_ROOT_URL=${COUCHDB_BACKEND_ROOT_URL}
+      - TEMP_DIR=${TEMP_DIR}
+      - WSI_BASE_DIR=${WSI_BASE_DIR}
+      - WSI_UPLOADED_DIR=${WSI_UPLOADED_DIR}
+      - WSI_CONVERTED_DIR=${WSI_CONVERTED_DIR}
+      - WSI_OVERLAYS_DIR=${WSI_OVERLAYS_DIR}
     volumes:
         - ${SLIDEVIEWERDATA_LOCAL_PATH}:/slideviewerdata
-    expose:
-      - 3000
 
   # IIPImage server for generating the image patches
   iipsrv:
     build: ./desuto-iipsrv
     volumes:
         - ${SLIDEVIEWERDATA_LOCAL_PATH}:/slideviewerdata
 
   # Python server for getting slide properties using openslide
   slideprops:
     build: ./desuto-slideproperties
     volumes:
         - ${SLIDEVIEWERDATA_LOCAL_PATH}:/slideviewerdata
 
 # Shared volume for uploaded images
 volumes:
   upload-volume: