git » galala » commit 14854b7

New flexbox-based layout and javascript gallery

author Alberto Bertogli
2015-03-18 22:10:48 UTC
committer Alberto Bertogli
2015-06-21 18:01:09 UTC
parent 13b564f850dce167fd2f192a040e51e7afbcc63e

New flexbox-based layout and javascript gallery

This patch replaces the old layout with a new one based on flexbox, and the
galleriffic javascript gallery with a custom-made one.

It should work well both on desktop and mobile devices.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>

common.py +5 -0
static/album.css +117 -0
static/css/basic.css +0 -66
static/css/black.css +0 -57
static/css/caption.png +0 -0
static/css/galleriffic-1.css +0 -161
static/css/galleriffic-2.css +0 -150
static/css/galleriffic-3.css +0 -150
static/css/galleriffic-4.css +0 -160
static/css/galleriffic-5.css +0 -197
static/css/galleriffic-galala.css +0 -176
static/css/jush.css +0 -29
static/css/loader.gif +0 -0
static/css/loaderWhite.gif +0 -0
static/css/nextPageArrow.gif +0 -0
static/css/nextPageArrowWhite.gif +0 -0
static/css/prevPageArrow.gif +0 -0
static/css/prevPageArrowWhite.gif +0 -0
static/css/white.css +0 -57
static/galala.js +119 -0
static/index.css +45 -0
static/jquery.touchSwipe.js +2080 -0
static/js/jquery-1.3.2.js +0 -4376
static/js/jquery.galleriffic.js +0 -979
static/js/jquery.history.js +0 -168
static/js/jquery.opacityrollover.js +0 -42
static/js/jush.js +0 -515
static/style.css +0 -48
static/vector_abstract_floral_background.jpg +0 -0
templates/album.html +44 -156
templates/index.html +1 -1

diff --git a/common.py b/common.py
index eafde29..36900f2 100644
--- a/common.py
+++ b/common.py
@@ -34,6 +34,10 @@ class Image (object):
         return self.album.shortname + "/" \
                 + os.path.basename(self.realpath)
 
+    @property
+    def anchor(self):
+        return os.path.basename(self.realpath)
+
     def __cmp__(self, other):
         return cmp(self.albumpath, other.albumpath)
 
@@ -45,6 +49,7 @@ class Image (object):
         # This must match the gallery parameters, as it is given to it
         # as a json object
         return dict(
+            anchor = self.anchor,
             image = self.normalpath,
             thumb = self.thumbpath,
             title = self.title,
diff --git a/static/album.css b/static/album.css
new file mode 100644
index 0000000..d7a6f3e
--- /dev/null
+++ b/static/album.css
@@ -0,0 +1,117 @@
+
+html, body {
+    margin: 0em;
+    padding: 0em;
+}
+
+body {
+    text-align: center;
+    font-family: sans-serif;
+    background-color: #fafafa;
+    color: black;
+    font-size: 75%;
+}
+
+a {
+    text-decoration: none;
+    color: #006064;
+}
+
+a:hover {
+    text-decoration: none;
+    color: #0097a7;
+}
+
+p {
+    margin: 0;
+    padding: 0;
+}
+
+h1 {
+    margin: 0;
+    margin-bottom: 0.5em;
+}
+
+h1 {
+    padding: 0;
+    font-size: 1.1em;
+    color: #263238;
+}
+
+/*
+ * Flex layout
+ */
+
+.container {
+    display: flex;
+    height: 100%;
+}
+
+.container > .mainpic {
+    flex: 1;
+
+    margin: 0;
+}
+
+.container > .mainpic > img {
+    /* 90vh ensures that the image is never too tall to fit in the display.
+     * 90% ensures that the image is never too wide to go over the thumbnails,
+     * leaving a reasonable margin. */
+    max-height: 90vh;
+    max-width: 90%;
+
+    border: 1px solid #aaa;
+
+    /* Center */
+    margin: auto;
+}
+
+.container > .mainpic > p {
+    margin-bottom: 0.5em;
+}
+
+.container > .mainpic > p > span#title {
+    font-weight: bold;
+}
+
+.container > .thumbnails {
+    min-width: 100px;
+    max-width: 15%;
+
+    /* Simplifies default margins and paddings. */
+    font-size: 0; 
+
+    overflow-y: scroll;
+
+    /* Flex to display them nicely */
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    align-items: center;
+    justify-content: center;
+
+}
+
+.container > .thumbnails > img {
+    width: 90%;
+
+    /* Leave a small space around earch image. */
+    margin-left: 2%;
+    margin-right: 2%;
+    margin-bottom: 2%;
+
+    transition: .3s opacity;
+    opacity: 0.8;
+
+    border: 1px solid #aaa;
+}
+
+.container > .thumbnails > img:hover {
+    opacity: 1;
+}
+
+/* Div used to preload images, do not display. */
+.preload {
+    display: none;
+}
+
diff --git a/static/css/basic.css b/static/css/basic.css
deleted file mode 100644
index 880e27f..0000000
--- a/static/css/basic.css
+++ /dev/null
@@ -1,66 +0,0 @@
-html, body {
-	margin:0;
-	padding:0;
-}
-
-body{
-	text-align: center;
-	font-family: sans-serif;
-	background-color: #001100;
-	color: #094b24;
-	font-size: 75%;
-}
-
-a {
-	text-decoration: none;
-	color: #09aa24;
-}
-
-a:hover {
-	text-decoration: none;
-	color: #0c0;
-}
-
-
-p, li {
-	line-height: 1.8em;
-}
-
-h1, h2 {
-	margin: 0 0 10px 0;
-	letter-spacing: -1px;
-}
-
-h1 {
-	padding: 0;
-	font-size: 1.5em;
-	color: #333;
-}
-
-pre {
-	font-size: 1.2em;
-	line-height: 1.2em;
-	overflow-x: auto;
-}
-
-div#page {
-	width: 1100px;
-	background-color: #fff;
-	margin: 0 auto;
-	text-align: left;
-	border-color: #ddd;
-	border-style: none solid solid;
-	border-width: medium 1px 1px;
-}
-
-div#container {
-	padding: 10px;
-}
-
-div#footer {
-	clear: both;
-	color: #777;
-	margin: 0 auto;
-	padding: 20px 0 40px;
-	text-align: center;
-}
diff --git a/static/css/black.css b/static/css/black.css
deleted file mode 100644
index 6bc022b..0000000
--- a/static/css/black.css
+++ /dev/null
@@ -1,57 +0,0 @@
-body{
-	background-color: #111;
-	color: #bbb;
-}
-a{
-	color: #f70;
-}
-h2 {
-	color: #ccc;
-}
-div#page {
-	background-color: #000;
-	border-color: #222;
-}
-div#footer {
-	color: #888;
-}
-div.caption-container {
-	color: #eee;
-}
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.download {
-	margin-top: 8px;
-}
-div.photo-index {
-	color: #888;
-}
-div.navigation a.prev {
-	background-image: url(prevPageArrowWhite.gif);
-}
-div.navigation a.next {
-	background-image: url(nextPageArrowWhite.gif);
-}
-div.loader {
-	background-image: url(loaderWhite.gif);
-}
-div.slideshow img {
-	border-color: #333;
-}
-ul.thumbs li.selected a.thumb {
-	background: #fff;
-}
-div.pagination a:hover {
-	background-color: #111;
-}
-div.pagination span.current {
-	background-color: #fff;
-	border-color: #fff;
-	color: #000;
-}
\ No newline at end of file
diff --git a/static/css/caption.png b/static/css/caption.png
deleted file mode 100644
index b49e5fc..0000000
Binary files a/static/css/caption.png and /dev/null differ
diff --git a/static/css/galleriffic-1.css b/static/css/galleriffic-1.css
deleted file mode 100644
index 70383f9..0000000
--- a/static/css/galleriffic-1.css
+++ /dev/null
@@ -1,161 +0,0 @@
-div.content {
-	/* The display of content is enabled using jQuery so that the slideshow content won't display unless javascript is enabled. */
-	display: none;
-	float: right;
-	width: 550px; 
-}
-div.content a, div.navigation a {
-	text-decoration: none;
-	color: #777;
-}
-div.content a:focus, div.content a:hover, div.content a:active {
-	text-decoration: underline;
-}
-div.controls {
-	margin-top: 5px;
-	height: 23px;
-}
-div.controls a {
-	padding: 5px;
-}
-div.ss-controls {
-	float: left;
-}
-div.nav-controls {
-	float: right;
-}
-div.slideshow-container {
-	position: relative;
-	clear: both;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.loader {
-	position: absolute;
-	top: 0;
-	left: 0;
-	background-image: url('loader.gif');
-	background-repeat: no-repeat;
-	background-position: center;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.slideshow {
-
-}
-div.slideshow span.image-wrapper {
-	display: block;
-	position: absolute;
-	top: 0;
-	left: 0;
-}
-div.slideshow a.advance-link {
-	display: block;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	line-height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	text-align: center;
-}
-div.slideshow a.advance-link:hover, div.slideshow a.advance-link:active, div.slideshow a.advance-link:visited {
-	text-decoration: none;
-}
-div.slideshow img {
-	vertical-align: middle;
-	border: 1px solid #ccc;
-}
-div.download {
-	float: right;
-}
-div.caption-container {
-	
-}
-span.image-caption {
-	display: block;
-	position: absolute;
-}
-div.caption {
-	background-color: #000;
-	padding: 12px;
-	color: #ccc;
-}
-div.caption a {
-	color: #fff;
-}
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.navigation {
-	/* The navigation style is set using jQuery so that the javascript specific styles won't be applied unless javascript is enabled. */
-}
-ul.thumbs {
-	clear: both;
-	margin: 0;
-	padding: 0;
-}
-ul.thumbs li {
-	float: none;
-	padding: 0;
-	margin: 0;
-	list-style: none;
-}
-a.thumb {
-	padding: 0;
-	display: inline;
-	border: none;
-}
-ul.thumbs li.selected a.thumb {
-	color: #000;
-	font-weight: bold;
-}
-a.thumb:focus {
-	outline: none;
-}
-ul.thumbs img {
-	border: none;
-	display: block;
-}
-div.pagination {
-	clear: both;
-}
-div.navigation div.top {
-	margin-bottom: 12px;
-	height: 11px;
-}
-div.navigation div.bottom {
-	margin-top: 12px;
-}
-div.pagination a, div.pagination span.current, div.pagination span.ellipsis {
-	display: block;
-	float: left;
-	margin-right: 2px;
-	padding: 4px 7px 2px 7px;
-	border: 1px solid #ccc;
-}
-div.pagination a:hover {
-	background-color: #eee;
-	text-decoration: none;
-}
-div.pagination span.current {
-	font-weight: bold;
-	background-color: #000;
-	border-color: #000;
-	color: #fff;
-}
-div.pagination span.ellipsis {
-	border: none;
-	padding: 5px 0 3px 2px;
-}
-#captionToggle a {
-	float: right;
-	display: block;
-	background-image: url('caption.png');
-	background-repeat: no-repeat;
-	background-position: right;
-	margin-top: 5px;
-	padding: 5px 30px 5px 5px;
-}
diff --git a/static/css/galleriffic-2.css b/static/css/galleriffic-2.css
deleted file mode 100644
index 4acd367..0000000
--- a/static/css/galleriffic-2.css
+++ /dev/null
@@ -1,150 +0,0 @@
-div.content {
-	/* The display of content is enabled using jQuery so that the slideshow content won't display unless javascript is enabled. */
-	display: none;
-	float: right;
-	width: 550px; 
-}
-div.content a, div.navigation a {
-	text-decoration: none;
-	color: #777;
-}
-div.content a:focus, div.content a:hover, div.content a:active {
-	text-decoration: underline;
-}
-div.controls {
-	margin-top: 5px;
-	height: 23px;
-}
-div.controls a {
-	padding: 5px;
-}
-div.ss-controls {
-	float: left;
-}
-div.nav-controls {
-	float: right;
-}
-div.slideshow-container {
-	position: relative;
-	clear: both;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.loader {
-	position: absolute;
-	top: 0;
-	left: 0;
-	background-image: url('loader.gif');
-	background-repeat: no-repeat;
-	background-position: center;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.slideshow {
-
-}
-div.slideshow span.image-wrapper {
-	display: block;
-	position: absolute;
-	top: 0;
-	left: 0;
-}
-div.slideshow a.advance-link {
-	display: block;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	line-height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	text-align: center;
-}
-div.slideshow a.advance-link:hover, div.slideshow a.advance-link:active, div.slideshow a.advance-link:visited {
-	text-decoration: none;
-}
-div.slideshow img {
-	vertical-align: middle;
-	border: 1px solid #ccc;
-}
-div.download {
-	float: right;
-}
-div.caption-container {
-	position: relative;
-	clear: left;
-	height: 75px;
-}
-span.image-caption {
-	display: block;
-	position: absolute;
-	width: 550px;
-	top: 0;
-	left: 0;
-}
-div.caption {
-	padding: 12px;
-}
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.navigation {
-	/* The navigation style is set using jQuery so that the javascript specific styles won't be applied unless javascript is enabled. */
-}
-ul.thumbs {
-	clear: both;
-	margin: 0;
-	padding: 0;
-}
-ul.thumbs li {
-	float: left;
-	padding: 0;
-	margin: 5px 10px 5px 0;
-	list-style: none;
-}
-a.thumb {
-	padding: 2px;
-	display: block;
-	border: 1px solid #ccc;
-}
-ul.thumbs li.selected a.thumb {
-	background: #000;
-}
-a.thumb:focus {
-	outline: none;
-}
-ul.thumbs img {
-	border: none;
-	display: block;
-}
-div.pagination {
-	clear: both;
-}
-div.navigation div.top {
-	margin-bottom: 12px;
-	height: 11px;
-}
-div.navigation div.bottom {
-	margin-top: 12px;
-}
-div.pagination a, div.pagination span.current, div.pagination span.ellipsis {
-	display: block;
-	float: left;
-	margin-right: 2px;
-	padding: 4px 7px 2px 7px;
-	border: 1px solid #ccc;
-}
-div.pagination a:hover {
-	background-color: #eee;
-	text-decoration: none;
-}
-div.pagination span.current {
-	font-weight: bold;
-	background-color: #000;
-	border-color: #000;
-	color: #fff;
-}
-div.pagination span.ellipsis {
-	border: none;
-	padding: 5px 0 3px 2px;
-}
diff --git a/static/css/galleriffic-3.css b/static/css/galleriffic-3.css
deleted file mode 100644
index 335080a..0000000
--- a/static/css/galleriffic-3.css
+++ /dev/null
@@ -1,150 +0,0 @@
-div.content {
-	/* The display of content is enabled using jQuery so that the slideshow content won't display unless javascript is enabled. */
-	display: none;
-	float: right;
-	width: 550px; 
-}
-div.content a, div.navigation a {
-	text-decoration: none;
-	color: #777;
-}
-div.content a:focus, div.content a:hover, div.content a:active {
-	text-decoration: underline;
-}
-div.controls {
-	margin-top: 5px;
-	height: 23px;
-}
-div.controls a {
-	padding: 5px;
-}
-div.ss-controls {
-	float: left;
-}
-div.nav-controls {
-	float: right;
-}
-div.slideshow-container {
-	position: relative;
-	clear: both;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.loader {
-	position: absolute;
-	top: 0;
-	left: 0;
-	background-image: url('loader.gif');
-	background-repeat: no-repeat;
-	background-position: center;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.slideshow {
-
-}
-div.slideshow span.image-wrapper {
-	display: block;
-	position: absolute;
-	top: 0;
-	left: 0;
-}
-div.slideshow a.advance-link {
-	display: block;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	line-height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	text-align: center;
-}
-div.slideshow a.advance-link:hover, div.slideshow a.advance-link:active, div.slideshow a.advance-link:visited {
-	text-decoration: none;
-}
-div.slideshow img {
-	vertical-align: middle;
-	border: 1px solid #ccc;
-}
-div.download {
-	float: right;
-}
-div.caption-container {
-	position: relative;
-	clear: left;
-	height: 75px;
-}
-span.image-caption {
-	display: block;
-	position: absolute;
-	width: 550px;
-	top: 0;
-	left: 0;
-}
-div.caption {
-	padding: 12px;
-}
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.navigation {
-	/* The navigation style is set using jQuery so that the javascript specific styles won't be applied unless javascript is enabled. */
-}
-ul.thumbs {
-	clear: both;
-	margin: 0;
-	padding: 0;
-}
-ul.thumbs li {
-	float: left;
-	padding: 0;
-	margin: 5px 10px 5px 0;
-	list-style: none;
-}
-a.thumb {
-	padding: 2px;
-	display: block;
-	border: 1px solid #ccc;
-}
-ul.thumbs li.selected a.thumb {
-	background: #000;
-}
-a.thumb:focus {
-	outline: none;
-}
-ul.thumbs img {
-	border: none;
-	display: block;
-}
-div.pagination {
-	clear: both;
-}
-div.navigation div.top {
-	margin-bottom: 12px;
-	height: 11px;
-}
-div.navigation div.bottom {
-	margin-top: 12px;
-}
-div.pagination a, div.pagination span.current, div.pagination span.ellipsis {
-	display: block;
-	float: left;
-	margin-right: 2px;
-	padding: 4px 7px 2px 7px;
-	border: 1px solid #ccc;
-}
-div.pagination a:hover {
-	background-color: #eee;
-	text-decoration: none;
-}
-div.pagination span.current {
-	font-weight: bold;
-	background-color: #000;
-	border-color: #000;
-	color: #fff;
-}
-div.pagination span.ellipsis {
-	border: none;
-	padding: 5px 0 3px 2px;
-}
diff --git a/static/css/galleriffic-4.css b/static/css/galleriffic-4.css
deleted file mode 100644
index 1aad4ac..0000000
--- a/static/css/galleriffic-4.css
+++ /dev/null
@@ -1,160 +0,0 @@
-div.content {
-	/* The display of content is enabled using jQuery so that the slideshow content won't display unless javascript is enabled. */
-	display: none;
-	float: right;
-	width: 550px; 
-}
-div.content a, div.navigation a {
-	text-decoration: none;
-	color: #777;
-}
-div.content a:focus, div.content a:hover, div.content a:active {
-	text-decoration: underline;
-}
-div.controls {
-	margin-top: 5px;
-	height: 23px;
-}
-div.controls a {
-	padding: 5px;
-}
-div.ss-controls {
-	float: left;
-}
-div.nav-controls {
-	float: right;
-}
-div.slideshow-container {
-	position: relative;
-	clear: both;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.loader {
-	position: absolute;
-	top: 0;
-	left: 0;
-	background-image: url('loader.gif');
-	background-repeat: no-repeat;
-	background-position: center;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-}
-div.slideshow {
-
-}
-div.slideshow span.image-wrapper {
-	display: block;
-	position: absolute;
-	top: 0;
-	left: 0;
-}
-div.slideshow a.advance-link {
-	display: block;
-	width: 550px;
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	line-height: 502px; /* This should be set to be at least the height of the largest image in the slideshow */
-	text-align: center;
-}
-div.slideshow a.advance-link:hover, div.slideshow a.advance-link:active, div.slideshow a.advance-link:visited {
-	text-decoration: none;
-}
-div.slideshow img {
-	vertical-align: middle;
-	border: 1px solid #ccc;
-}
-div.download {
-	float: right;
-}
-div.caption-container {
-	
-}
-span.image-caption {
-	display: block;
-	position: absolute;
-}
-div.caption {
-	background-color: #000;
-	padding: 12px;
-	color: #ccc;
-}
-div.caption a {
-	color: #fff;
-}
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.navigation {
-	/* The navigation style is set using jQuery so that the javascript specific styles won't be applied unless javascript is enabled. */
-}
-ul.thumbs {
-	clear: both;
-	margin: 0;
-	padding: 0;
-}
-ul.thumbs li {
-	float: left;
-	padding: 0;
-	margin: 5px 10px 5px 0;
-	list-style: none;
-}
-a.thumb {
-	padding: 2px;
-	display: block;
-	border: 1px solid #ccc;
-}
-ul.thumbs li.selected a.thumb {
-	background: #000;
-}
-a.thumb:focus {
-	outline: none;
-}
-ul.thumbs img {
-	border: none;
-	display: block;
-}
-div.pagination {
-	clear: both;
-}
-div.navigation div.top {
-	margin-bottom: 12px;
-	height: 11px;
-}
-div.navigation div.bottom {
-	margin-top: 12px;
-}
-div.pagination a, div.pagination span.current, div.pagination span.ellipsis {
-	display: block;
-	float: left;
-	margin-right: 2px;
-	padding: 4px 7px 2px 7px;
-	border: 1px solid #ccc;
-}
-div.pagination a:hover {
-	background-color: #eee;
-	text-decoration: none;
-}
-div.pagination span.current {
-	font-weight: bold;
-	background-color: #000;
-	border-color: #000;
-	color: #fff;
-}
-div.pagination span.ellipsis {
-	border: none;
-	padding: 5px 0 3px 2px;
-}
-#captionToggle a {
-	float: right;
-	display: block;
-	background-image: url('caption.png');
-	background-repeat: no-repeat;
-	background-position: right;
-	margin-top: 5px;
-	padding: 5px 30px 5px 5px;
-}
diff --git a/static/css/galleriffic-5.css b/static/css/galleriffic-5.css
deleted file mode 100644
index e810f3f..0000000
--- a/static/css/galleriffic-5.css
+++ /dev/null
@@ -1,197 +0,0 @@
-div#container {
-	overflow: hidden;
-}
-div.content {
-	display: none;
-	clear: both;
-}
-
-div.content a, div.navigation a {
-	text-decoration: none;
-}
-div.content a:hover, div.content a:active {
-	text-decoration: underline;
-}
-
-div.navigation a.pageLink {
-	height: 77px;
-	line-height: 77px;
-}
-
-div.controls {
-	margin-top: 5px;
-	height: 23px;
-}
-div.controls a {
-	padding: 5px;
-}
-div.ss-controls {
-	float: left;
-}
-div.nav-controls {
-	float: right;
-}
-
-div.slideshow-container,
-div.loader,
-div.slideshow a.advance-link {
-	width: 510px; /* This should be set to be at least the width of the largest image in the slideshow with padding */
-}
-
-div.loader,
-div.slideshow a.advance-link,
-div.caption-container {
-	height: 502px; /* This should be set to be at least the height of the largest image in the slideshow with padding */	
-}
-
-div.slideshow-container {
-	position: relative;
-	clear: both;
-	float: left;
-	height: 532px;
-}
-
-div.loader {
-	position: absolute;
-	top: 0;
-	left: 0;
-	background-image: url('images/loader.gif');
-	background-repeat: no-repeat;
-	background-position: center;
-}
-div.slideshow span.image-wrapper {
-	display: block;
-	position: absolute;
-	top: 30px;
-	left: 0;
-}
-div.slideshow a.advance-link {
-	display: block;
-	line-height: 502px; /* This should be set to be at least the height of the largest image in the slideshow with padding */
-	text-align: center;
-}
-
-div.slideshow a.advance-link:hover,
-div.slideshow a.advance-link:active,
-div.slideshow a.advance-link:visited {
-	text-decoration: none;
-}
-div.slideshow a.advance-link:focus {
-	outline: none;
-}
-
-div.slideshow img {
-	border-style: solid;
-	border-width: 1px;
-}
-div.caption-container {
-	float: right;
-	position: relative;
-	margin-top: 30px;
-}
-span.image-caption {
-	display: block;
-	position: absolute;
-	top: 0;
-	left: 0;
-}
-
-div.caption-container, span.image-caption {
-	width: 334px;
-}
-
-div.caption {
-	padding: 0 12px;
-}
-
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.download {
-	margin-top: 8px;
-}
-div.photo-index {
-	position: absolute;
-	bottom: 0;
-	left: 0;
-	padding: 0 12px;
-}
-div.navigation-container {
-	float: left;
-	position: relative;
-	left: 50%;
-}
-div.navigation {
-	float: left;
-	position: relative;
-	left: -50%;
-}
-div.navigation a.pageLink {
-	display: block;
-	position: relative;
-	float: left;
-	margin: 2px;
-	width: 16px;
-	background-position:center center;
-	background-repeat:no-repeat;
-}
-div.navigation a.pageLink:focus {
-	outline: none;
-}
-
-ul.thumbs {
-	position: relative;
-	float: left;
-	margin: 0;
-	padding: 0;
-}
-ul.thumbs li {
-	float: left;
-	padding: 0;
-	margin: 2px;
-	list-style: none;
-}
-a.thumb {
-	padding: 1px;
-	display: block;
-}
-a.thumb:focus {
-	outline: none;
-}
-ul.thumbs img {
-	border: none;
-	display: block;
-}
-div.pagination {
-	clear: both;
-	position: relative;
-	left: -50%;
-}
-div.pagination a, div.pagination span.current, div.pagination span.ellipsis {
-	position: relative;
-	display: block;
-	float: left;
-	margin-right: 2px;
-	padding: 4px 7px 2px 7px;
-	border: 1px solid #ccc;
-}
-div.pagination a:hover {
-	text-decoration: none;
-}
-div.pagination span.current {
-	font-weight: bold;
-}
-div.pagination span.ellipsis {
-	border: none;
-	padding: 5px 0 3px 2px;
-}
-
-div.gallery-gutter {
-	clear: both;
-	padding-bottom: 20px;
-}
diff --git a/static/css/galleriffic-galala.css b/static/css/galleriffic-galala.css
deleted file mode 100644
index f132c88..0000000
--- a/static/css/galleriffic-galala.css
+++ /dev/null
@@ -1,176 +0,0 @@
-
-div.content {
-	/* The display of content is enabled using jQuery so that the
-	 * slideshow content won't display unless javascript is enabled. */
-	display: none;
-	float: right;
-	width: 880px;
-}
-div.content a, div.navigation a {
-	text-decoration: none;
-	color: #777;
-}
-div.content a:focus, div.content a:hover, div.content a:active {
-	text-decoration: underline;
-}
-div.controls {
-	margin-top: 5px;
-	height: 23px;
-}
-div.controls a {
-	padding: 5px;
-}
-div.ss-controls {
-	float: left;
-}
-div.nav-controls {
-	float: right;
-}
-
-div.slideshow-container {
-	position: relative;
-	clear: both;
-	/* This should be set to be at least the height of the largest image
-	 * in the slideshow */
-	height: 615px;
-}
-
-div.loader {
-	position: absolute;
-	top: 0;
-	left: 0;
-	background-image: url('loader.gif');
-	background-repeat: no-repeat;
-	background-position: center;
-
-	width: 850px;
-	/* This should be set to be at least the height of the largest image
-	 * in the slideshow */
-	height: 615px;
-}
-
-div.slideshow {
-
-}
-div.slideshow span.image-wrapper {
-	display: block;
-	position: absolute;
-	top: 0;
-	left: 0;
-}
-div.slideshow a.advance-link {
-	display: block;
-	width: 850px;
-
-	/* This should be set to be at least the height of the largest image
-	 * in the slideshow */
-	height: 615px;
-
-	/* This should be set to be at least the height of the largest image
-	 * in the slideshow */
-	line-height: 615px;
-	
-	text-align: center;
-}
-div.slideshow a.advance-link:hover, div.slideshow a.advance-link:active, div.slideshow a.advance-link:visited {
-	text-decoration: none;
-}
-div.slideshow img {
-	vertical-align: middle;
-	border: 1px solid #ccc;
-
-	/* Lower than the numbers above.
-	 * Sample values:
-	 *  - If width above is  850px, 800px here works well.
-	 *  - If height above is 652px, 650px here works well. */
-	max-height: 610px;
-	max-width: 800px;
-}
-div.download {
-	float: right;
-}
-div.caption-container {
-	position: relative;
-	clear: left;
-	height: 75px;
-}
-span.image-caption {
-	display: block;
-	position: absolute;
-	width: 650px;
-	top: 0;
-	left: 0;
-}
-div.caption {
-	padding: 12px;
-}
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.navigation {
-	/* The navigation style is set using jQuery so that the javascript specific styles won't be applied unless javascript is enabled. */
-}
-ul.thumbs {
-	clear: both;
-	margin: 0;
-	padding: 0;
-}
-ul.thumbs li {
-	float: left;
-	padding: 0;
-	margin: 5px 10px 5px 0;
-	list-style: none;
-}
-a.thumb {
-	padding: 2px;
-	display: block;
-	border: 1px solid #ccc;
-}
-ul.thumbs li.selected a.thumb {
-	background: #000;
-}
-a.thumb:focus {
-	outline: none;
-}
-ul.thumbs img {
-	border: none;
-	display: block;
-	max-height: 75px;
-	max-width: 75px;
-}
-div.pagination {
-	clear: both;
-}
-div.navigation div.top {
-	margin-bottom: 12px;
-	height: 11px;
-}
-div.navigation div.bottom {
-	margin-top: 12px;
-}
-div.pagination a, div.pagination span.current, div.pagination span.ellipsis {
-	display: block;
-	float: left;
-	margin-right: 2px;
-	padding: 4px 7px 2px 7px;
-	border: 1px solid #ccc;
-}
-div.pagination a:hover {
-	background-color: #eee;
-	text-decoration: none;
-}
-div.pagination span.current {
-	font-weight: bold;
-	background-color: #000;
-	border-color: #000;
-	color: #fff;
-}
-div.pagination span.ellipsis {
-	border: none;
-	padding: 5px 0 3px 2px;
-}
diff --git a/static/css/jush.css b/static/css/jush.css
deleted file mode 100644
index 07a0421..0000000
--- a/static/css/jush.css
+++ /dev/null
@@ -1,29 +0,0 @@
-.jush { color: black; }
-.jush-htm_com, .jush-com, .jush-one, .jush-php_com, .jush-php_one, .jush-js_one { color: gray; }
-.jush-php { color: #000033; background-color: #FFF0F0; }
-.jush-php_quo, .jush-quo, .jush-php_eot, .jush-apo, .jush-py_rlapo, .jush-py_rlquo, .jush-py_rapo, .jush-py_rquo, .jush-py_lapo, .jush-py_lquo, .jush-sql_apo, .jush-sqlite_apo, .jush-sql_quo, .jush-sqlite_quo, .jush-sql_eot { color: green; }
-.jush-php_apo { color: #009F00; }
-.jush-php_quo_var, .jush-php_var, .jush-sql_var { font-style: italic; }
-.jush-php_halt2 { background-color: white; color: black; }
-.jush-tag_css, .jush-att_css .jush-att_quo, .jush-att_css .jush-att_apo, .jush-att_css .jush-att_val { color: black; background-color: #FFFFE0; }
-.jush-tag_js, .jush-att_js .jush-att_quo, .jush-att_js .jush-att_apo, .jush-att_js .jush-att_val, .jush-css_js { color: black; background-color: #F0F0FF; }
-.jush-tag { color: navy; }
-.jush-att, .jush-att_js, .jush-att_css { color: teal; }
-.jush-att_quo, .jush-att_apo, .jush-att_val { color: purple; }
-.jush-ent { color: purple; }
-.jush-js_reg { color: navy; }
-.jush-php_sql .jush-php_quo, .jush-php_sql .jush-php_apo,
-.jush-php_sqlite .jush-php_quo, .jush-php_sqlite .jush-php_apo,
-.jush-php_pgsql .jush-php_quo, .jush-php_pgsql .jush-php_apo
-{ background-color: #FFBBB0; }
-.jush-bac, .jush-php_bac, .jush-bra, .jush-pgsql .jush-sqlite_quo { color: red; }
-.jush-num, .jush-clr { color: #007f7f; }
-
-.jush a { color: navy; }
-.jush-sql a { font-weight: bold; }
-.jush-tag a,
-.jush-php_phpini .jush-php_apo a, .jush-php_phpini .jush-php_quo a,
-.jush-php_sql .jush-php_apo a, .jush-php_sql .jush-php_quo a,
-.jush-php_sqlite .jush-php_apo a, .jush-php_sqlite .jush-php_quo a,
-.jush-php_pgsql .jush-php_apo a, .jush-php_pgsql .jush-php_quo a
-{ color: inherit; color: expression(parentNode.currentStyle.color); }
diff --git a/static/css/loader.gif b/static/css/loader.gif
deleted file mode 100644
index 36b04f2..0000000
Binary files a/static/css/loader.gif and /dev/null differ
diff --git a/static/css/loaderWhite.gif b/static/css/loaderWhite.gif
deleted file mode 100644
index c095f68..0000000
Binary files a/static/css/loaderWhite.gif and /dev/null differ
diff --git a/static/css/nextPageArrow.gif b/static/css/nextPageArrow.gif
deleted file mode 100644
index 6300aae..0000000
Binary files a/static/css/nextPageArrow.gif and /dev/null differ
diff --git a/static/css/nextPageArrowWhite.gif b/static/css/nextPageArrowWhite.gif
deleted file mode 100644
index 96d6069..0000000
Binary files a/static/css/nextPageArrowWhite.gif and /dev/null differ
diff --git a/static/css/prevPageArrow.gif b/static/css/prevPageArrow.gif
deleted file mode 100644
index 337c37a..0000000
Binary files a/static/css/prevPageArrow.gif and /dev/null differ
diff --git a/static/css/prevPageArrowWhite.gif b/static/css/prevPageArrowWhite.gif
deleted file mode 100644
index efe76e7..0000000
Binary files a/static/css/prevPageArrowWhite.gif and /dev/null differ
diff --git a/static/css/white.css b/static/css/white.css
deleted file mode 100644
index 542c99c..0000000
--- a/static/css/white.css
+++ /dev/null
@@ -1,57 +0,0 @@
-body{
-	background-color: #eee;
-	color: #444;
-}
-a{
-	color: #27D;
-}
-h2 {
-	color: #333;
-}
-div#page {
-	background-color: #fff;
-	border-color: #ddd;
-}
-div#footer {
-	color: #777;
-}
-div.caption-container {
-	color: #111;
-}
-div.image-title {
-	font-weight: bold;
-	font-size: 1.4em;
-}
-div.image-desc {
-	line-height: 1.3em;
-	padding-top: 12px;
-}
-div.download {
-	margin-top: 8px;
-}
-div.photo-index {
-	color: #777;
-}
-div.navigation a.prev {
-	background-image: url(prevPageArrow.gif);
-}
-div.navigation a.next {
-	background-image: url(nextPageArrow.gif);
-}
-div.loader {
-	background-image: url(loader.gif);
-}
-div.slideshow img {
-	border-color: #ccc;
-}
-ul.thumbs li.selected a.thumb {
-	background: #000;
-}
-div.pagination a:hover {
-	background-color: #eee;
-}
-div.pagination span.current {
-	background-color: #000;
-	border-color: #000;
-	color: #fff;
-}
\ No newline at end of file
diff --git a/static/galala.js b/static/galala.js
new file mode 100644
index 0000000..751d499
--- /dev/null
+++ b/static/galala.js
@@ -0,0 +1,119 @@
+
+/* Operations on the images list */
+
+function findImageIndex(anchor) {
+    for (var i = 0; i < images.length; i++) {
+        if (images[i].anchor == anchor) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+function nextImageIndex(anchor) {
+    var i = findImageIndex(anchor) + 1;
+    if (i >= images.length) {
+        return images.length - 1;
+    }
+
+    return i;
+}
+
+function nextImage(anchor) {
+    return images[nextImageIndex(anchor)];
+}
+
+function prevImageIndex(anchor) {
+    var i = findImageIndex(anchor) - 1;
+    if (i < 0) {
+        return 0;
+    }
+
+    return i;
+}
+
+function prevImage(anchor) {
+    return images[prevImageIndex(anchor)];
+}
+
+
+/* Operations on the main <img> */
+
+function setMain(anchor) {
+    var main = $("img#main");
+    var img = images[findImageIndex(anchor)];
+    main.attr("src", img.image);
+    main.attr("alt", img.title);
+    main.data().anchor = img.anchor;
+
+    $("span#title").text(img.title);
+    $("span#desc").text(img.description);
+
+    document.location.hash = img.anchor;
+
+    scrollToThumbnail(img.anchor);
+    updatePreload();
+}
+
+function scrollToThumbnail(anchor) {
+    // We need to use the long selector because anchor can have a '.'.
+    var thumb = $('img[id="' + anchor + '"]');
+
+    $("div.thumbnails").animate(
+        { scrollTop: thumb[0].offsetTop },
+        { duration: "fast"});
+}
+
+function advanceMain() {
+    var next = nextImage($("img#main").data("anchor"));
+    setMain(next.anchor);
+}
+
+function retreatMain() {
+    var prev = prevImage($("img#main").data("anchor"));
+    setMain(prev.anchor);
+}
+
+function updatePreload() {
+    var next = nextImage($("img#main").data("anchor"));
+    var preload1 = $("img#preload1");
+    preload1.attr("src", next.image);
+
+    next = nextImage(next.anchor);
+    var preload2 = $("img#preload2");
+    preload2.attr("src", next.image);
+}
+
+$(document).ready(function() {
+    // Binding for clicks, swipes and keys.
+    $("img#main").click(advanceMain);
+
+    $("img#main").swipe({
+        swipeLeft: advanceMain,
+        swipeRight: retreatMain,
+    });
+
+    $("html").keydown(function(e) {
+        switch (e.which) {
+            case 39: // Right.
+                advanceMain();
+                break;
+            case 37: // Left.
+                retreatMain();
+                break;
+        }
+    });
+
+    $("img.thumb").click(function() {
+        var anchor = this.id;
+        setMain(anchor);
+    });
+
+    // Set the first image.
+    if (document.location.hash != "") {
+        setMain(document.location.hash.substr(1));
+    } else {
+        setMain(images[0].anchor);
+    }
+});
diff --git a/static/index.css b/static/index.css
new file mode 100644
index 0000000..a28abd1
--- /dev/null
+++ b/static/index.css
@@ -0,0 +1,45 @@
+
+/* Colors from http://www.google.com/design/spec/style/color.html */
+
+body {
+    padding: 0 20pt 1em 0;
+    font-family: sans-serif;
+    background-color: #fafafa;
+    color: #263238;
+
+    margin: 1em auto 1em 10em;
+    padding: 0 20pt 1em 20pt;
+    width: 40em;
+}
+
+div.introduction {
+    font-size: x-large;
+}
+
+div.album-list {
+    margin: 2em auto 2em auto;
+}
+
+div.album-item {
+    margin: 1.5em auto 1.5em auto;
+}
+
+div.album-item div.title {
+    font-weight: bold;
+    font-size: large;
+}
+
+div.album-item div.text {
+    margin-left: 2em;
+}
+
+div.album-item a {
+    text-decoration: none;
+    color: #006064;
+}
+
+div.album-item a:hover {
+    text-decoration: none;
+    color: #0097a7;
+}
+
diff --git a/static/jquery.touchSwipe.js b/static/jquery.touchSwipe.js
new file mode 100644
index 0000000..bd4d179
--- /dev/null
+++ b/static/jquery.touchSwipe.js
@@ -0,0 +1,2080 @@
+/*
+* @fileOverview TouchSwipe - jQuery Plugin
+* @version 1.6.9
+*
+* @author Matt Bryson http://www.github.com/mattbryson
+* @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
+* @see http://labs.rampinteractive.co.uk/touchSwipe/
+* @see http://plugins.jquery.com/project/touchSwipe
+*
+* Copyright (c) 2010-2015 Matt Bryson
+* Dual licensed under the MIT or GPL Version 2 licenses.
+*
+*/
+
+/*
+*
+* Changelog
+* $Date: 2010-12-12 (Wed, 12 Dec 2010) $
+* $version: 1.0.0
+* $version: 1.0.1 - removed multibyte comments
+*
+* $Date: 2011-21-02 (Mon, 21 Feb 2011) $
+* $version: 1.1.0 	- added allowPageScroll property to allow swiping and scrolling of page
+*					- changed handler signatures so one handler can be used for multiple events
+* $Date: 2011-23-02 (Wed, 23 Feb 2011) $
+* $version: 1.2.0 	- added click handler. This is fired if the user simply clicks and does not swipe. The event object and click target are passed to handler.
+*					- If you use the http://code.google.com/p/jquery-ui-for-ipad-and-iphone/ plugin, you can also assign jQuery mouse events to children of a touchSwipe object.
+* $version: 1.2.1 	- removed console log!
+*
+* $version: 1.2.2 	- Fixed bug where scope was not preserved in callback methods.
+*
+* $Date: 2011-28-04 (Thurs, 28 April 2011) $
+* $version: 1.2.4 	- Changed licence terms to be MIT or GPL inline with jQuery. Added check for support of touch events to stop non compatible browsers erroring.
+*
+* $Date: 2011-27-09 (Tues, 27 September 2011) $
+* $version: 1.2.5 	- Added support for testing swipes with mouse on desktop browser (thanks to https://github.com/joelhy)
+*
+* $Date: 2012-14-05 (Mon, 14 May 2012) $
+* $version: 1.2.6 	- Added timeThreshold between start and end touch, so user can ignore slow swipes (thanks to Mark Chase). Default is null, all swipes are detected
+*
+* $Date: 2012-05-06 (Tues, 05 June 2012) $
+* $version: 1.2.7 	- Changed time threshold to have null default for backwards compatibility. Added duration param passed back in events, and refactored how time is handled.
+*
+* $Date: 2012-05-06 (Tues, 05 June 2012) $
+* $version: 1.2.8 	- Added the possibility to return a value like null or false in the trigger callback. In that way we can control when the touch start/move should take effect or not (simply by returning in some cases return null; or return false;) This effects the ontouchstart/ontouchmove event.
+*
+* $Date: 2012-06-06 (Wed, 06 June 2012) $
+* $version: 1.3.0 	- Refactored whole plugin to allow for methods to be executed, as well as exposed defaults for user override. Added 'enable', 'disable', and 'destroy' methods
+*
+* $Date: 2012-05-06 (Fri, 05 June 2012) $
+* $version: 1.3.1 	- Bug fixes  - bind() with false as last argument is no longer supported in jQuery 1.6, also, if you just click, the duration is now returned correctly.
+*
+* $Date: 2012-29-07 (Sun, 29 July 2012) $
+* $version: 1.3.2	- Added fallbackToMouseEvents option to NOT capture mouse events on non touch devices.
+* 			- Added "all" fingers value to the fingers property, so any combination of fingers triggers the swipe, allowing event handlers to check the finger count
+*
+* $Date: 2012-09-08 (Thurs, 9 Aug 2012) $
+* $version: 1.3.3	- Code tidy prep for minefied version
+*
+* $Date: 2012-04-10 (wed, 4 Oct 2012) $
+* $version: 1.4.0	- Added pinch support, pinchIn and pinchOut
+*
+* $Date: 2012-11-10 (Thurs, 11 Oct 2012) $
+* $version: 1.5.0	- Added excludedElements, a jquery selector that specifies child elements that do NOT trigger swipes. By default, this is one select that removes all form, input select, button and anchor elements.
+*
+* $Date: 2012-22-10 (Mon, 22 Oct 2012) $
+* $version: 1.5.1	- Fixed bug with jQuery 1.8 and trailing comma in excludedElements
+*					- Fixed bug with IE and eventPreventDefault()
+* $Date: 2013-01-12 (Fri, 12 Jan 2013) $
+* $version: 1.6.0	- Fixed bugs with pinching, mainly when both pinch and swipe enabled, as well as adding time threshold for multifinger gestures, so releasing one finger beofre the other doesnt trigger as single finger gesture.
+*					- made the demo site all static local HTML pages so they can be run locally by a developer
+*					- added jsDoc comments and added documentation for the plugin	
+*					- code tidy
+*					- added triggerOnTouchLeave property that will end the event when the user swipes off the element.
+* $Date: 2013-03-23 (Sat, 23 Mar 2013) $
+* $version: 1.6.1	- Added support for ie8 touch events
+* $version: 1.6.2	- Added support for events binding with on / off / bind in jQ for all callback names.
+*                   - Deprecated the 'click' handler in favour of tap.
+*                   - added cancelThreshold property
+*                   - added option method to update init options at runtime
+* $version 1.6.3    - added doubletap, longtap events and longTapThreshold, doubleTapThreshold property
+*
+* $Date: 2013-04-04 (Thurs, 04 April 2013) $
+* $version 1.6.4    - Fixed bug with cancelThreshold introduced in 1.6.3, where swipe status no longer fired start event, and stopped once swiping back.
+*
+* $Date: 2013-08-24 (Sat, 24 Aug 2013) $
+* $version 1.6.5    - Merged a few pull requests fixing various bugs, added AMD support.
+*
+* $Date: 2014-06-04 (Wed, 04 June 2014) $
+* $version 1.6.6 	- Merge of pull requests.
+*    				- IE10 touch support 
+*    				- Only prevent default event handling on valid swipe
+*    				- Separate license/changelog comment
+*    				- Detect if the swipe is valid at the end of the touch event.
+*    				- Pass fingerdata to event handlers. 
+*    				- Add 'hold' gesture 
+*    				- Be more tolerant about the tap distance
+*    				- Typos and minor fixes
+*
+* $Date: 2015-22-01 (Thurs, 22 Jan 2015) $
+* $version 1.6.7    - Added patch from https://github.com/mattbryson/TouchSwipe-Jquery-Plugin/issues/206 to fix memory leak
+*
+* $Date: 2015-2-2 (Mon, 2 Feb 2015) $
+* $version 1.6.8    - Added preventDefaultEvents option to proxy events regardless.
+*					- Fixed issue with swipe and pinch not triggering at the same time
+*
+* $Date: 2015-9-6 (Tues, 9 June 2015) $
+* $version 1.6.9    - Added PR from jdalton/hybrid to fix pointer events
+*					- Added scrolling demo
+*					- Added version property to plugin
+*
+*
+*/
+
+/**
+ * See (http://jquery.com/).
+ * @name $
+ * @class 
+ * See the jQuery Library  (http://jquery.com/) for full details.  This just
+ * documents the function and classes that are added to jQuery by this plug-in.
+ */
+ 
+/**
+ * See (http://jquery.com/)
+ * @name fn
+ * @class 
+ * See the jQuery Library  (http://jquery.com/) for full details.  This just
+ * documents the function and classes that are added to jQuery by this plug-in.
+ * @memberOf $
+ */
+
+
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd && define.amd.jQuery) {
+        // AMD. Register as anonymous module.
+        define(['jquery'], factory);
+    } else {
+        // Browser globals.
+        factory(jQuery);
+    }
+}(function ($) {
+	"use strict";
+
+	//Constants
+	var VERSION = "1.6.9",
+		LEFT = "left",
+		RIGHT = "right",
+		UP = "up",
+		DOWN = "down",
+		IN = "in",
+		OUT = "out",
+
+		NONE = "none",
+		AUTO = "auto",
+		
+		SWIPE = "swipe",
+		PINCH = "pinch",
+		TAP = "tap",
+		DOUBLE_TAP = "doubletap",
+		LONG_TAP = "longtap",
+		HOLD = "hold",
+		
+		HORIZONTAL = "horizontal",
+		VERTICAL = "vertical",
+
+		ALL_FINGERS = "all",
+		
+		DOUBLE_TAP_THRESHOLD = 10,
+
+		PHASE_START = "start",
+		PHASE_MOVE = "move",
+		PHASE_END = "end",
+		PHASE_CANCEL = "cancel",
+
+		SUPPORTS_TOUCH = 'ontouchstart' in window,
+		
+		SUPPORTS_POINTER_IE10 = window.navigator.msPointerEnabled && !window.navigator.pointerEnabled,
+		
+		SUPPORTS_POINTER = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
+
+		PLUGIN_NS = 'TouchSwipe';
+
+
+
+	/**
+	* The default configuration, and available options to configure touch swipe with.
+	* You can set the default values by updating any of the properties prior to instantiation.
+	* @name $.fn.swipe.defaults
+	* @namespace
+	* @property {int} [fingers=1] The number of fingers to detect in a swipe. Any swipes that do not meet this requirement will NOT trigger swipe handlers.
+	* @property {int} [threshold=75] The number of pixels that the user must move their finger by before it is considered a swipe. 
+	* @property {int} [cancelThreshold=null] The number of pixels that the user must move their finger back from the original swipe direction to cancel the gesture.
+	* @property {int} [pinchThreshold=20] The number of pixels that the user must pinch their finger by before it is considered a pinch. 
+	* @property {int} [maxTimeThreshold=null] Time, in milliseconds, between touchStart and touchEnd must NOT exceed in order to be considered a swipe. 
+	* @property {int} [fingerReleaseThreshold=250] Time in milliseconds between releasing multiple fingers.  If 2 fingers are down, and are released one after the other, if they are within this threshold, it counts as a simultaneous release. 
+	* @property {int} [longTapThreshold=500] Time in milliseconds between tap and release for a long tap
+	* @property {int} [doubleTapThreshold=200] Time in milliseconds between 2 taps to count as a double tap
+	* @property {function} [swipe=null] A handler to catch all swipes. See {@link $.fn.swipe#event:swipe}
+	* @property {function} [swipeLeft=null] A handler that is triggered for "left" swipes. See {@link $.fn.swipe#event:swipeLeft}
+	* @property {function} [swipeRight=null] A handler that is triggered for "right" swipes. See {@link $.fn.swipe#event:swipeRight}
+	* @property {function} [swipeUp=null] A handler that is triggered for "up" swipes. See {@link $.fn.swipe#event:swipeUp}
+	* @property {function} [swipeDown=null] A handler that is triggered for "down" swipes. See {@link $.fn.swipe#event:swipeDown}
+	* @property {function} [swipeStatus=null] A handler triggered for every phase of the swipe. See {@link $.fn.swipe#event:swipeStatus}
+	* @property {function} [pinchIn=null] A handler triggered for pinch in events. See {@link $.fn.swipe#event:pinchIn}
+	* @property {function} [pinchOut=null] A handler triggered for pinch out events. See {@link $.fn.swipe#event:pinchOut}
+	* @property {function} [pinchStatus=null] A handler triggered for every phase of a pinch. See {@link $.fn.swipe#event:pinchStatus}
+	* @property {function} [tap=null] A handler triggered when a user just taps on the item, rather than swipes it. If they do not move, tap is triggered, if they do move, it is not. 
+	* @property {function} [doubleTap=null] A handler triggered when a user double taps on the item. The delay between taps can be set with the doubleTapThreshold property. See {@link $.fn.swipe.defaults#doubleTapThreshold}
+	* @property {function} [longTap=null] A handler triggered when a user long taps on the item. The delay between start and end can be set with the longTapThreshold property. See {@link $.fn.swipe.defaults#longTapThreshold}
+	* @property (function) [hold=null] A handler triggered when a user reaches longTapThreshold on the item. See {@link $.fn.swipe.defaults#longTapThreshold}
+	* @property {boolean} [triggerOnTouchEnd=true] If true, the swipe events are triggered when the touch end event is received (user releases finger).  If false, it will be triggered on reaching the threshold, and then cancel the touch event automatically. 
+	* @property {boolean} [triggerOnTouchLeave=false] If true, then when the user leaves the swipe object, the swipe will end and trigger appropriate handlers. 
+	* @property {string|undefined} [allowPageScroll='auto'] How the browser handles page scrolls when the user is swiping on a touchSwipe object. See {@link $.fn.swipe.pageScroll}.  <br/><br/>
+										<code>"auto"</code> : all undefined swipes will cause the page to scroll in that direction. <br/>
+										<code>"none"</code> : the page will not scroll when user swipes. <br/>
+										<code>"horizontal"</code> : will force page to scroll on horizontal swipes. <br/>
+										<code>"vertical"</code> : will force page to scroll on vertical swipes. <br/>
+	* @property {boolean} [fallbackToMouseEvents=true] If true mouse events are used when run on a non touch device, false will stop swipes being triggered by mouse events on non tocuh devices. 
+	* @property {string} [excludedElements="button, input, select, textarea, a, .noSwipe"] A jquery selector that specifies child elements that do NOT trigger swipes. By default this excludes all form, input, select, button, anchor and .noSwipe elements. 
+	* @property {boolean} [preventDefaultEvents=true] by default default events are cancelled, so the page doesn't move.  You can dissable this so both native events fire as well as your handlers. 
+	
+	*/
+	var defaults = {
+		fingers: 1, 		
+		threshold: 75, 	
+		cancelThreshold:null,	
+		pinchThreshold:20,
+		maxTimeThreshold: null, 
+		fingerReleaseThreshold:250, 
+		longTapThreshold:500,
+		doubleTapThreshold:200,
+		swipe: null, 		
+		swipeLeft: null, 	
+		swipeRight: null, 	
+		swipeUp: null, 		
+		swipeDown: null, 	
+		swipeStatus: null, 	
+		pinchIn:null,		
+		pinchOut:null,		
+		pinchStatus:null,	
+		click:null, //Deprecated since 1.6.2
+		tap:null,
+		doubleTap:null,
+		longTap:null, 		
+		hold:null, 
+		triggerOnTouchEnd: true, 
+		triggerOnTouchLeave:false, 
+		allowPageScroll: "auto", 
+		fallbackToMouseEvents: true,	
+		excludedElements:"label, button, input, select, textarea, a, .noSwipe",
+		preventDefaultEvents:true
+	};
+
+
+
+	/**
+	* Applies TouchSwipe behaviour to one or more jQuery objects.
+	* The TouchSwipe plugin can be instantiated via this method, or methods within 
+	* TouchSwipe can be executed via this method as per jQuery plugin architecture.
+	* @see TouchSwipe
+	* @class
+	* @param {Mixed} method If the current DOMNode is a TouchSwipe object, and <code>method</code> is a TouchSwipe method, then
+	* the <code>method</code> is executed, and any following arguments are passed to the TouchSwipe method.
+	* If <code>method</code> is an object, then the TouchSwipe class is instantiated on the current DOMNode, passing the 
+	* configuration properties defined in the object. See TouchSwipe
+	*
+	*/
+	$.fn.swipe = function (method) {
+		var $this = $(this),
+			plugin = $this.data(PLUGIN_NS);
+
+		//Check if we are already instantiated and trying to execute a method	
+		if (plugin && typeof method === 'string') {
+			if (plugin[method]) {
+				return plugin[method].apply(this, Array.prototype.slice.call(arguments, 1));
+			} else {
+				$.error('Method ' + method + ' does not exist on jQuery.swipe');
+			}
+		}
+		//Else not instantiated and trying to pass init object (or nothing)
+		else if (!plugin && (typeof method === 'object' || !method)) {
+			return init.apply(this, arguments);
+		}
+
+		return $this;
+	};
+	
+	/**
+	 * The version of the plugin
+	 * @readonly
+	 */
+	$.fn.swipe.version = VERSION;
+
+
+
+	//Expose our defaults so a user could override the plugin defaults
+	$.fn.swipe.defaults = defaults;
+
+	/**
+	* The phases that a touch event goes through.  The <code>phase</code> is passed to the event handlers. 
+	* These properties are read only, attempting to change them will not alter the values passed to the event handlers.
+	* @namespace
+	* @readonly
+	* @property {string} PHASE_START Constant indicating the start phase of the touch event. Value is <code>"start"</code>.
+	* @property {string} PHASE_MOVE Constant indicating the move phase of the touch event. Value is <code>"move"</code>.
+	* @property {string} PHASE_END Constant indicating the end phase of the touch event. Value is <code>"end"</code>.
+	* @property {string} PHASE_CANCEL Constant indicating the cancel phase of the touch event. Value is <code>"cancel"</code>.
+	*/
+	$.fn.swipe.phases = {
+		PHASE_START: PHASE_START,
+		PHASE_MOVE: PHASE_MOVE,
+		PHASE_END: PHASE_END,
+		PHASE_CANCEL: PHASE_CANCEL
+	};
+
+	/**
+	* The direction constants that are passed to the event handlers. 
+	* These properties are read only, attempting to change them will not alter the values passed to the event handlers.
+	* @namespace
+	* @readonly
+	* @property {string} LEFT Constant indicating the left direction. Value is <code>"left"</code>.
+	* @property {string} RIGHT Constant indicating the right direction. Value is <code>"right"</code>.
+	* @property {string} UP Constant indicating the up direction. Value is <code>"up"</code>.
+	* @property {string} DOWN Constant indicating the down direction. Value is <code>"cancel"</code>.
+	* @property {string} IN Constant indicating the in direction. Value is <code>"in"</code>.
+	* @property {string} OUT Constant indicating the out direction. Value is <code>"out"</code>.
+	*/
+	$.fn.swipe.directions = {
+		LEFT: LEFT,
+		RIGHT: RIGHT,
+		UP: UP,
+		DOWN: DOWN,
+		IN : IN,
+		OUT: OUT
+	};
+	
+	/**
+	* The page scroll constants that can be used to set the value of <code>allowPageScroll</code> option
+	* These properties are read only
+	* @namespace
+	* @readonly
+	* @see $.fn.swipe.defaults#allowPageScroll
+	* @property {string} NONE Constant indicating no page scrolling is allowed. Value is <code>"none"</code>.
+	* @property {string} HORIZONTAL Constant indicating horizontal page scrolling is allowed. Value is <code>"horizontal"</code>.
+	* @property {string} VERTICAL Constant indicating vertical page scrolling is allowed. Value is <code>"vertical"</code>.
+	* @property {string} AUTO Constant indicating either horizontal or vertical will be allowed, depending on the swipe handlers registered. Value is <code>"auto"</code>.
+	*/
+	$.fn.swipe.pageScroll = {
+		NONE: NONE,
+		HORIZONTAL: HORIZONTAL,
+		VERTICAL: VERTICAL,
+		AUTO: AUTO
+	};
+
+	/**
+	* Constants representing the number of fingers used in a swipe.  These are used to set both the value of <code>fingers</code> in the 
+	* options object, as well as the value of the <code>fingers</code> event property.
+	* These properties are read only, attempting to change them will not alter the values passed to the event handlers.
+	* @namespace
+	* @readonly
+	* @see $.fn.swipe.defaults#fingers
+	* @property {string} ONE Constant indicating 1 finger is to be detected / was detected. Value is <code>1</code>.
+	* @property {string} TWO Constant indicating 2 fingers are to be detected / were detected. Value is <code>1</code>.
+	* @property {string} THREE Constant indicating 3 finger are to be detected / were detected. Value is <code>1</code>.
+	* @property {string} ALL Constant indicating any combination of finger are to be detected.  Value is <code>"all"</code>.
+	*/
+	$.fn.swipe.fingers = {
+		ONE: 1,
+		TWO: 2,
+		THREE: 3,
+		ALL: ALL_FINGERS
+	};
+
+	/**
+	* Initialise the plugin for each DOM element matched
+	* This creates a new instance of the main TouchSwipe class for each DOM element, and then
+	* saves a reference to that instance in the elements data property.
+	* @internal
+	*/
+	function init(options) {
+		//Prep and extend the options
+		if (options && (options.allowPageScroll === undefined && (options.swipe !== undefined || options.swipeStatus !== undefined))) {
+			options.allowPageScroll = NONE;
+		}
+		
+        //Check for deprecated options
+		//Ensure that any old click handlers are assigned to the new tap, unless we have a tap
+		if(options.click!==undefined && options.tap===undefined) {
+		    options.tap = options.click;
+		}
+
+		if (!options) {
+			options = {};
+		}
+		
+        //pass empty object so we dont modify the defaults
+		options = $.extend({}, $.fn.swipe.defaults, options);
+
+		//For each element instantiate the plugin
+		return this.each(function () {
+			var $this = $(this);
+
+			//Check we havent already initialised the plugin
+			var plugin = $this.data(PLUGIN_NS);
+
+			if (!plugin) {
+				plugin = new TouchSwipe(this, options);
+				$this.data(PLUGIN_NS, plugin);
+			}
+		});
+	}
+
+	/**
+	* Main TouchSwipe Plugin Class.
+	* Do not use this to construct your TouchSwipe object, use the jQuery plugin method $.fn.swipe(); {@link $.fn.swipe}
+	* @private
+	* @name TouchSwipe
+	* @param {DOMNode} element The HTML DOM object to apply to plugin to
+	* @param {Object} options The options to configure the plugin with.  @link {$.fn.swipe.defaults}
+	* @see $.fh.swipe.defaults
+	* @see $.fh.swipe
+    * @class
+	*/
+	function TouchSwipe(element, options) {
+        var useTouchEvents = (SUPPORTS_TOUCH || SUPPORTS_POINTER || !options.fallbackToMouseEvents),
+            START_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerDown' : 'pointerdown') : 'touchstart') : 'mousedown',
+            MOVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerMove' : 'pointermove') : 'touchmove') : 'mousemove',
+            END_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerUp' : 'pointerup') : 'touchend') : 'mouseup',
+            LEAVE_EV = useTouchEvents ? null : 'mouseleave', //we manually detect leave on touch devices, so null event here
+            CANCEL_EV = (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerCancel' : 'pointercancel') : 'touchcancel');
+
+
+
+		//touch properties
+		var distance = 0,
+			direction = null,
+			duration = 0,
+			startTouchesDistance = 0,
+			endTouchesDistance = 0,
+			pinchZoom = 1,
+			pinchDistance = 0,
+			pinchDirection = 0,
+			maximumsMap=null;
+
+		
+		
+		//jQuery wrapped element for this instance
+		var $element = $(element);
+		
+		//Current phase of th touch cycle
+		var phase = "start";
+
+		// the current number of fingers being used.
+		var fingerCount = 0; 			
+
+		//track mouse points / delta
+		var fingerData=null;
+
+		//track times
+		var startTime = 0,
+			endTime = 0,
+			previousTouchEndTime=0,
+			previousTouchFingerCount=0,
+			doubleTapStartTime=0;
+
+		//Timeouts
+		var singleTapTimeout=null,
+			holdTimeout=null;
+        
+		// Add gestures to all swipable areas if supported
+		try {
+			$element.bind(START_EV, touchStart);
+			$element.bind(CANCEL_EV, touchCancel);
+		}
+		catch (e) {
+			$.error('events not supported ' + START_EV + ',' + CANCEL_EV + ' on jQuery.swipe');
+		}
+
+		//
+		//Public methods
+		//
+		
+		/**
+		* re-enables the swipe plugin with the previous configuration
+		* @function
+		* @name $.fn.swipe#enable
+		* @return {DOMNode} The Dom element that was registered with TouchSwipe 
+		* @example $("#element").swipe("enable");
+		*/
+		this.enable = function () {
+			$element.bind(START_EV, touchStart);
+			$element.bind(CANCEL_EV, touchCancel);
+			return $element;
+		};
+
+		/**
+		* disables the swipe plugin
+		* @function
+		* @name $.fn.swipe#disable
+		* @return {DOMNode} The Dom element that is now registered with TouchSwipe
+	    * @example $("#element").swipe("disable");
+		*/
+		this.disable = function () {
+			removeListeners();
+			return $element;
+		};
+
+		/**
+		* Destroy the swipe plugin completely. To use any swipe methods, you must re initialise the plugin.
+		* @function
+		* @name $.fn.swipe#destroy
+		* @example $("#element").swipe("destroy");
+		*/
+		this.destroy = function () {
+			removeListeners();
+			$element.data(PLUGIN_NS, null);
+			$element = null;
+		};
+
+		
+        /**
+         * Allows run time updating of the swipe configuration options.
+         * @function
+    	 * @name $.fn.swipe#option
+    	 * @param {String} property The option property to get or set
+         * @param {Object} [value] The value to set the property to
+		 * @return {Object} If only a property name is passed, then that property value is returned.
+		 * @example $("#element").swipe("option", "threshold"); // return the threshold
+         * @example $("#element").swipe("option", "threshold", 100); // set the threshold after init
+         * @see $.fn.swipe.defaults
+         *
+         */
+        this.option = function (property, value) {
+            if(options[property]!==undefined) {
+                if(value===undefined) {
+                    return options[property];
+                } else {
+                    options[property] = value;
+                }
+            } else {
+                $.error('Option ' + property + ' does not exist on jQuery.swipe.options');
+            }
+
+            return null;
+        }
+
+		//
+		// Private methods
+		//
+		
+		//
+		// EVENTS
+		//
+		/**
+		* Event handler for a touch start event.
+		* Stops the default click event from triggering and stores where we touched
+		* @inner
+		* @param {object} jqEvent The normalised jQuery event object.
+		*/
+		function touchStart(jqEvent) {
+			//If we already in a touch event (a finger already in use) then ignore subsequent ones..
+			if( getTouchInProgress() )
+				return;
+			
+			//Check if this element matches any in the excluded elements selectors,  or its parent is excluded, if so, DON'T swipe
+			if( $(jqEvent.target).closest( options.excludedElements, $element ).length>0 ) 
+				return;
+				
+			//As we use Jquery bind for events, we need to target the original event object
+			//If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
+			var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
+			
+			var ret,
+				touches = event.touches,
+				evt = touches ? touches[0] : event;
+
+			phase = PHASE_START;
+
+			//If we support touches, get the finger count
+			if (touches) {
+				// get the total number of fingers touching the screen
+				fingerCount = touches.length;
+			}
+			//Else this is the desktop, so stop the browser from dragging content
+			else {
+				jqEvent.preventDefault(); //call this on jq event so we are cross browser
+			}
+
+			//clear vars..
+			distance = 0;
+			direction = null;
+			pinchDirection=null;
+			duration = 0;
+			startTouchesDistance=0;
+			endTouchesDistance=0;
+			pinchZoom = 1;
+			pinchDistance = 0;
+			fingerData=createAllFingerData();
+			maximumsMap=createMaximumsData();
+			cancelMultiFingerRelease();
+
+			
+			// check the number of fingers is what we are looking for, or we are capturing pinches
+			if (!touches || (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || hasPinches()) {
+				// get the coordinates of the touch
+				createFingerData( 0, evt );
+				startTime = getTimeStamp();
+				
+				if(fingerCount==2) {
+					//Keep track of the initial pinch distance, so we can calculate the diff later
+					//Store second finger data as start
+					createFingerData( 1, touches[1] );
+					startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
+				}
+				
+				if (options.swipeStatus || options.pinchStatus) {
+					ret = triggerHandler(event, phase);
+				}
+			}
+			else {
+				//A touch with more or less than the fingers we are looking for, so cancel
+				ret = false; 
+			}
+
+			//If we have a return value from the users handler, then return and cancel
+			if (ret === false) {
+				phase = PHASE_CANCEL;
+				triggerHandler(event, phase);
+				return ret;
+			}
+			else {
+				if (options.hold) {
+					holdTimeout = setTimeout($.proxy(function() {
+						//Trigger the event
+						$element.trigger('hold', [event.target]);
+						//Fire the callback
+						if(options.hold) {
+							ret = options.hold.call($element, event, event.target);
+						}
+					}, this), options.longTapThreshold );
+				}
+
+				setTouchInProgress(true);
+			}
+
+            return null;
+		};
+		
+		
+		
+		/**
+		* Event handler for a touch move event. 
+		* If we change fingers during move, then cancel the event
+		* @inner
+		* @param {object} jqEvent The normalised jQuery event object.
+		*/
+		function touchMove(jqEvent) {
+			
+			//As we use Jquery bind for events, we need to target the original event object
+			//If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
+			var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
+			
+			//If we are ending, cancelling, or within the threshold of 2 fingers being released, don't track anything..
+			if (phase === PHASE_END || phase === PHASE_CANCEL || inMultiFingerRelease())
+				return;
+
+			var ret,
+				touches = event.touches,
+				evt = touches ? touches[0] : event;
+			
+
+			//Update the  finger data 
+			var currentFinger = updateFingerData(evt);
+			endTime = getTimeStamp();
+			
+			if (touches) {
+				fingerCount = touches.length;
+			}
+
+			if (options.hold)
+				clearTimeout(holdTimeout);
+
+			phase = PHASE_MOVE;
+
+			//If we have 2 fingers get Touches distance as well
+			if(fingerCount==2) {
+				
+				//Keep track of the initial pinch distance, so we can calculate the diff later
+				//We do this here as well as the start event, in case they start with 1 finger, and the press 2 fingers
+				if(startTouchesDistance==0) {
+					//Create second finger if this is the first time...
+					createFingerData( 1, touches[1] );
+					
+					startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
+				} else {
+					//Else just update the second finger
+					updateFingerData(touches[1]);
+				
+					endTouchesDistance = calculateTouchesDistance(fingerData[0].end, fingerData[1].end);
+					pinchDirection = calculatePinchDirection(fingerData[0].end, fingerData[1].end);
+				}
+				
+				
+				pinchZoom = calculatePinchZoom(startTouchesDistance, endTouchesDistance);
+				pinchDistance = Math.abs(startTouchesDistance - endTouchesDistance);
+			}
+			
+			
+			
+
+			if ( (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !touches || hasPinches() ) {
+				
+				direction = calculateDirection(currentFinger.start, currentFinger.end);
+				
+				//Check if we need to prevent default event (page scroll / pinch zoom) or not
+				validateDefaultEvent(jqEvent, direction);
+
+				//Distance and duration are all off the main finger
+				distance = calculateDistance(currentFinger.start, currentFinger.end);
+				duration = calculateDuration();
+
+                //Cache the maximum distance we made in this direction
+                setMaxDistance(direction, distance);
+
+
+				if (options.swipeStatus || options.pinchStatus) {
+					ret = triggerHandler(event, phase);
+				}
+				
+				
+				//If we trigger end events when threshold are met, or trigger events when touch leaves element
+				if(!options.triggerOnTouchEnd || options.triggerOnTouchLeave) {
+					
+					var inBounds = true;
+					
+					//If checking if we leave the element, run the bounds check (we can use touchleave as its not supported on webkit)
+					if(options.triggerOnTouchLeave) {
+						var bounds = getbounds( this );
+						inBounds = isInBounds( currentFinger.end, bounds );
+					}
+					
+					//Trigger end handles as we swipe if thresholds met or if we have left the element if the user has asked to check these..
+					if(!options.triggerOnTouchEnd && inBounds) {
+						phase = getNextPhase( PHASE_MOVE );
+					} 
+					//We end if out of bounds here, so set current phase to END, and check if its modified 
+					else if(options.triggerOnTouchLeave && !inBounds ) {
+						phase = getNextPhase( PHASE_END );
+					}
+						
+					if(phase==PHASE_CANCEL || phase==PHASE_END)	{
+						triggerHandler(event, phase);
+					}				
+				}
+			}
+			else {
+				phase = PHASE_CANCEL;
+				triggerHandler(event, phase);
+			}
+
+			if (ret === false) {
+				phase = PHASE_CANCEL;
+				triggerHandler(event, phase);
+			}
+		}
+
+
+
+		/**
+		* Event handler for a touch end event. 
+		* Calculate the direction and trigger events
+		* @inner
+		* @param {object} jqEvent The normalised jQuery event object.
+		*/
+		function touchEnd(jqEvent) {
+			//As we use Jquery bind for events, we need to target the original event object
+			//If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
+			var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent,
+			    touches = event.touches;
+
+			//If we are still in a touch with another finger return
+			//This allows us to wait a fraction and see if the other finger comes up, if it does within the threshold, then we treat it as a multi release, not a single release.
+			if (touches) {
+				if(touches.length) {
+					startMultiFingerRelease();
+					return true;
+				}
+			}
+			
+			//If a previous finger has been released, check how long ago, if within the threshold, then assume it was a multifinger release.
+			//This is used to allow 2 fingers to release fractionally after each other, whilst maintainig the event as containg 2 fingers, not 1
+			if(inMultiFingerRelease()) {	
+				fingerCount=previousTouchFingerCount;
+			}	
+		
+			//Set end of swipe
+			endTime = getTimeStamp();
+			
+			//Get duration incase move was never fired
+			duration = calculateDuration();
+			
+			//If we trigger handlers at end of swipe OR, we trigger during, but they didnt trigger and we are still in the move phase
+			if(didSwipeBackToCancel() || !validateSwipeDistance()) {
+			    phase = PHASE_CANCEL;
+                triggerHandler(event, phase);
+			} else if (options.triggerOnTouchEnd || (options.triggerOnTouchEnd == false && phase === PHASE_MOVE)) {
+				//call this on jq event so we are cross browser 
+				jqEvent.preventDefault(); 
+				phase = PHASE_END;
+                triggerHandler(event, phase);
+			}
+			//Special cases - A tap should always fire on touch end regardless,
+			//So here we manually trigger the tap end handler by itself
+			//We dont run trigger handler as it will re-trigger events that may have fired already
+			else if (!options.triggerOnTouchEnd && hasTap()) {
+                //Trigger the pinch events...
+			    phase = PHASE_END;
+			    triggerHandlerForGesture(event, phase, TAP);
+			}
+			else if (phase === PHASE_MOVE) {
+				phase = PHASE_CANCEL;
+				triggerHandler(event, phase);
+			}
+
+			setTouchInProgress(false);
+
+            return null;
+		}
+
+
+
+		/**
+		* Event handler for a touch cancel event. 
+		* Clears current vars
+		* @inner
+		*/
+		function touchCancel() {
+			// reset the variables back to default values
+			fingerCount = 0;
+			endTime = 0;
+			startTime = 0;
+			startTouchesDistance=0;
+			endTouchesDistance=0;
+			pinchZoom=1;
+			
+			//If we were in progress of tracking a possible multi touch end, then re set it.
+			cancelMultiFingerRelease();
+			
+			setTouchInProgress(false);
+		}
+		
+		
+		/**
+		* Event handler for a touch leave event. 
+		* This is only triggered on desktops, in touch we work this out manually
+		* as the touchleave event is not supported in webkit
+		* @inner
+		*/
+		function touchLeave(jqEvent) {
+			var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
+			
+			//If we have the trigger on leave property set....
+			if(options.triggerOnTouchLeave) {
+				phase = getNextPhase( PHASE_END );
+				triggerHandler(event, phase);
+			}
+		}
+		
+		/**
+		* Removes all listeners that were associated with the plugin
+		* @inner
+		*/
+		function removeListeners() {
+			$element.unbind(START_EV, touchStart);
+			$element.unbind(CANCEL_EV, touchCancel);
+			$element.unbind(MOVE_EV, touchMove);
+			$element.unbind(END_EV, touchEnd);
+			
+			//we only have leave events on desktop, we manually calculate leave on touch as its not supported in webkit
+			if(LEAVE_EV) { 
+				$element.unbind(LEAVE_EV, touchLeave);
+			}
+			
+			setTouchInProgress(false);
+		}
+
+		
+		/**
+		 * Checks if the time and distance thresholds have been met, and if so then the appropriate handlers are fired.
+		 */
+		function getNextPhase(currentPhase) {
+			
+			var nextPhase = currentPhase;
+			
+			// Ensure we have valid swipe (under time and over distance  and check if we are out of bound...)
+			var validTime = validateSwipeTime();
+			var validDistance = validateSwipeDistance();
+			var didCancel = didSwipeBackToCancel();
+						
+			//If we have exceeded our time, then cancel	
+			if(!validTime || didCancel) {
+				nextPhase = PHASE_CANCEL;
+			}
+			//Else if we are moving, and have reached distance then end
+			else if (validDistance && currentPhase == PHASE_MOVE && (!options.triggerOnTouchEnd || options.triggerOnTouchLeave) ) {
+				nextPhase = PHASE_END;
+			} 
+			//Else if we have ended by leaving and didn't reach distance, then cancel
+			else if (!validDistance && currentPhase==PHASE_END && options.triggerOnTouchLeave) {
+				nextPhase = PHASE_CANCEL;
+			}
+			
+			return nextPhase;
+		}
+		
+		
+		/**
+		* Trigger the relevant event handler
+		* The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
+		* @param {object} event the original event object
+		* @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
+		* @inner
+		*/
+		function triggerHandler(event, phase) {
+
+			var ret,
+				touches = event.touches;
+			
+			//Swipes and pinches are not mutually exclusive - can happend at same time, so need to trigger 2 events potentially
+			if( (didSwipe() || hasSwipes()) || (didPinch() || hasPinches()) ) {
+				// SWIPE GESTURES
+				if(didSwipe() || hasSwipes()) { //hasSwipes as status needs to fire even if swipe is invalid
+					//Trigger the swipe events...
+					ret = triggerHandlerForGesture(event, phase, SWIPE);
+				}	
+
+				// PINCH GESTURES (if the above didn't cancel)
+				if((didPinch() || hasPinches()) && ret!==false) {
+					//Trigger the pinch events...
+					ret = triggerHandlerForGesture(event, phase, PINCH);
+				}
+			} else {
+			 
+				// CLICK / TAP (if the above didn't cancel)
+				if(didDoubleTap() && ret!==false) {
+					//Trigger the tap events...
+					ret = triggerHandlerForGesture(event, phase, DOUBLE_TAP);
+				}
+				
+				// CLICK / TAP (if the above didn't cancel)
+				else if(didLongTap() && ret!==false) {
+					//Trigger the tap events...
+					ret = triggerHandlerForGesture(event, phase, LONG_TAP);
+				}
+
+				// CLICK / TAP (if the above didn't cancel)
+				else if(didTap() && ret!==false) {
+					//Trigger the tap event..
+					ret = triggerHandlerForGesture(event, phase, TAP);
+				}
+			}
+			
+			
+			
+			// If we are cancelling the gesture, then manually trigger the reset handler
+			if (phase === PHASE_CANCEL) {
+				touchCancel(event);
+			}
+			
+			// If we are ending the gesture, then manually trigger the reset handler IF all fingers are off
+			if(phase === PHASE_END) {
+				//If we support touch, then check that all fingers are off before we cancel
+				if (touches) {
+					if(!touches.length) {
+						touchCancel(event);	
+					}
+				} 
+				else {
+					touchCancel(event);
+				}
+			}
+					
+			return ret;
+		}
+		
+		
+		
+		/**
+		* Trigger the relevant event handler
+		* The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
+		* @param {object} event the original event object
+		* @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
+		* @param {string} gesture the gesture to trigger a handler for : PINCH or SWIPE {@link $.fn.swipe.gestures}
+		* @return Boolean False, to indicate that the event should stop propagation, or void.
+		* @inner
+		*/
+		function triggerHandlerForGesture(event, phase, gesture) {	
+			
+			var ret;
+			
+			//SWIPES....
+			if(gesture==SWIPE) {
+				//Trigger status every time..
+				
+				//Trigger the event...
+				$element.trigger('swipeStatus', [phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData]);
+				
+				//Fire the callback
+				if (options.swipeStatus) {
+					ret = options.swipeStatus.call($element, event, phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData);
+					//If the status cancels, then dont run the subsequent event handlers..
+					if(ret===false) return false;
+				}
+				
+				
+				
+				
+				if (phase == PHASE_END && validateSwipe()) {
+					//Fire the catch all event
+					$element.trigger('swipe', [direction, distance, duration, fingerCount, fingerData]);
+					
+					//Fire catch all callback
+					if (options.swipe) {
+						ret = options.swipe.call($element, event, direction, distance, duration, fingerCount, fingerData);
+						//If the status cancels, then dont run the subsequent event handlers..
+						if(ret===false) return false;
+					}
+					
+					//trigger direction specific event handlers	
+					switch (direction) {
+						case LEFT:
+							//Trigger the event
+							$element.trigger('swipeLeft', [direction, distance, duration, fingerCount, fingerData]);
+					
+					        //Fire the callback
+							if (options.swipeLeft) {
+								ret = options.swipeLeft.call($element, event, direction, distance, duration, fingerCount, fingerData);
+							}
+							break;
+	
+						case RIGHT:
+							//Trigger the event
+					        $element.trigger('swipeRight', [direction, distance, duration, fingerCount, fingerData]);
+					
+					        //Fire the callback
+							if (options.swipeRight) {
+								ret = options.swipeRight.call($element, event, direction, distance, duration, fingerCount, fingerData);
+							}
+							break;
+	
+						case UP:
+							//Trigger the event
+					        $element.trigger('swipeUp', [direction, distance, duration, fingerCount, fingerData]);
+					
+					        //Fire the callback
+							if (options.swipeUp) {
+								ret = options.swipeUp.call($element, event, direction, distance, duration, fingerCount, fingerData);
+							}
+							break;
+	
+						case DOWN:
+							//Trigger the event
+					        $element.trigger('swipeDown', [direction, distance, duration, fingerCount, fingerData]);
+					
+					        //Fire the callback
+							if (options.swipeDown) {
+								ret = options.swipeDown.call($element, event, direction, distance, duration, fingerCount, fingerData);
+							}
+							break;
+					}
+				}
+			}
+			
+			
+			//PINCHES....
+			if(gesture==PINCH) {
+				//Trigger the event
+			     $element.trigger('pinchStatus', [phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
+					
+                //Fire the callback
+				if (options.pinchStatus) {
+					ret = options.pinchStatus.call($element, event, phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
+					//If the status cancels, then dont run the subsequent event handlers..
+					if(ret===false) return false;
+				}
+				
+				if(phase==PHASE_END && validatePinch()) {
+					
+					switch (pinchDirection) {
+						case IN:
+							//Trigger the event
+                            $element.trigger('pinchIn', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
+                    
+                            //Fire the callback
+                            if (options.pinchIn) {
+								ret = options.pinchIn.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
+							}
+							break;
+						
+						case OUT:
+							//Trigger the event
+                            $element.trigger('pinchOut', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
+                    
+                            //Fire the callback
+                            if (options.pinchOut) {
+								ret = options.pinchOut.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
+							}
+							break;	
+					}
+				}
+			}
+			
+
+
+                
+	    		
+			if(gesture==TAP) {
+				if(phase === PHASE_CANCEL || phase === PHASE_END) {
+					
+    			    
+    			    //Cancel any existing double tap
+				    clearTimeout(singleTapTimeout);
+    			    //Cancel hold timeout
+				    clearTimeout(holdTimeout);
+				           
+					//If we are also looking for doubelTaps, wait incase this is one...
+				    if(hasDoubleTap() && !inDoubleTap()) {
+				        //Cache the time of this tap
+                        doubleTapStartTime = getTimeStamp();
+                       
+				        //Now wait for the double tap timeout, and trigger this single tap
+				        //if its not cancelled by a double tap
+				        singleTapTimeout = setTimeout($.proxy(function() {
+        			        doubleTapStartTime=null;
+        			        //Trigger the event
+                			$element.trigger('tap', [event.target]);
+
+                        
+                            //Fire the callback
+                            if(options.tap) {
+                                ret = options.tap.call($element, event, event.target);
+                            }
+    			        }, this), options.doubleTapThreshold );
+    			    	
+    			    } else {
+                        doubleTapStartTime=null;
+                        
+                        //Trigger the event
+                        $element.trigger('tap', [event.target]);
+
+                        
+                        //Fire the callback
+                        if(options.tap) {
+                            ret = options.tap.call($element, event, event.target);
+                        }
+	    		    }
+	    		}
+			}
+			
+			else if (gesture==DOUBLE_TAP) {
+				if(phase === PHASE_CANCEL || phase === PHASE_END) {
+					//Cancel any pending singletap 
+				    clearTimeout(singleTapTimeout);
+				    doubleTapStartTime=null;
+				        
+                    //Trigger the event
+                    $element.trigger('doubletap', [event.target]);
+                
+                    //Fire the callback
+                    if(options.doubleTap) {
+                        ret = options.doubleTap.call($element, event, event.target);
+                    }
+	    		}
+			}
+			
+			else if (gesture==LONG_TAP) {
+				if(phase === PHASE_CANCEL || phase === PHASE_END) {
+					//Cancel any pending singletap (shouldnt be one)
+				    clearTimeout(singleTapTimeout);
+				    doubleTapStartTime=null;
+				        
+                    //Trigger the event
+                    $element.trigger('longtap', [event.target]);
+                
+                    //Fire the callback
+                    if(options.longTap) {
+                        ret = options.longTap.call($element, event, event.target);
+                    }
+	    		}
+			}				
+				
+			return ret;
+		}
+
+
+
+		
+		//
+		// GESTURE VALIDATION
+		//
+		
+		/**
+		* Checks the user has swipe far enough
+		* @return Boolean if <code>threshold</code> has been set, return true if the threshold was met, else false.
+		* If no threshold was set, then we return true.
+		* @inner
+		*/
+		function validateSwipeDistance() {
+			var valid = true;
+			//If we made it past the min swipe distance..
+			if (options.threshold !== null) {
+				valid = distance >= options.threshold;
+			}
+			
+            return valid;
+		}
+		
+		/**
+		* Checks the user has swiped back to cancel.
+		* @return Boolean if <code>cancelThreshold</code> has been set, return true if the cancelThreshold was met, else false.
+		* If no cancelThreshold was set, then we return true.
+		* @inner
+		*/
+		function didSwipeBackToCancel() {
+            var cancelled = false;
+    		if(options.cancelThreshold !== null && direction !==null)  {
+    		    cancelled =  (getMaxDistance( direction ) - distance) >= options.cancelThreshold;
+			}
+			
+			return cancelled;
+		}
+
+		/**
+		* Checks the user has pinched far enough
+		* @return Boolean if <code>pinchThreshold</code> has been set, return true if the threshold was met, else false.
+		* If no threshold was set, then we return true.
+		* @inner
+		*/
+		function validatePinchDistance() {
+			if (options.pinchThreshold !== null) {
+				return pinchDistance >= options.pinchThreshold;
+			}
+			return true;
+		}
+
+		/**
+		* Checks that the time taken to swipe meets the minimum / maximum requirements
+		* @return Boolean
+		* @inner
+		*/
+		function validateSwipeTime() {
+			var result;
+			//If no time set, then return true
+
+			if (options.maxTimeThreshold) {
+				if (duration >= options.maxTimeThreshold) {
+					result = false;
+				} else {
+					result = true;
+				}
+			}
+			else {
+				result = true;
+			}
+
+			return result;
+		}
+
+	
+
+		/**
+		* Checks direction of the swipe and the value allowPageScroll to see if we should allow or prevent the default behaviour from occurring.
+		* This will essentially allow page scrolling or not when the user is swiping on a touchSwipe object.
+		* @param {object} jqEvent The normalised jQuery representation of the event object.
+		* @param {string} direction The direction of the event. See {@link $.fn.swipe.directions}
+		* @see $.fn.swipe.directions
+		* @inner
+		*/
+		function validateDefaultEvent(jqEvent, direction) {
+
+			//If we have no pinches, then do this
+			//If we have a pinch, and we we have 2 fingers or more down, then dont allow page scroll.
+
+			//If the option is set, allways allow the event to bubble up (let user handle wiredness)
+			if( options.preventDefaultEvents === false) {
+				return;
+			}
+
+			if (options.allowPageScroll === NONE) {
+				jqEvent.preventDefault();
+			} else {
+				var auto = options.allowPageScroll === AUTO;
+
+				switch (direction) {
+					case LEFT:
+						if ((options.swipeLeft && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
+							jqEvent.preventDefault();
+						}
+						break;
+
+					case RIGHT:
+						if ((options.swipeRight && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
+							jqEvent.preventDefault();
+						}
+						break;
+
+					case UP:
+						if ((options.swipeUp && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
+							jqEvent.preventDefault();
+						}
+						break;
+
+					case DOWN:
+						if ((options.swipeDown && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
+							jqEvent.preventDefault();
+						}
+						break;
+				}
+			}
+
+		}
+
+
+		// PINCHES
+		/**
+		 * Returns true of the current pinch meets the thresholds
+		 * @return Boolean
+		 * @inner
+		*/
+		function validatePinch() {
+		    var hasCorrectFingerCount = validateFingers();
+		    var hasEndPoint = validateEndPoint();
+			var hasCorrectDistance = validatePinchDistance();
+			return hasCorrectFingerCount && hasEndPoint && hasCorrectDistance;
+			
+		}
+		
+		/**
+		 * Returns true if any Pinch events have been registered
+		 * @return Boolean
+		 * @inner
+		*/
+		function hasPinches() {
+			//Enure we dont return 0 or null for false values
+			return !!(options.pinchStatus || options.pinchIn || options.pinchOut);
+		}
+		
+		/**
+		 * Returns true if we are detecting pinches, and have one
+		 * @return Boolean
+		 * @inner
+		 */
+		function didPinch() {
+			//Enure we dont return 0 or null for false values
+			return !!(validatePinch() && hasPinches());
+		}
+
+
+
+
+		// SWIPES
+		/**
+		 * Returns true if the current swipe meets the thresholds
+		 * @return Boolean
+		 * @inner
+		*/
+		function validateSwipe() {
+			//Check validity of swipe
+			var hasValidTime = validateSwipeTime();
+			var hasValidDistance = validateSwipeDistance();	
+			var hasCorrectFingerCount = validateFingers();
+		    var hasEndPoint = validateEndPoint();
+		    var didCancel = didSwipeBackToCancel();	
+		    
+			// if the user swiped more than the minimum length, perform the appropriate action
+			// hasValidDistance is null when no distance is set 
+			var valid =  !didCancel && hasEndPoint && hasCorrectFingerCount && hasValidDistance && hasValidTime;
+			
+			return valid;
+		}
+		
+		/**
+		 * Returns true if any Swipe events have been registered
+		 * @return Boolean
+		 * @inner
+		*/
+		function hasSwipes() {
+			//Enure we dont return 0 or null for false values
+			return !!(options.swipe || options.swipeStatus || options.swipeLeft || options.swipeRight || options.swipeUp || options.swipeDown);
+		}
+		
+		
+		/**
+		 * Returns true if we are detecting swipes and have one
+		 * @return Boolean
+		 * @inner
+		*/
+		function didSwipe() {
+			//Enure we dont return 0 or null for false values
+			return !!(validateSwipe() && hasSwipes());
+		}
+
+        /**
+		 * Returns true if we have matched the number of fingers we are looking for
+		 * @return Boolean
+		 * @inner
+		*/
+        function validateFingers() {
+            //The number of fingers we want were matched, or on desktop we ignore
+    		return ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH);
+    	}
+        
+        /**
+		 * Returns true if we have an end point for the swipe
+		 * @return Boolean
+		 * @inner
+		*/
+        function validateEndPoint() {
+            //We have an end value for the finger
+		    return fingerData[0].end.x !== 0;
+        }
+
+		// TAP / CLICK
+		/**
+		 * Returns true if a click / tap events have been registered
+		 * @return Boolean
+		 * @inner
+		*/
+		function hasTap() {
+			//Enure we dont return 0 or null for false values
+			return !!(options.tap) ;
+		}
+		
+		/**
+		 * Returns true if a double tap events have been registered
+		 * @return Boolean
+		 * @inner
+		*/
+		function hasDoubleTap() {
+			//Enure we dont return 0 or null for false values
+			return !!(options.doubleTap) ;
+		}
+		
+		/**
+		 * Returns true if any long tap events have been registered
+		 * @return Boolean
+		 * @inner
+		*/
+		function hasLongTap() {
+			//Enure we dont return 0 or null for false values
+			return !!(options.longTap) ;
+		}
+		
+		/**
+		 * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
+		 * @return Boolean
+		 * @inner
+		*/
+		function validateDoubleTap() {
+		    if(doubleTapStartTime==null){
+		        return false;
+		    }
+		    var now = getTimeStamp();
+		    return (hasDoubleTap() && ((now-doubleTapStartTime) <= options.doubleTapThreshold));
+		}
+		
+		/**
+		 * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
+		 * @return Boolean
+		 * @inner
+		*/
+		function inDoubleTap() {
+		    return validateDoubleTap();
+		}
+		
+		
+		/**
+		 * Returns true if we have a valid tap
+		 * @return Boolean
+		 * @inner
+		*/
+		function validateTap() {
+		    return ((fingerCount === 1 || !SUPPORTS_TOUCH) && (isNaN(distance) || distance < options.threshold));
+		}
+		
+		/**
+		 * Returns true if we have a valid long tap
+		 * @return Boolean
+		 * @inner
+		*/
+		function validateLongTap() {
+		    //slight threshold on moving finger
+            return ((duration > options.longTapThreshold) && (distance < DOUBLE_TAP_THRESHOLD)); 
+		}
+		
+		/**
+		 * Returns true if we are detecting taps and have one
+		 * @return Boolean
+		 * @inner
+		*/
+		function didTap() {
+		    //Enure we dont return 0 or null for false values
+			return !!(validateTap() && hasTap());
+		}
+		
+		
+		/**
+		 * Returns true if we are detecting double taps and have one
+		 * @return Boolean
+		 * @inner
+		*/
+		function didDoubleTap() {
+		    //Enure we dont return 0 or null for false values
+			return !!(validateDoubleTap() && hasDoubleTap());
+		}
+		
+		/**
+		 * Returns true if we are detecting long taps and have one
+		 * @return Boolean
+		 * @inner
+		*/
+		function didLongTap() {
+		    //Enure we dont return 0 or null for false values
+			return !!(validateLongTap() && hasLongTap());
+		}
+		
+		
+		
+		
+		// MULTI FINGER TOUCH
+		/**
+		 * Starts tracking the time between 2 finger releases, and keeps track of how many fingers we initially had up
+		 * @inner
+		*/
+		function startMultiFingerRelease() {
+			previousTouchEndTime = getTimeStamp();
+			previousTouchFingerCount = event.touches.length+1;
+		}
+		
+		/**
+		 * Cancels the tracking of time between 2 finger releases, and resets counters
+		 * @inner
+		*/
+		function cancelMultiFingerRelease() {
+			previousTouchEndTime = 0;
+			previousTouchFingerCount = 0;
+		}
+		
+		/**
+		 * Checks if we are in the threshold between 2 fingers being released 
+		 * @return Boolean
+		 * @inner
+		*/
+		function inMultiFingerRelease() {
+			
+			var withinThreshold = false;
+			
+			if(previousTouchEndTime) {	
+				var diff = getTimeStamp() - previousTouchEndTime	
+				if( diff<=options.fingerReleaseThreshold ) {
+					withinThreshold = true;
+				}
+			}
+			
+			return withinThreshold;	
+		}
+		
+
+		/**
+		* gets a data flag to indicate that a touch is in progress
+		* @return Boolean
+		* @inner
+		*/
+		function getTouchInProgress() {
+			//strict equality to ensure only true and false are returned
+			return !!($element.data(PLUGIN_NS+'_intouch') === true);
+		}
+		
+		/**
+		* Sets a data flag to indicate that a touch is in progress
+		* @param {boolean} val The value to set the property to
+		* @inner
+		*/
+		function setTouchInProgress(val) {
+			
+			//Add or remove event listeners depending on touch status
+			if(val===true) {
+				$element.bind(MOVE_EV, touchMove);
+				$element.bind(END_EV, touchEnd);
+				
+				//we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
+				if(LEAVE_EV) { 
+					$element.bind(LEAVE_EV, touchLeave);
+				}
+			} else {
+				$element.unbind(MOVE_EV, touchMove, false);
+				$element.unbind(END_EV, touchEnd, false);
+			
+				//we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
+				if(LEAVE_EV) { 
+					$element.unbind(LEAVE_EV, touchLeave, false);
+				}
+			}
+			
+		
+			//strict equality to ensure only true and false can update the value
+			$element.data(PLUGIN_NS+'_intouch', val === true);
+		}
+		
+		
+		/**
+		 * Creates the finger data for the touch/finger in the event object.
+		 * @param {int} index The index in the array to store the finger data (usually the order the fingers were pressed)
+		 * @param {object} evt The event object containing finger data
+		 * @return finger data object
+		 * @inner
+		*/
+		function createFingerData( index, evt ) {
+			var id = evt.identifier!==undefined ? evt.identifier : 0; 
+			
+			fingerData[index].identifier = id;
+			fingerData[index].start.x = fingerData[index].end.x = evt.pageX||evt.clientX;
+			fingerData[index].start.y = fingerData[index].end.y = evt.pageY||evt.clientY;
+			
+			return fingerData[index];
+		}
+		
+		/**
+		 * Updates the finger data for a particular event object
+		 * @param {object} evt The event object containing the touch/finger data to upadte
+		 * @return a finger data object.
+		 * @inner
+		*/
+		function updateFingerData(evt) {
+			
+			var id = evt.identifier!==undefined ? evt.identifier : 0; 
+			var f = getFingerData( id );
+			
+			f.end.x = evt.pageX||evt.clientX;
+			f.end.y = evt.pageY||evt.clientY;
+			
+			return f;
+		}
+		
+		/**
+		 * Returns a finger data object by its event ID.
+		 * Each touch event has an identifier property, which is used 
+		 * to track repeat touches
+		 * @param {int} id The unique id of the finger in the sequence of touch events.
+		 * @return a finger data object.
+		 * @inner
+		*/
+		function getFingerData( id ) {
+			for(var i=0; i<fingerData.length; i++) {
+				if(fingerData[i].identifier == id) {
+					return fingerData[i];	
+				}
+			}
+		}
+		
+		/**
+		 * Creats all the finger onjects and returns an array of finger data
+		 * @return Array of finger objects
+		 * @inner
+		*/
+		function createAllFingerData() {
+			var fingerData=[];
+			for (var i=0; i<=5; i++) {
+				fingerData.push({
+					start:{ x: 0, y: 0 },
+					end:{ x: 0, y: 0 },
+					identifier:0
+				});
+			}
+			
+			return fingerData;
+		}
+		
+		/**
+		 * Sets the maximum distance swiped in the given direction. 
+		 * If the new value is lower than the current value, the max value is not changed.
+		 * @param {string}  direction The direction of the swipe
+		 * @param {int}  distance The distance of the swipe
+		 * @inner
+		*/
+		function setMaxDistance(direction, distance) {
+    		distance = Math.max(distance, getMaxDistance(direction) );
+    		maximumsMap[direction].distance = distance;
+		}
+        
+        /**
+		 * gets the maximum distance swiped in the given direction. 
+		 * @param {string}  direction The direction of the swipe
+		 * @return int  The distance of the swipe
+		 * @inner
+		*/        
+		function getMaxDistance(direction) {
+			if (maximumsMap[direction]) return maximumsMap[direction].distance;
+			return undefined;
+		}
+		
+		/**
+		 * Creats a map of directions to maximum swiped values.
+		 * @return Object A dictionary of maximum values, indexed by direction.
+		 * @inner
+		*/
+		function createMaximumsData() {
+			var maxData={};
+			maxData[LEFT]=createMaximumVO(LEFT);
+			maxData[RIGHT]=createMaximumVO(RIGHT);
+			maxData[UP]=createMaximumVO(UP);
+			maxData[DOWN]=createMaximumVO(DOWN);
+			
+			return maxData;
+		}
+		
+		/**
+		 * Creates a map maximum swiped values for a given swipe direction
+		 * @param {string} The direction that these values will be associated with
+		 * @return Object Maximum values
+		 * @inner
+		*/
+		function createMaximumVO(dir) {
+		    return { 
+		        direction:dir, 
+		        distance:0
+		    }
+		}
+		
+		
+		//
+		// MATHS / UTILS
+		//
+
+		/**
+		* Calculate the duration of the swipe
+		* @return int
+		* @inner
+		*/
+		function calculateDuration() {
+			return endTime - startTime;
+		}
+		
+		/**
+		* Calculate the distance between 2 touches (pinch)
+		* @param {point} startPoint A point object containing x and y co-ordinates
+	    * @param {point} endPoint A point object containing x and y co-ordinates
+	    * @return int;
+		* @inner
+		*/
+		function calculateTouchesDistance(startPoint, endPoint) {
+			var diffX = Math.abs(startPoint.x - endPoint.x);
+			var diffY = Math.abs(startPoint.y - endPoint.y);
+				
+			return Math.round(Math.sqrt(diffX*diffX+diffY*diffY));
+		}
+		
+		/**
+		* Calculate the zoom factor between the start and end distances
+		* @param {int} startDistance Distance (between 2 fingers) the user started pinching at
+	    * @param {int} endDistance Distance (between 2 fingers) the user ended pinching at
+	    * @return float The zoom value from 0 to 1.
+		* @inner
+		*/
+		function calculatePinchZoom(startDistance, endDistance) {
+			var percent = (endDistance/startDistance) * 1;
+			return percent.toFixed(2);
+		}
+		
+		
+		/**
+		* Returns the pinch direction, either IN or OUT for the given points
+		* @return string Either {@link $.fn.swipe.directions.IN} or {@link $.fn.swipe.directions.OUT}
+		* @see $.fn.swipe.directions
+		* @inner
+		*/
+		function calculatePinchDirection() {
+			if(pinchZoom<1) {
+				return OUT;
+			}
+			else {
+				return IN;
+			}
+		}
+		
+		
+		/**
+		* Calculate the length / distance of the swipe
+		* @param {point} startPoint A point object containing x and y co-ordinates
+	    * @param {point} endPoint A point object containing x and y co-ordinates
+	    * @return int
+		* @inner
+		*/
+		function calculateDistance(startPoint, endPoint) {
+			return Math.round(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)));
+		}
+
+		/**
+		* Calculate the angle of the swipe
+		* @param {point} startPoint A point object containing x and y co-ordinates
+	    * @param {point} endPoint A point object containing x and y co-ordinates
+	    * @return int
+		* @inner
+		*/
+		function calculateAngle(startPoint, endPoint) {
+			var x = startPoint.x - endPoint.x;
+			var y = endPoint.y - startPoint.y;
+			var r = Math.atan2(y, x); //radians
+			var angle = Math.round(r * 180 / Math.PI); //degrees
+
+			//ensure value is positive
+			if (angle < 0) {
+				angle = 360 - Math.abs(angle);
+			}
+
+			return angle;
+		}
+
+		/**
+		* Calculate the direction of the swipe
+		* This will also call calculateAngle to get the latest angle of swipe
+		* @param {point} startPoint A point object containing x and y co-ordinates
+	    * @param {point} endPoint A point object containing x and y co-ordinates
+	    * @return string Either {@link $.fn.swipe.directions.LEFT} / {@link $.fn.swipe.directions.RIGHT} / {@link $.fn.swipe.directions.DOWN} / {@link $.fn.swipe.directions.UP}
+		* @see $.fn.swipe.directions
+		* @inner
+		*/
+		function calculateDirection(startPoint, endPoint ) {
+			var angle = calculateAngle(startPoint, endPoint);
+
+			if ((angle <= 45) && (angle >= 0)) {
+				return LEFT;
+			} else if ((angle <= 360) && (angle >= 315)) {
+				return LEFT;
+			} else if ((angle >= 135) && (angle <= 225)) {
+				return RIGHT;
+			} else if ((angle > 45) && (angle < 135)) {
+				return DOWN;
+			} else {
+				return UP;
+			}
+		}
+		
+
+		/**
+		* Returns a MS time stamp of the current time
+		* @return int
+		* @inner
+		*/
+		function getTimeStamp() {
+			var now = new Date();
+			return now.getTime();
+		}
+		
+		
+		
+		/**
+		 * Returns a bounds object with left, right, top and bottom properties for the element specified.
+		 * @param {DomNode} The DOM node to get the bounds for.
+		 */
+		function getbounds( el ) {
+			el = $(el);
+			var offset = el.offset();
+			
+			var bounds = {	
+					left:offset.left,
+					right:offset.left+el.outerWidth(),
+					top:offset.top,
+					bottom:offset.top+el.outerHeight()
+					}
+			
+			return bounds;	
+		}
+		
+		
+		/**
+		 * Checks if the point object is in the bounds object.
+		 * @param {object} point A point object.
+		 * @param {int} point.x The x value of the point.
+		 * @param {int} point.y The x value of the point.
+		 * @param {object} bounds The bounds object to test
+		 * @param {int} bounds.left The leftmost value
+		 * @param {int} bounds.right The righttmost value
+		 * @param {int} bounds.top The topmost value
+		* @param {int} bounds.bottom The bottommost value
+		 */
+		function isInBounds(point, bounds) {
+			return (point.x > bounds.left && point.x < bounds.right && point.y > bounds.top && point.y < bounds.bottom);
+		};
+	
+	
+	}
+	
+	
+
+
+/**
+ * A catch all handler that is triggered for all swipe directions. 
+ * @name $.fn.swipe#swipe
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user swiped
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+ 
+
+
+
+/**
+ * A handler that is triggered for "left" swipes.
+ * @name $.fn.swipe#swipeLeft
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user swiped
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+ 
+/**
+ * A handler that is triggered for "right" swipes.
+ * @name $.fn.swipe#swipeRight
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user swiped
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+
+/**
+ * A handler that is triggered for "up" swipes.
+ * @name $.fn.swipe#swipeUp
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user swiped
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+ 
+/**
+ * A handler that is triggered for "down" swipes.
+ * @name $.fn.swipe#swipeDown
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user swiped
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+ 
+/**
+ * A handler triggered for every phase of the swipe. This handler is constantly fired for the duration of the pinch.
+ * This is triggered regardless of swipe thresholds.
+ * @name $.fn.swipe#swipeStatus
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {string} phase The phase of the swipe event. See {@link $.fn.swipe.phases}
+ * @param {string} direction The direction the user swiped in. This is null if the user has yet to move. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user swiped. This is 0 if the user has yet to move.
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+ 
+/**
+ * A handler triggered for pinch in events.
+ * @name $.fn.swipe#pinchIn
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user pinched
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+
+/**
+ * A handler triggered for pinch out events.
+ * @name $.fn.swipe#pinchOut
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user pinched
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
+ * @param {object} fingerData The coordinates of fingers in event
+ */ 
+
+/**
+ * A handler triggered for all pinch events. This handler is constantly fired for the duration of the pinch. This is triggered regardless of thresholds.
+ * @name $.fn.swipe#pinchStatus
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
+ * @param {int} distance The distance the user pinched
+ * @param {int} duration The duration of the swipe in milliseconds
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
+ * @param {object} fingerData The coordinates of fingers in event
+ */
+
+/**
+ * A click handler triggered when a user simply clicks, rather than swipes on an element.
+ * This is deprecated since version 1.6.2, any assignment to click will be assigned to the tap handler.
+ * You cannot use <code>on</code> to bind to this event as the default jQ <code>click</code> event will be triggered.
+ * Use the <code>tap</code> event instead.
+ * @name $.fn.swipe#click
+ * @event
+ * @deprecated since version 1.6.2, please use {@link $.fn.swipe#tap} instead 
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {DomObject} target The element clicked on.
+ */
+ 
+ /**
+ * A click / tap handler triggered when a user simply clicks or taps, rather than swipes on an element.
+ * @name $.fn.swipe#tap
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {DomObject} target The element clicked on.
+ */
+ 
+/**
+ * A double tap handler triggered when a user double clicks or taps on an element.
+ * You can set the time delay for a double tap with the {@link $.fn.swipe.defaults#doubleTapThreshold} property. 
+ * Note: If you set both <code>doubleTap</code> and <code>tap</code> handlers, the <code>tap</code> event will be delayed by the <code>doubleTapThreshold</code>
+ * as the script needs to check if its a double tap.
+ * @name $.fn.swipe#doubleTap
+ * @see  $.fn.swipe.defaults#doubleTapThreshold
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {DomObject} target The element clicked on.
+ */
+ 
+ /**
+ * A long tap handler triggered once a tap has been release if the tap was longer than the longTapThreshold.
+ * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property. 
+ * @name $.fn.swipe#longTap
+ * @see  $.fn.swipe.defaults#longTapThreshold
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {DomObject} target The element clicked on.
+ */
+
+  /**
+ * A hold tap handler triggered as soon as the longTapThreshold is reached
+ * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property. 
+ * @name $.fn.swipe#hold
+ * @see  $.fn.swipe.defaults#longTapThreshold
+ * @event
+ * @default null
+ * @param {EventObject} event The original event object
+ * @param {DomObject} target The element clicked on.
+ */
+
+}));
diff --git a/static/js/jquery-1.3.2.js b/static/js/jquery-1.3.2.js
deleted file mode 100644
index 462cde5..0000000
--- a/static/js/jquery-1.3.2.js
+++ /dev/null
@@ -1,4376 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.3.2
- * http://jquery.com/
- *
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- *
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
- */
-(function(){
-
-var 
-	// Will speed up references to window, and allows munging its name.
-	window = this,
-	// Will speed up references to undefined, and allows munging its name.
-	undefined,
-	// Map over jQuery in case of overwrite
-	_jQuery = window.jQuery,
-	// Map over the $ in case of overwrite
-	_$ = window.$,
-
-	jQuery = window.jQuery = window.$ = function( selector, context ) {
-		// The jQuery object is actually just the init constructor 'enhanced'
-		return new jQuery.fn.init( selector, context );
-	},
-
-	// A simple way to check for HTML strings or ID strings
-	// (both of which we optimize for)
-	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
-	// Is it a simple selector
-	isSimple = /^.[^:#\[\.,]*$/;
-
-jQuery.fn = jQuery.prototype = {
-	init: function( selector, context ) {
-		// Make sure that a selection was provided
-		selector = selector || document;
-
-		// Handle $(DOMElement)
-		if ( selector.nodeType ) {
-			this[0] = selector;
-			this.length = 1;
-			this.context = selector;
-			return this;
-		}
-		// Handle HTML strings
-		if ( typeof selector === "string" ) {
-			// Are we dealing with HTML string or an ID?
-			var match = quickExpr.exec( selector );
-
-			// Verify a match, and that no context was specified for #id
-			if ( match && (match[1] || !context) ) {
-
-				// HANDLE: $(html) -> $(array)
-				if ( match[1] )
-					selector = jQuery.clean( [ match[1] ], context );
-
-				// HANDLE: $("#id")
-				else {
-					var elem = document.getElementById( match[3] );
-
-					// Handle the case where IE and Opera return items
-					// by name instead of ID
-					if ( elem && elem.id != match[3] )
-						return jQuery().find( selector );
-
-					// Otherwise, we inject the element directly into the jQuery object
-					var ret = jQuery( elem || [] );
-					ret.context = document;
-					ret.selector = selector;
-					return ret;
-				}
-
-			// HANDLE: $(expr, [context])
-			// (which is just equivalent to: $(content).find(expr)
-			} else
-				return jQuery( context ).find( selector );
-
-		// HANDLE: $(function)
-		// Shortcut for document ready
-		} else if ( jQuery.isFunction( selector ) )
-			return jQuery( document ).ready( selector );
-
-		// Make sure that old selector state is passed along
-		if ( selector.selector && selector.context ) {
-			this.selector = selector.selector;
-			this.context = selector.context;
-		}
-
-		return this.setArray(jQuery.isArray( selector ) ?
-			selector :
-			jQuery.makeArray(selector));
-	},
-
-	// Start with an empty selector
-	selector: "",
-
-	// The current version of jQuery being used
-	jquery: "1.3.2",
-
-	// The number of elements contained in the matched element set
-	size: function() {
-		return this.length;
-	},
-
-	// Get the Nth element in the matched element set OR
-	// Get the whole matched element set as a clean array
-	get: function( num ) {
-		return num === undefined ?
-
-			// Return a 'clean' array
-			Array.prototype.slice.call( this ) :
-
-			// Return just the object
-			this[ num ];
-	},
-
-	// Take an array of elements and push it onto the stack
-	// (returning the new matched element set)
-	pushStack: function( elems, name, selector ) {
-		// Build a new jQuery matched element set
-		var ret = jQuery( elems );
-
-		// Add the old object onto the stack (as a reference)
-		ret.prevObject = this;
-
-		ret.context = this.context;
-
-		if ( name === "find" )
-			ret.selector = this.selector + (this.selector ? " " : "") + selector;
-		else if ( name )
-			ret.selector = this.selector + "." + name + "(" + selector + ")";
-
-		// Return the newly-formed element set
-		return ret;
-	},
-
-	// Force the current matched set of elements to become
-	// the specified array of elements (destroying the stack in the process)
-	// You should use pushStack() in order to do this, but maintain the stack
-	setArray: function( elems ) {
-		// Resetting the length to 0, then using the native Array push
-		// is a super-fast way to populate an object with array-like properties
-		this.length = 0;
-		Array.prototype.push.apply( this, elems );
-
-		return this;
-	},
-
-	// Execute a callback for every element in the matched set.
-	// (You can seed the arguments with an array of args, but this is
-	// only used internally.)
-	each: function( callback, args ) {
-		return jQuery.each( this, callback, args );
-	},
-
-	// Determine the position of an element within
-	// the matched set of elements
-	index: function( elem ) {
-		// Locate the position of the desired element
-		return jQuery.inArray(
-			// If it receives a jQuery object, the first element is used
-			elem && elem.jquery ? elem[0] : elem
-		, this );
-	},
-
-	attr: function( name, value, type ) {
-		var options = name;
-
-		// Look for the case where we're accessing a style value
-		if ( typeof name === "string" )
-			if ( value === undefined )
-				return this[0] && jQuery[ type || "attr" ]( this[0], name );
-
-			else {
-				options = {};
-				options[ name ] = value;
-			}
-
-		// Check to see if we're setting style values
-		return this.each(function(i){
-			// Set all the styles
-			for ( name in options )
-				jQuery.attr(
-					type ?
-						this.style :
-						this,
-					name, jQuery.prop( this, options[ name ], type, i, name )
-				);
-		});
-	},
-
-	css: function( key, value ) {
-		// ignore negative width and height values
-		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
-			value = undefined;
-		return this.attr( key, value, "curCSS" );
-	},
-
-	text: function( text ) {
-		if ( typeof text !== "object" && text != null )
-			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
-
-		var ret = "";
-
-		jQuery.each( text || this, function(){
-			jQuery.each( this.childNodes, function(){
-				if ( this.nodeType != 8 )
-					ret += this.nodeType != 1 ?
-						this.nodeValue :
-						jQuery.fn.text( [ this ] );
-			});
-		});
-
-		return ret;
-	},
-
-	wrapAll: function( html ) {
-		if ( this[0] ) {
-			// The elements to wrap the target around
-			var wrap = jQuery( html, this[0].ownerDocument ).clone();
-
-			if ( this[0].parentNode )
-				wrap.insertBefore( this[0] );
-
-			wrap.map(function(){
-				var elem = this;
-
-				while ( elem.firstChild )
-					elem = elem.firstChild;
-
-				return elem;
-			}).append(this);
-		}
-
-		return this;
-	},
-
-	wrapInner: function( html ) {
-		return this.each(function(){
-			jQuery( this ).contents().wrapAll( html );
-		});
-	},
-
-	wrap: function( html ) {
-		return this.each(function(){
-			jQuery( this ).wrapAll( html );
-		});
-	},
-
-	append: function() {
-		return this.domManip(arguments, true, function(elem){
-			if (this.nodeType == 1)
-				this.appendChild( elem );
-		});
-	},
-
-	prepend: function() {
-		return this.domManip(arguments, true, function(elem){
-			if (this.nodeType == 1)
-				this.insertBefore( elem, this.firstChild );
-		});
-	},
-
-	before: function() {
-		return this.domManip(arguments, false, function(elem){
-			this.parentNode.insertBefore( elem, this );
-		});
-	},
-
-	after: function() {
-		return this.domManip(arguments, false, function(elem){
-			this.parentNode.insertBefore( elem, this.nextSibling );
-		});
-	},
-
-	end: function() {
-		return this.prevObject || jQuery( [] );
-	},
-
-	// For internal use only.
-	// Behaves like an Array's method, not like a jQuery method.
-	push: [].push,
-	sort: [].sort,
-	splice: [].splice,
-
-	find: function( selector ) {
-		if ( this.length === 1 ) {
-			var ret = this.pushStack( [], "find", selector );
-			ret.length = 0;
-			jQuery.find( selector, this[0], ret );
-			return ret;
-		} else {
-			return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
-				return jQuery.find( selector, elem );
-			})), "find", selector );
-		}
-	},
-
-	clone: function( events ) {
-		// Do the clone
-		var ret = this.map(function(){
-			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
-				// IE copies events bound via attachEvent when
-				// using cloneNode. Calling detachEvent on the
-				// clone will also remove the events from the orignal
-				// In order to get around this, we use innerHTML.
-				// Unfortunately, this means some modifications to
-				// attributes in IE that are actually only stored
-				// as properties will not be copied (such as the
-				// the name attribute on an input).
-				var html = this.outerHTML;
-				if ( !html ) {
-					var div = this.ownerDocument.createElement("div");
-					div.appendChild( this.cloneNode(true) );
-					html = div.innerHTML;
-				}
-
-				return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
-			} else
-				return this.cloneNode(true);
-		});
-
-		// Copy the events from the original to the clone
-		if ( events === true ) {
-			var orig = this.find("*").andSelf(), i = 0;
-
-			ret.find("*").andSelf().each(function(){
-				if ( this.nodeName !== orig[i].nodeName )
-					return;
-
-				var events = jQuery.data( orig[i], "events" );
-
-				for ( var type in events ) {
-					for ( var handler in events[ type ] ) {
-						jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
-					}
-				}
-
-				i++;
-			});
-		}
-
-		// Return the cloned set
-		return ret;
-	},
-
-	filter: function( selector ) {
-		return this.pushStack(
-			jQuery.isFunction( selector ) &&
-			jQuery.grep(this, function(elem, i){
-				return selector.call( elem, i );
-			}) ||
-
-			jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
-				return elem.nodeType === 1;
-			}) ), "filter", selector );
-	},
-
-	closest: function( selector ) {
-		var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
-			closer = 0;
-
-		return this.map(function(){
-			var cur = this;
-			while ( cur && cur.ownerDocument ) {
-				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
-					jQuery.data(cur, "closest", closer);
-					return cur;
-				}
-				cur = cur.parentNode;
-				closer++;
-			}
-		});
-	},
-
-	not: function( selector ) {
-		if ( typeof selector === "string" )
-			// test special case where just one selector is passed in
-			if ( isSimple.test( selector ) )
-				return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
-			else
-				selector = jQuery.multiFilter( selector, this );
-
-		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
-		return this.filter(function() {
-			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
-		});
-	},
-
-	add: function( selector ) {
-		return this.pushStack( jQuery.unique( jQuery.merge(
-			this.get(),
-			typeof selector === "string" ?
-				jQuery( selector ) :
-				jQuery.makeArray( selector )
-		)));
-	},
-
-	is: function( selector ) {
-		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
-	},
-
-	hasClass: function( selector ) {
-		return !!selector && this.is( "." + selector );
-	},
-
-	val: function( value ) {
-		if ( value === undefined ) {			
-			var elem = this[0];
-
-			if ( elem ) {
-				if( jQuery.nodeName( elem, 'option' ) )
-					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
-				
-				// We need to handle select boxes special
-				if ( jQuery.nodeName( elem, "select" ) ) {
-					var index = elem.selectedIndex,
-						values = [],
-						options = elem.options,
-						one = elem.type == "select-one";
-
-					// Nothing was selected
-					if ( index < 0 )
-						return null;
-
-					// Loop through all the selected options
-					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
-						var option = options[ i ];
-
-						if ( option.selected ) {
-							// Get the specifc value for the option
-							value = jQuery(option).val();
-
-							// We don't need an array for one selects
-							if ( one )
-								return value;
-
-							// Multi-Selects return an array
-							values.push( value );
-						}
-					}
-
-					return values;				
-				}
-
-				// Everything else, we just grab the value
-				return (elem.value || "").replace(/\r/g, "");
-
-			}
-
-			return undefined;
-		}
-
-		if ( typeof value === "number" )
-			value += '';
-
-		return this.each(function(){
-			if ( this.nodeType != 1 )
-				return;
-
-			if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
-				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
-					jQuery.inArray(this.name, value) >= 0);
-
-			else if ( jQuery.nodeName( this, "select" ) ) {
-				var values = jQuery.makeArray(value);
-
-				jQuery( "option", this ).each(function(){
-					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
-						jQuery.inArray( this.text, values ) >= 0);
-				});
-
-				if ( !values.length )
-					this.selectedIndex = -1;
-
-			} else
-				this.value = value;
-		});
-	},
-
-	html: function( value ) {
-		return value === undefined ?
-			(this[0] ?
-				this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
-				null) :
-			this.empty().append( value );
-	},
-
-	replaceWith: function( value ) {
-		return this.after( value ).remove();
-	},
-
-	eq: function( i ) {
-		return this.slice( i, +i + 1 );
-	},
-
-	slice: function() {
-		return this.pushStack( Array.prototype.slice.apply( this, arguments ),
-			"slice", Array.prototype.slice.call(arguments).join(",") );
-	},
-
-	map: function( callback ) {
-		return this.pushStack( jQuery.map(this, function(elem, i){
-			return callback.call( elem, i, elem );
-		}));
-	},
-
-	andSelf: function() {
-		return this.add( this.prevObject );
-	},
-
-	domManip: function( args, table, callback ) {
-		if ( this[0] ) {
-			var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
-				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
-				first = fragment.firstChild;
-
-			if ( first )
-				for ( var i = 0, l = this.length; i < l; i++ )
-					callback.call( root(this[i], first), this.length > 1 || i > 0 ?
-							fragment.cloneNode(true) : fragment );
-		
-			if ( scripts )
-				jQuery.each( scripts, evalScript );
-		}
-
-		return this;
-		
-		function root( elem, cur ) {
-			return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
-				(elem.getElementsByTagName("tbody")[0] ||
-				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
-				elem;
-		}
-	}
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-function evalScript( i, elem ) {
-	if ( elem.src )
-		jQuery.ajax({
-			url: elem.src,
-			async: false,
-			dataType: "script"
-		});
-
-	else
-		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
-
-	if ( elem.parentNode )
-		elem.parentNode.removeChild( elem );
-}
-
-function now(){
-	return +new Date;
-}
-
-jQuery.extend = jQuery.fn.extend = function() {
-	// copy reference to target object
-	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
-
-	// Handle a deep copy situation
-	if ( typeof target === "boolean" ) {
-		deep = target;
-		target = arguments[1] || {};
-		// skip the boolean and the target
-		i = 2;
-	}
-
-	// Handle case when target is a string or something (possible in deep copy)
-	if ( typeof target !== "object" && !jQuery.isFunction(target) )
-		target = {};
-
-	// extend jQuery itself if only one argument is passed
-	if ( length == i ) {
-		target = this;
-		--i;
-	}
-
-	for ( ; i < length; i++ )
-		// Only deal with non-null/undefined values
-		if ( (options = arguments[ i ]) != null )
-			// Extend the base object
-			for ( var name in options ) {
-				var src = target[ name ], copy = options[ name ];
-
-				// Prevent never-ending loop
-				if ( target === copy )
-					continue;
-
-				// Recurse if we're merging object values
-				if ( deep && copy && typeof copy === "object" && !copy.nodeType )
-					target[ name ] = jQuery.extend( deep, 
-						// Never move original objects, clone them
-						src || ( copy.length != null ? [ ] : { } )
-					, copy );
-
-				// Don't bring in undefined values
-				else if ( copy !== undefined )
-					target[ name ] = copy;
-
-			}
-
-	// Return the modified object
-	return target;
-};
-
-// exclude the following css properties to add px
-var	exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
-	// cache defaultView
-	defaultView = document.defaultView || {},
-	toString = Object.prototype.toString;
-
-jQuery.extend({
-	noConflict: function( deep ) {
-		window.$ = _$;
-
-		if ( deep )
-			window.jQuery = _jQuery;
-
-		return jQuery;
-	},
-
-	// See test/unit/core.js for details concerning isFunction.
-	// Since version 1.3, DOM methods and functions like alert
-	// aren't supported. They return false on IE (#2968).
-	isFunction: function( obj ) {
-		return toString.call(obj) === "[object Function]";
-	},
-
-	isArray: function( obj ) {
-		return toString.call(obj) === "[object Array]";
-	},
-
-	// check if an element is in a (or is an) XML document
-	isXMLDoc: function( elem ) {
-		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
-			!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
-	},
-
-	// Evalulates a script in a global context
-	globalEval: function( data ) {
-		if ( data && /\S/.test(data) ) {
-			// Inspired by code by Andrea Giammarchi
-			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
-			var head = document.getElementsByTagName("head")[0] || document.documentElement,
-				script = document.createElement("script");
-
-			script.type = "text/javascript";
-			if ( jQuery.support.scriptEval )
-				script.appendChild( document.createTextNode( data ) );
-			else
-				script.text = data;
-
-			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
-			// This arises when a base node is used (#2709).
-			head.insertBefore( script, head.firstChild );
-			head.removeChild( script );
-		}
-	},
-
-	nodeName: function( elem, name ) {
-		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
-	},
-
-	// args is for internal usage only
-	each: function( object, callback, args ) {
-		var name, i = 0, length = object.length;
-
-		if ( args ) {
-			if ( length === undefined ) {
-				for ( name in object )
-					if ( callback.apply( object[ name ], args ) === false )
-						break;
-			} else
-				for ( ; i < length; )
-					if ( callback.apply( object[ i++ ], args ) === false )
-						break;
-
-		// A special, fast, case for the most common use of each
-		} else {
-			if ( length === undefined ) {
-				for ( name in object )
-					if ( callback.call( object[ name ], name, object[ name ] ) === false )
-						break;
-			} else
-				for ( var value = object[0];
-					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
-		}
-
-		return object;
-	},
-
-	prop: function( elem, value, type, i, name ) {
-		// Handle executable functions
-		if ( jQuery.isFunction( value ) )
-			value = value.call( elem, i );
-
-		// Handle passing in a number to a CSS property
-		return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
-			value + "px" :
-			value;
-	},
-
-	className: {
-		// internal only, use addClass("class")
-		add: function( elem, classNames ) {
-			jQuery.each((classNames || "").split(/\s+/), function(i, className){
-				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
-					elem.className += (elem.className ? " " : "") + className;
-			});
-		},
-
-		// internal only, use removeClass("class")
-		remove: function( elem, classNames ) {
-			if (elem.nodeType == 1)
-				elem.className = classNames !== undefined ?
-					jQuery.grep(elem.className.split(/\s+/), function(className){
-						return !jQuery.className.has( classNames, className );
-					}).join(" ") :
-					"";
-		},
-
-		// internal only, use hasClass("class")
-		has: function( elem, className ) {
-			return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
-		}
-	},
-
-	// A method for quickly swapping in/out CSS properties to get correct calculations
-	swap: function( elem, options, callback ) {
-		var old = {};
-		// Remember the old values, and insert the new ones
-		for ( var name in options ) {
-			old[ name ] = elem.style[ name ];
-			elem.style[ name ] = options[ name ];
-		}
-
-		callback.call( elem );
-
-		// Revert the old values
-		for ( var name in options )
-			elem.style[ name ] = old[ name ];
-	},
-
-	css: function( elem, name, force, extra ) {
-		if ( name == "width" || name == "height" ) {
-			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
-
-			function getWH() {
-				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
-
-				if ( extra === "border" )
-					return;
-
-				jQuery.each( which, function() {
-					if ( !extra )
-						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
-					if ( extra === "margin" )
-						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
-					else
-						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
-				});
-			}
-
-			if ( elem.offsetWidth !== 0 )
-				getWH();
-			else
-				jQuery.swap( elem, props, getWH );
-
-			return Math.max(0, Math.round(val));
-		}
-
-		return jQuery.curCSS( elem, name, force );
-	},
-
-	curCSS: function( elem, name, force ) {
-		var ret, style = elem.style;
-
-		// We need to handle opacity special in IE
-		if ( name == "opacity" && !jQuery.support.opacity ) {
-			ret = jQuery.attr( style, "opacity" );
-
-			return ret == "" ?
-				"1" :
-				ret;
-		}
-
-		// Make sure we're using the right name for getting the float value
-		if ( name.match( /float/i ) )
-			name = styleFloat;
-
-		if ( !force && style && style[ name ] )
-			ret = style[ name ];
-
-		else if ( defaultView.getComputedStyle ) {
-
-			// Only "float" is needed here
-			if ( name.match( /float/i ) )
-				name = "float";
-
-			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
-
-			var computedStyle = defaultView.getComputedStyle( elem, null );
-
-			if ( computedStyle )
-				ret = computedStyle.getPropertyValue( name );
-
-			// We should always get a number back from opacity
-			if ( name == "opacity" && ret == "" )
-				ret = "1";
-
-		} else if ( elem.currentStyle ) {
-			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
-				return letter.toUpperCase();
-			});
-
-			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
-
-			// From the awesome hack by Dean Edwards
-			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
-			// If we're not dealing with a regular pixel number
-			// but a number that has a weird ending, we need to convert it to pixels
-			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
-				// Remember the original values
-				var left = style.left, rsLeft = elem.runtimeStyle.left;
-
-				// Put in the new values to get a computed value out
-				elem.runtimeStyle.left = elem.currentStyle.left;
-				style.left = ret || 0;
-				ret = style.pixelLeft + "px";
-
-				// Revert the changed values
-				style.left = left;
-				elem.runtimeStyle.left = rsLeft;
-			}
-		}
-
-		return ret;
-	},
-
-	clean: function( elems, context, fragment ) {
-		context = context || document;
-
-		// !context.createElement fails in IE with an error but returns typeof 'object'
-		if ( typeof context.createElement === "undefined" )
-			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
-
-		// If a single string is passed in and it's a single tag
-		// just do a createElement and skip the rest
-		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
-			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
-			if ( match )
-				return [ context.createElement( match[1] ) ];
-		}
-
-		var ret = [], scripts = [], div = context.createElement("div");
-
-		jQuery.each(elems, function(i, elem){
-			if ( typeof elem === "number" )
-				elem += '';
-
-			if ( !elem )
-				return;
-
-			// Convert html string into DOM nodes
-			if ( typeof elem === "string" ) {
-				// Fix "XHTML"-style tags in all browsers
-				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
-					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
-						all :
-						front + "></" + tag + ">";
-				});
-
-				// Trim whitespace, otherwise indexOf won't work as expected
-				var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
-
-				var wrap =
-					// option or optgroup
-					!tags.indexOf("<opt") &&
-					[ 1, "<select multiple='multiple'>", "</select>" ] ||
-
-					!tags.indexOf("<leg") &&
-					[ 1, "<fieldset>", "</fieldset>" ] ||
-
-					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
-					[ 1, "<table>", "</table>" ] ||
-
-					!tags.indexOf("<tr") &&
-					[ 2, "<table><tbody>", "</tbody></table>" ] ||
-
-				 	// <thead> matched above
-					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
-					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
-
-					!tags.indexOf("<col") &&
-					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
-
-					// IE can't serialize <link> and <script> tags normally
-					!jQuery.support.htmlSerialize &&
-					[ 1, "div<div>", "</div>" ] ||
-
-					[ 0, "", "" ];
-
-				// Go to html and back, then peel off extra wrappers
-				div.innerHTML = wrap[1] + elem + wrap[2];
-
-				// Move to the right depth
-				while ( wrap[0]-- )
-					div = div.lastChild;
-
-				// Remove IE's autoinserted <tbody> from table fragments
-				if ( !jQuery.support.tbody ) {
-
-					// String was a <table>, *may* have spurious <tbody>
-					var hasBody = /<tbody/i.test(elem),
-						tbody = !tags.indexOf("<table") && !hasBody ?
-							div.firstChild && div.firstChild.childNodes :
-
-						// String was a bare <thead> or <tfoot>
-						wrap[1] == "<table>" && !hasBody ?
-							div.childNodes :
-							[];
-
-					for ( var j = tbody.length - 1; j >= 0 ; --j )
-						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
-							tbody[ j ].parentNode.removeChild( tbody[ j ] );
-
-					}
-
-				// IE completely kills leading whitespace when innerHTML is used
-				if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
-					div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
-				
-				elem = jQuery.makeArray( div.childNodes );
-			}
-
-			if ( elem.nodeType )
-				ret.push( elem );
-			else
-				ret = jQuery.merge( ret, elem );
-
-		});
-
-		if ( fragment ) {
-			for ( var i = 0; ret[i]; i++ ) {
-				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
-					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
-				} else {
-					if ( ret[i].nodeType === 1 )
-						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
-					fragment.appendChild( ret[i] );
-				}
-			}
-			
-			return scripts;
-		}
-
-		return ret;
-	},
-
-	attr: function( elem, name, value ) {
-		// don't set attributes on text and comment nodes
-		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
-			return undefined;
-
-		var notxml = !jQuery.isXMLDoc( elem ),
-			// Whether we are setting (or getting)
-			set = value !== undefined;
-
-		// Try to normalize/fix the name
-		name = notxml && jQuery.props[ name ] || name;
-
-		// Only do all the following if this is a node (faster for style)
-		// IE elem.getAttribute passes even for style
-		if ( elem.tagName ) {
-
-			// These attributes require special treatment
-			var special = /href|src|style/.test( name );
-
-			// Safari mis-reports the default selected property of a hidden option
-			// Accessing the parent's selectedIndex property fixes it
-			if ( name == "selected" && elem.parentNode )
-				elem.parentNode.selectedIndex;
-
-			// If applicable, access the attribute via the DOM 0 way
-			if ( name in elem && notxml && !special ) {
-				if ( set ){
-					// We can't allow the type property to be changed (since it causes problems in IE)
-					if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
-						throw "type property can't be changed";
-
-					elem[ name ] = value;
-				}
-
-				// browsers index elements by id/name on forms, give priority to attributes.
-				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
-					return elem.getAttributeNode( name ).nodeValue;
-
-				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
-				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
-				if ( name == "tabIndex" ) {
-					var attributeNode = elem.getAttributeNode( "tabIndex" );
-					return attributeNode && attributeNode.specified
-						? attributeNode.value
-						: elem.nodeName.match(/(button|input|object|select|textarea)/i)
-							? 0
-							: elem.nodeName.match(/^(a|area)$/i) && elem.href
-								? 0
-								: undefined;
-				}
-
-				return elem[ name ];
-			}
-
-			if ( !jQuery.support.style && notxml &&  name == "style" )
-				return jQuery.attr( elem.style, "cssText", value );
-
-			if ( set )
-				// convert the value to a string (all browsers do this but IE) see #1070
-				elem.setAttribute( name, "" + value );
-
-			var attr = !jQuery.support.hrefNormalized && notxml && special
-					// Some attributes require a special call on IE
-					? elem.getAttribute( name, 2 )
-					: elem.getAttribute( name );
-
-			// Non-existent attributes return null, we normalize to undefined
-			return attr === null ? undefined : attr;
-		}
-
-		// elem is actually elem.style ... set the style
-
-		// IE uses filters for opacity
-		if ( !jQuery.support.opacity && name == "opacity" ) {
-			if ( set ) {
-				// IE has trouble with opacity if it does not have layout
-				// Force it by setting the zoom level
-				elem.zoom = 1;
-
-				// Set the alpha filter to set the opacity
-				elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
-					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
-			}
-
-			return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
-				(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
-				"";
-		}
-
-		name = name.replace(/-([a-z])/ig, function(all, letter){
-			return letter.toUpperCase();
-		});
-
-		if ( set )
-			elem[ name ] = value;
-
-		return elem[ name ];
-	},
-
-	trim: function( text ) {
-		return (text || "").replace( /^\s+|\s+$/g, "" );
-	},
-
-	makeArray: function( array ) {
-		var ret = [];
-
-		if( array != null ){
-			var i = array.length;
-			// The window, strings (and functions) also have 'length'
-			if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
-				ret[0] = array;
-			else
-				while( i )
-					ret[--i] = array[i];
-		}
-
-		return ret;
-	},
-
-	inArray: function( elem, array ) {
-		for ( var i = 0, length = array.length; i < length; i++ )
-		// Use === because on IE, window == document
-			if ( array[ i ] === elem )
-				return i;
-
-		return -1;
-	},
-
-	merge: function( first, second ) {
-		// We have to loop this way because IE & Opera overwrite the length
-		// expando of getElementsByTagName
-		var i = 0, elem, pos = first.length;
-		// Also, we need to make sure that the correct elements are being returned
-		// (IE returns comment nodes in a '*' query)
-		if ( !jQuery.support.getAll ) {
-			while ( (elem = second[ i++ ]) != null )
-				if ( elem.nodeType != 8 )
-					first[ pos++ ] = elem;
-
-		} else
-			while ( (elem = second[ i++ ]) != null )
-				first[ pos++ ] = elem;
-
-		return first;
-	},
-
-	unique: function( array ) {
-		var ret = [], done = {};
-
-		try {
-
-			for ( var i = 0, length = array.length; i < length; i++ ) {
-				var id = jQuery.data( array[ i ] );
-
-				if ( !done[ id ] ) {
-					done[ id ] = true;
-					ret.push( array[ i ] );
-				}
-			}
-
-		} catch( e ) {
-			ret = array;
-		}
-
-		return ret;
-	},
-
-	grep: function( elems, callback, inv ) {
-		var ret = [];
-
-		// Go through the array, only saving the items
-		// that pass the validator function
-		for ( var i = 0, length = elems.length; i < length; i++ )
-			if ( !inv != !callback( elems[ i ], i ) )
-				ret.push( elems[ i ] );
-
-		return ret;
-	},
-
-	map: function( elems, callback ) {
-		var ret = [];
-
-		// Go through the array, translating each of the items to their
-		// new value (or values).
-		for ( var i = 0, length = elems.length; i < length; i++ ) {
-			var value = callback( elems[ i ], i );
-
-			if ( value != null )
-				ret[ ret.length ] = value;
-		}
-
-		return ret.concat.apply( [], ret );
-	}
-});
-
-// Use of jQuery.browser is deprecated.
-// It's included for backwards compatibility and plugins,
-// although they should work to migrate away.
-
-var userAgent = navigator.userAgent.toLowerCase();
-
-// Figure out what browser is being used
-jQuery.browser = {
-	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
-	safari: /webkit/.test( userAgent ),
-	opera: /opera/.test( userAgent ),
-	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
-	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
-};
-
-jQuery.each({
-	parent: function(elem){return elem.parentNode;},
-	parents: function(elem){return jQuery.dir(elem,"parentNode");},
-	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
-	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
-	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
-	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
-	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
-	children: function(elem){return jQuery.sibling(elem.firstChild);},
-	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
-}, function(name, fn){
-	jQuery.fn[ name ] = function( selector ) {
-		var ret = jQuery.map( this, fn );
-
-		if ( selector && typeof selector == "string" )
-			ret = jQuery.multiFilter( selector, ret );
-
-		return this.pushStack( jQuery.unique( ret ), name, selector );
-	};
-});
-
-jQuery.each({
-	appendTo: "append",
-	prependTo: "prepend",
-	insertBefore: "before",
-	insertAfter: "after",
-	replaceAll: "replaceWith"
-}, function(name, original){
-	jQuery.fn[ name ] = function( selector ) {
-		var ret = [], insert = jQuery( selector );
-
-		for ( var i = 0, l = insert.length; i < l; i++ ) {
-			var elems = (i > 0 ? this.clone(true) : this).get();
-			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
-			ret = ret.concat( elems );
-		}
-
-		return this.pushStack( ret, name, selector );
-	};
-});
-
-jQuery.each({
-	removeAttr: function( name ) {
-		jQuery.attr( this, name, "" );
-		if (this.nodeType == 1)
-			this.removeAttribute( name );
-	},
-
-	addClass: function( classNames ) {
-		jQuery.className.add( this, classNames );
-	},
-
-	removeClass: function( classNames ) {
-		jQuery.className.remove( this, classNames );
-	},
-
-	toggleClass: function( classNames, state ) {
-		if( typeof state !== "boolean" )
-			state = !jQuery.className.has( this, classNames );
-		jQuery.className[ state ? "add" : "remove" ]( this, classNames );
-	},
-
-	remove: function( selector ) {
-		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
-			// Prevent memory leaks
-			jQuery( "*", this ).add([this]).each(function(){
-				jQuery.event.remove(this);
-				jQuery.removeData(this);
-			});
-			if (this.parentNode)
-				this.parentNode.removeChild( this );
-		}
-	},
-
-	empty: function() {
-		// Remove element nodes and prevent memory leaks
-		jQuery(this).children().remove();
-
-		// Remove any remaining nodes
-		while ( this.firstChild )
-			this.removeChild( this.firstChild );
-	}
-}, function(name, fn){
-	jQuery.fn[ name ] = function(){
-		return this.each( fn, arguments );
-	};
-});
-
-// Helper function used by the dimensions and offset modules
-function num(elem, prop) {
-	return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
-}
-var expando = "jQuery" + now(), uuid = 0, windowData = {};
-
-jQuery.extend({
-	cache: {},
-
-	data: function( elem, name, data ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// Compute a unique ID for the element
-		if ( !id )
-			id = elem[ expando ] = ++uuid;
-
-		// Only generate the data cache if we're
-		// trying to access or manipulate it
-		if ( name && !jQuery.cache[ id ] )
-			jQuery.cache[ id ] = {};
-
-		// Prevent overriding the named cache with undefined values
-		if ( data !== undefined )
-			jQuery.cache[ id ][ name ] = data;
-
-		// Return the named cache data, or the ID for the element
-		return name ?
-			jQuery.cache[ id ][ name ] :
-			id;
-	},
-
-	removeData: function( elem, name ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// If we want to remove a specific section of the element's data
-		if ( name ) {
-			if ( jQuery.cache[ id ] ) {
-				// Remove the section of cache data
-				delete jQuery.cache[ id ][ name ];
-
-				// If we've removed all the data, remove the element's cache
-				name = "";
-
-				for ( name in jQuery.cache[ id ] )
-					break;
-
-				if ( !name )
-					jQuery.removeData( elem );
-			}
-
-		// Otherwise, we want to remove all of the element's data
-		} else {
-			// Clean up the element expando
-			try {
-				delete elem[ expando ];
-			} catch(e){
-				// IE has trouble directly removing the expando
-				// but it's ok with using removeAttribute
-				if ( elem.removeAttribute )
-					elem.removeAttribute( expando );
-			}
-
-			// Completely remove the data cache
-			delete jQuery.cache[ id ];
-		}
-	},
-	queue: function( elem, type, data ) {
-		if ( elem ){
-	
-			type = (type || "fx") + "queue";
-	
-			var q = jQuery.data( elem, type );
-	
-			if ( !q || jQuery.isArray(data) )
-				q = jQuery.data( elem, type, jQuery.makeArray(data) );
-			else if( data )
-				q.push( data );
-	
-		}
-		return q;
-	},
-
-	dequeue: function( elem, type ){
-		var queue = jQuery.queue( elem, type ),
-			fn = queue.shift();
-		
-		if( !type || type === "fx" )
-			fn = queue[0];
-			
-		if( fn !== undefined )
-			fn.call(elem);
-	}
-});
-
-jQuery.fn.extend({
-	data: function( key, value ){
-		var parts = key.split(".");
-		parts[1] = parts[1] ? "." + parts[1] : "";
-
-		if ( value === undefined ) {
-			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-
-			if ( data === undefined && this.length )
-				data = jQuery.data( this[0], key );
-
-			return data === undefined && parts[1] ?
-				this.data( parts[0] ) :
-				data;
-		} else
-			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
-				jQuery.data( this, key, value );
-			});
-	},
-
-	removeData: function( key ){
-		return this.each(function(){
-			jQuery.removeData( this, key );
-		});
-	},
-	queue: function(type, data){
-		if ( typeof type !== "string" ) {
-			data = type;
-			type = "fx";
-		}
-
-		if ( data === undefined )
-			return jQuery.queue( this[0], type );
-
-		return this.each(function(){
-			var queue = jQuery.queue( this, type, data );
-			
-			 if( type == "fx" && queue.length == 1 )
-				queue[0].call(this);
-		});
-	},
-	dequeue: function(type){
-		return this.each(function(){
-			jQuery.dequeue( this, type );
-		});
-	}
-});/*!
- * Sizzle CSS Selector Engine - v0.9.3
- *  Copyright 2009, The Dojo Foundation
- *  Released under the MIT, BSD, and GPL Licenses.
- *  More information: http://sizzlejs.com/
- */
-(function(){
-
-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
-	done = 0,
-	toString = Object.prototype.toString;
-
-var Sizzle = function(selector, context, results, seed) {
-	results = results || [];
-	context = context || document;
-
-	if ( context.nodeType !== 1 && context.nodeType !== 9 )
-		return [];
-	
-	if ( !selector || typeof selector !== "string" ) {
-		return results;
-	}
-
-	var parts = [], m, set, checkSet, check, mode, extra, prune = true;
-	
-	// Reset the position of the chunker regexp (start from head)
-	chunker.lastIndex = 0;
-	
-	while ( (m = chunker.exec(selector)) !== null ) {
-		parts.push( m[1] );
-		
-		if ( m[2] ) {
-			extra = RegExp.rightContext;
-			break;
-		}
-	}
-
-	if ( parts.length > 1 && origPOS.exec( selector ) ) {
-		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
-			set = posProcess( parts[0] + parts[1], context );
-		} else {
-			set = Expr.relative[ parts[0] ] ?
-				[ context ] :
-				Sizzle( parts.shift(), context );
-
-			while ( parts.length ) {
-				selector = parts.shift();
-
-				if ( Expr.relative[ selector ] )
-					selector += parts.shift();
-
-				set = posProcess( selector, set );
-			}
-		}
-	} else {
-		var ret = seed ?
-			{ expr: parts.pop(), set: makeArray(seed) } :
-			Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
-		set = Sizzle.filter( ret.expr, ret.set );
-
-		if ( parts.length > 0 ) {
-			checkSet = makeArray(set);
-		} else {
-			prune = false;
-		}
-
-		while ( parts.length ) {
-			var cur = parts.pop(), pop = cur;
-
-			if ( !Expr.relative[ cur ] ) {
-				cur = "";
-			} else {
-				pop = parts.pop();
-			}
-
-			if ( pop == null ) {
-				pop = context;
-			}
-
-			Expr.relative[ cur ]( checkSet, pop, isXML(context) );
-		}
-	}
-
-	if ( !checkSet ) {
-		checkSet = set;
-	}
-
-	if ( !checkSet ) {
-		throw "Syntax error, unrecognized expression: " + (cur || selector);
-	}
-
-	if ( toString.call(checkSet) === "[object Array]" ) {
-		if ( !prune ) {
-			results.push.apply( results, checkSet );
-		} else if ( context.nodeType === 1 ) {
-			for ( var i = 0; checkSet[i] != null; i++ ) {
-				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
-					results.push( set[i] );
-				}
-			}
-		} else {
-			for ( var i = 0; checkSet[i] != null; i++ ) {
-				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
-					results.push( set[i] );
-				}
-			}
-		}
-	} else {
-		makeArray( checkSet, results );
-	}
-
-	if ( extra ) {
-		Sizzle( extra, context, results, seed );
-
-		if ( sortOrder ) {
-			hasDuplicate = false;
-			results.sort(sortOrder);
-
-			if ( hasDuplicate ) {
-				for ( var i = 1; i < results.length; i++ ) {
-					if ( results[i] === results[i-1] ) {
-						results.splice(i--, 1);
-					}
-				}
-			}
-		}
-	}
-
-	return results;
-};
-
-Sizzle.matches = function(expr, set){
-	return Sizzle(expr, null, null, set);
-};
-
-Sizzle.find = function(expr, context, isXML){
-	var set, match;
-
-	if ( !expr ) {
-		return [];
-	}
-
-	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
-		var type = Expr.order[i], match;
-		
-		if ( (match = Expr.match[ type ].exec( expr )) ) {
-			var left = RegExp.leftContext;
-
-			if ( left.substr( left.length - 1 ) !== "\\" ) {
-				match[1] = (match[1] || "").replace(/\\/g, "");
-				set = Expr.find[ type ]( match, context, isXML );
-				if ( set != null ) {
-					expr = expr.replace( Expr.match[ type ], "" );
-					break;
-				}
-			}
-		}
-	}
-
-	if ( !set ) {
-		set = context.getElementsByTagName("*");
-	}
-
-	return {set: set, expr: expr};
-};
-
-Sizzle.filter = function(expr, set, inplace, not){
-	var old = expr, result = [], curLoop = set, match, anyFound,
-		isXMLFilter = set && set[0] && isXML(set[0]);
-
-	while ( expr && set.length ) {
-		for ( var type in Expr.filter ) {
-			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
-				var filter = Expr.filter[ type ], found, item;
-				anyFound = false;
-
-				if ( curLoop == result ) {
-					result = [];
-				}
-
-				if ( Expr.preFilter[ type ] ) {
-					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
-
-					if ( !match ) {
-						anyFound = found = true;
-					} else if ( match === true ) {
-						continue;
-					}
-				}
-
-				if ( match ) {
-					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
-						if ( item ) {
-							found = filter( item, match, i, curLoop );
-							var pass = not ^ !!found;
-
-							if ( inplace && found != null ) {
-								if ( pass ) {
-									anyFound = true;
-								} else {
-									curLoop[i] = false;
-								}
-							} else if ( pass ) {
-								result.push( item );
-								anyFound = true;
-							}
-						}
-					}
-				}
-
-				if ( found !== undefined ) {
-					if ( !inplace ) {
-						curLoop = result;
-					}
-
-					expr = expr.replace( Expr.match[ type ], "" );
-
-					if ( !anyFound ) {
-						return [];
-					}
-
-					break;
-				}
-			}
-		}
-
-		// Improper expression
-		if ( expr == old ) {
-			if ( anyFound == null ) {
-				throw "Syntax error, unrecognized expression: " + expr;
-			} else {
-				break;
-			}
-		}
-
-		old = expr;
-	}
-
-	return curLoop;
-};
-
-var Expr = Sizzle.selectors = {
-	order: [ "ID", "NAME", "TAG" ],
-	match: {
-		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
-		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
-		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
-		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
-		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
-		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
-		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
-		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
-	},
-	attrMap: {
-		"class": "className",
-		"for": "htmlFor"
-	},
-	attrHandle: {
-		href: function(elem){
-			return elem.getAttribute("href");
-		}
-	},
-	relative: {
-		"+": function(checkSet, part, isXML){
-			var isPartStr = typeof part === "string",
-				isTag = isPartStr && !/\W/.test(part),
-				isPartStrNotTag = isPartStr && !isTag;
-
-			if ( isTag && !isXML ) {
-				part = part.toUpperCase();
-			}
-
-			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
-				if ( (elem = checkSet[i]) ) {
-					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
-
-					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
-						elem || false :
-						elem === part;
-				}
-			}
-
-			if ( isPartStrNotTag ) {
-				Sizzle.filter( part, checkSet, true );
-			}
-		},
-		">": function(checkSet, part, isXML){
-			var isPartStr = typeof part === "string";
-
-			if ( isPartStr && !/\W/.test(part) ) {
-				part = isXML ? part : part.toUpperCase();
-
-				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
-					var elem = checkSet[i];
-					if ( elem ) {
-						var parent = elem.parentNode;
-						checkSet[i] = parent.nodeName === part ? parent : false;
-					}
-				}
-			} else {
-				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
-					var elem = checkSet[i];
-					if ( elem ) {
-						checkSet[i] = isPartStr ?
-							elem.parentNode :
-							elem.parentNode === part;
-					}
-				}
-
-				if ( isPartStr ) {
-					Sizzle.filter( part, checkSet, true );
-				}
-			}
-		},
-		"": function(checkSet, part, isXML){
-			var doneName = done++, checkFn = dirCheck;
-
-			if ( !part.match(/\W/) ) {
-				var nodeCheck = part = isXML ? part : part.toUpperCase();
-				checkFn = dirNodeCheck;
-			}
-
-			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
-		},
-		"~": function(checkSet, part, isXML){
-			var doneName = done++, checkFn = dirCheck;
-
-			if ( typeof part === "string" && !part.match(/\W/) ) {
-				var nodeCheck = part = isXML ? part : part.toUpperCase();
-				checkFn = dirNodeCheck;
-			}
-
-			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
-		}
-	},
-	find: {
-		ID: function(match, context, isXML){
-			if ( typeof context.getElementById !== "undefined" && !isXML ) {
-				var m = context.getElementById(match[1]);
-				return m ? [m] : [];
-			}
-		},
-		NAME: function(match, context, isXML){
-			if ( typeof context.getElementsByName !== "undefined" ) {
-				var ret = [], results = context.getElementsByName(match[1]);
-
-				for ( var i = 0, l = results.length; i < l; i++ ) {
-					if ( results[i].getAttribute("name") === match[1] ) {
-						ret.push( results[i] );
-					}
-				}
-
-				return ret.length === 0 ? null : ret;
-			}
-		},
-		TAG: function(match, context){
-			return context.getElementsByTagName(match[1]);
-		}
-	},
-	preFilter: {
-		CLASS: function(match, curLoop, inplace, result, not, isXML){
-			match = " " + match[1].replace(/\\/g, "") + " ";
-
-			if ( isXML ) {
-				return match;
-			}
-
-			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
-				if ( elem ) {
-					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
-						if ( !inplace )
-							result.push( elem );
-					} else if ( inplace ) {
-						curLoop[i] = false;
-					}
-				}
-			}
-
-			return false;
-		},
-		ID: function(match){
-			return match[1].replace(/\\/g, "");
-		},
-		TAG: function(match, curLoop){
-			for ( var i = 0; curLoop[i] === false; i++ ){}
-			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
-		},
-		CHILD: function(match){
-			if ( match[1] == "nth" ) {
-				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
-				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
-					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
-					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
-
-				// calculate the numbers (first)n+(last) including if they are negative
-				match[2] = (test[1] + (test[2] || 1)) - 0;
-				match[3] = test[3] - 0;
-			}
-
-			// TODO: Move to normal caching system
-			match[0] = done++;
-
-			return match;
-		},
-		ATTR: function(match, curLoop, inplace, result, not, isXML){
-			var name = match[1].replace(/\\/g, "");
-			
-			if ( !isXML && Expr.attrMap[name] ) {
-				match[1] = Expr.attrMap[name];
-			}
-
-			if ( match[2] === "~=" ) {
-				match[4] = " " + match[4] + " ";
-			}
-
-			return match;
-		},
-		PSEUDO: function(match, curLoop, inplace, result, not){
-			if ( match[1] === "not" ) {
-				// If we're dealing with a complex expression, or a simple one
-				if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
-					match[3] = Sizzle(match[3], null, null, curLoop);
-				} else {
-					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
-					if ( !inplace ) {
-						result.push.apply( result, ret );
-					}
-					return false;
-				}
-			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
-				return true;
-			}
-			
-			return match;
-		},
-		POS: function(match){
-			match.unshift( true );
-			return match;
-		}
-	},
-	filters: {
-		enabled: function(elem){
-			return elem.disabled === false && elem.type !== "hidden";
-		},
-		disabled: function(elem){
-			return elem.disabled === true;
-		},
-		checked: function(elem){
-			return elem.checked === true;
-		},
-		selected: function(elem){
-			// Accessing this property makes selected-by-default
-			// options in Safari work properly
-			elem.parentNode.selectedIndex;
-			return elem.selected === true;
-		},
-		parent: function(elem){
-			return !!elem.firstChild;
-		},
-		empty: function(elem){
-			return !elem.firstChild;
-		},
-		has: function(elem, i, match){
-			return !!Sizzle( match[3], elem ).length;
-		},
-		header: function(elem){
-			return /h\d/i.test( elem.nodeName );
-		},
-		text: function(elem){
-			return "text" === elem.type;
-		},
-		radio: function(elem){
-			return "radio" === elem.type;
-		},
-		checkbox: function(elem){
-			return "checkbox" === elem.type;
-		},
-		file: function(elem){
-			return "file" === elem.type;
-		},
-		password: function(elem){
-			return "password" === elem.type;
-		},
-		submit: function(elem){
-			return "submit" === elem.type;
-		},
-		image: function(elem){
-			return "image" === elem.type;
-		},
-		reset: function(elem){
-			return "reset" === elem.type;
-		},
-		button: function(elem){
-			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
-		},
-		input: function(elem){
-			return /input|select|textarea|button/i.test(elem.nodeName);
-		}
-	},
-	setFilters: {
-		first: function(elem, i){
-			return i === 0;
-		},
-		last: function(elem, i, match, array){
-			return i === array.length - 1;
-		},
-		even: function(elem, i){
-			return i % 2 === 0;
-		},
-		odd: function(elem, i){
-			return i % 2 === 1;
-		},
-		lt: function(elem, i, match){
-			return i < match[3] - 0;
-		},
-		gt: function(elem, i, match){
-			return i > match[3] - 0;
-		},
-		nth: function(elem, i, match){
-			return match[3] - 0 == i;
-		},
-		eq: function(elem, i, match){
-			return match[3] - 0 == i;
-		}
-	},
-	filter: {
-		PSEUDO: function(elem, match, i, array){
-			var name = match[1], filter = Expr.filters[ name ];
-
-			if ( filter ) {
-				return filter( elem, i, match, array );
-			} else if ( name === "contains" ) {
-				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
-			} else if ( name === "not" ) {
-				var not = match[3];
-
-				for ( var i = 0, l = not.length; i < l; i++ ) {
-					if ( not[i] === elem ) {
-						return false;
-					}
-				}
-
-				return true;
-			}
-		},
-		CHILD: function(elem, match){
-			var type = match[1], node = elem;
-			switch (type) {
-				case 'only':
-				case 'first':
-					while (node = node.previousSibling)  {
-						if ( node.nodeType === 1 ) return false;
-					}
-					if ( type == 'first') return true;
-					node = elem;
-				case 'last':
-					while (node = node.nextSibling)  {
-						if ( node.nodeType === 1 ) return false;
-					}
-					return true;
-				case 'nth':
-					var first = match[2], last = match[3];
-
-					if ( first == 1 && last == 0 ) {
-						return true;
-					}
-					
-					var doneName = match[0],
-						parent = elem.parentNode;
-	
-					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
-						var count = 0;
-						for ( node = parent.firstChild; node; node = node.nextSibling ) {
-							if ( node.nodeType === 1 ) {
-								node.nodeIndex = ++count;
-							}
-						} 
-						parent.sizcache = doneName;
-					}
-					
-					var diff = elem.nodeIndex - last;
-					if ( first == 0 ) {
-						return diff == 0;
-					} else {
-						return ( diff % first == 0 && diff / first >= 0 );
-					}
-			}
-		},
-		ID: function(elem, match){
-			return elem.nodeType === 1 && elem.getAttribute("id") === match;
-		},
-		TAG: function(elem, match){
-			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
-		},
-		CLASS: function(elem, match){
-			return (" " + (elem.className || elem.getAttribute("class")) + " ")
-				.indexOf( match ) > -1;
-		},
-		ATTR: function(elem, match){
-			var name = match[1],
-				result = Expr.attrHandle[ name ] ?
-					Expr.attrHandle[ name ]( elem ) :
-					elem[ name ] != null ?
-						elem[ name ] :
-						elem.getAttribute( name ),
-				value = result + "",
-				type = match[2],
-				check = match[4];
-
-			return result == null ?
-				type === "!=" :
-				type === "=" ?
-				value === check :
-				type === "*=" ?
-				value.indexOf(check) >= 0 :
-				type === "~=" ?
-				(" " + value + " ").indexOf(check) >= 0 :
-				!check ?
-				value && result !== false :
-				type === "!=" ?
-				value != check :
-				type === "^=" ?
-				value.indexOf(check) === 0 :
-				type === "$=" ?
-				value.substr(value.length - check.length) === check :
-				type === "|=" ?
-				value === check || value.substr(0, check.length + 1) === check + "-" :
-				false;
-		},
-		POS: function(elem, match, i, array){
-			var name = match[2], filter = Expr.setFilters[ name ];
-
-			if ( filter ) {
-				return filter( elem, i, match, array );
-			}
-		}
-	}
-};
-
-var origPOS = Expr.match.POS;
-
-for ( var type in Expr.match ) {
-	Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
-}
-
-var makeArray = function(array, results) {
-	array = Array.prototype.slice.call( array );
-
-	if ( results ) {
-		results.push.apply( results, array );
-		return results;
-	}
-	
-	return array;
-};
-
-// Perform a simple check to determine if the browser is capable of
-// converting a NodeList to an array using builtin methods.
-try {
-	Array.prototype.slice.call( document.documentElement.childNodes );
-
-// Provide a fallback method if it does not work
-} catch(e){
-	makeArray = function(array, results) {
-		var ret = results || [];
-
-		if ( toString.call(array) === "[object Array]" ) {
-			Array.prototype.push.apply( ret, array );
-		} else {
-			if ( typeof array.length === "number" ) {
-				for ( var i = 0, l = array.length; i < l; i++ ) {
-					ret.push( array[i] );
-				}
-			} else {
-				for ( var i = 0; array[i]; i++ ) {
-					ret.push( array[i] );
-				}
-			}
-		}
-
-		return ret;
-	};
-}
-
-var sortOrder;
-
-if ( document.documentElement.compareDocumentPosition ) {
-	sortOrder = function( a, b ) {
-		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
-		if ( ret === 0 ) {
-			hasDuplicate = true;
-		}
-		return ret;
-	};
-} else if ( "sourceIndex" in document.documentElement ) {
-	sortOrder = function( a, b ) {
-		var ret = a.sourceIndex - b.sourceIndex;
-		if ( ret === 0 ) {
-			hasDuplicate = true;
-		}
-		return ret;
-	};
-} else if ( document.createRange ) {
-	sortOrder = function( a, b ) {
-		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
-		aRange.selectNode(a);
-		aRange.collapse(true);
-		bRange.selectNode(b);
-		bRange.collapse(true);
-		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
-		if ( ret === 0 ) {
-			hasDuplicate = true;
-		}
-		return ret;
-	};
-}
-
-// Check to see if the browser returns elements by name when
-// querying by getElementById (and provide a workaround)
-(function(){
-	// We're going to inject a fake input element with a specified name
-	var form = document.createElement("form"),
-		id = "script" + (new Date).getTime();
-	form.innerHTML = "<input name='" + id + "'/>";
-
-	// Inject it into the root element, check its status, and remove it quickly
-	var root = document.documentElement;
-	root.insertBefore( form, root.firstChild );
-
-	// The workaround has to do additional checks after a getElementById
-	// Which slows things down for other browsers (hence the branching)
-	if ( !!document.getElementById( id ) ) {
-		Expr.find.ID = function(match, context, isXML){
-			if ( typeof context.getElementById !== "undefined" && !isXML ) {
-				var m = context.getElementById(match[1]);
-				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
-			}
-		};
-
-		Expr.filter.ID = function(elem, match){
-			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
-			return elem.nodeType === 1 && node && node.nodeValue === match;
-		};
-	}
-
-	root.removeChild( form );
-})();
-
-(function(){
-	// Check to see if the browser returns only elements
-	// when doing getElementsByTagName("*")
-
-	// Create a fake element
-	var div = document.createElement("div");
-	div.appendChild( document.createComment("") );
-
-	// Make sure no comments are found
-	if ( div.getElementsByTagName("*").length > 0 ) {
-		Expr.find.TAG = function(match, context){
-			var results = context.getElementsByTagName(match[1]);
-
-			// Filter out possible comments
-			if ( match[1] === "*" ) {
-				var tmp = [];
-
-				for ( var i = 0; results[i]; i++ ) {
-					if ( results[i].nodeType === 1 ) {
-						tmp.push( results[i] );
-					}
-				}
-
-				results = tmp;
-			}
-
-			return results;
-		};
-	}
-
-	// Check to see if an attribute returns normalized href attributes
-	div.innerHTML = "<a href='#'></a>";
-	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
-			div.firstChild.getAttribute("href") !== "#" ) {
-		Expr.attrHandle.href = function(elem){
-			return elem.getAttribute("href", 2);
-		};
-	}
-})();
-
-if ( document.querySelectorAll ) (function(){
-	var oldSizzle = Sizzle, div = document.createElement("div");
-	div.innerHTML = "<p class='TEST'></p>";
-
-	// Safari can't handle uppercase or unicode characters when
-	// in quirks mode.
-	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
-		return;
-	}
-	
-	Sizzle = function(query, context, extra, seed){
-		context = context || document;
-
-		// Only use querySelectorAll on non-XML documents
-		// (ID selectors don't work in non-HTML documents)
-		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
-			try {
-				return makeArray( context.querySelectorAll(query), extra );
-			} catch(e){}
-		}
-		
-		return oldSizzle(query, context, extra, seed);
-	};
-
-	Sizzle.find = oldSizzle.find;
-	Sizzle.filter = oldSizzle.filter;
-	Sizzle.selectors = oldSizzle.selectors;
-	Sizzle.matches = oldSizzle.matches;
-})();
-
-if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
-	var div = document.createElement("div");
-	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
-
-	// Opera can't find a second classname (in 9.6)
-	if ( div.getElementsByClassName("e").length === 0 )
-		return;
-
-	// Safari caches class attributes, doesn't catch changes (in 3.2)
-	div.lastChild.className = "e";
-
-	if ( div.getElementsByClassName("e").length === 1 )
-		return;
-
-	Expr.order.splice(1, 0, "CLASS");
-	Expr.find.CLASS = function(match, context, isXML) {
-		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
-			return context.getElementsByClassName(match[1]);
-		}
-	};
-})();
-
-function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
-	var sibDir = dir == "previousSibling" && !isXML;
-	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
-		var elem = checkSet[i];
-		if ( elem ) {
-			if ( sibDir && elem.nodeType === 1 ){
-				elem.sizcache = doneName;
-				elem.sizset = i;
-			}
-			elem = elem[dir];
-			var match = false;
-
-			while ( elem ) {
-				if ( elem.sizcache === doneName ) {
-					match = checkSet[elem.sizset];
-					break;
-				}
-
-				if ( elem.nodeType === 1 && !isXML ){
-					elem.sizcache = doneName;
-					elem.sizset = i;
-				}
-
-				if ( elem.nodeName === cur ) {
-					match = elem;
-					break;
-				}
-
-				elem = elem[dir];
-			}
-
-			checkSet[i] = match;
-		}
-	}
-}
-
-function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
-	var sibDir = dir == "previousSibling" && !isXML;
-	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
-		var elem = checkSet[i];
-		if ( elem ) {
-			if ( sibDir && elem.nodeType === 1 ) {
-				elem.sizcache = doneName;
-				elem.sizset = i;
-			}
-			elem = elem[dir];
-			var match = false;
-
-			while ( elem ) {
-				if ( elem.sizcache === doneName ) {
-					match = checkSet[elem.sizset];
-					break;
-				}
-
-				if ( elem.nodeType === 1 ) {
-					if ( !isXML ) {
-						elem.sizcache = doneName;
-						elem.sizset = i;
-					}
-					if ( typeof cur !== "string" ) {
-						if ( elem === cur ) {
-							match = true;
-							break;
-						}
-
-					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
-						match = elem;
-						break;
-					}
-				}
-
-				elem = elem[dir];
-			}
-
-			checkSet[i] = match;
-		}
-	}
-}
-
-var contains = document.compareDocumentPosition ?  function(a, b){
-	return a.compareDocumentPosition(b) & 16;
-} : function(a, b){
-	return a !== b && (a.contains ? a.contains(b) : true);
-};
-
-var isXML = function(elem){
-	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
-		!!elem.ownerDocument && isXML( elem.ownerDocument );
-};
-
-var posProcess = function(selector, context){
-	var tmpSet = [], later = "", match,
-		root = context.nodeType ? [context] : context;
-
-	// Position selectors must be done after the filter
-	// And so must :not(positional) so we move all PSEUDOs to the end
-	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
-		later += match[0];
-		selector = selector.replace( Expr.match.PSEUDO, "" );
-	}
-
-	selector = Expr.relative[selector] ? selector + "*" : selector;
-
-	for ( var i = 0, l = root.length; i < l; i++ ) {
-		Sizzle( selector, root[i], tmpSet );
-	}
-
-	return Sizzle.filter( later, tmpSet );
-};
-
-// EXPOSE
-jQuery.find = Sizzle;
-jQuery.filter = Sizzle.filter;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.filters;
-
-Sizzle.selectors.filters.hidden = function(elem){
-	return elem.offsetWidth === 0 || elem.offsetHeight === 0;
-};
-
-Sizzle.selectors.filters.visible = function(elem){
-	return elem.offsetWidth > 0 || elem.offsetHeight > 0;
-};
-
-Sizzle.selectors.filters.animated = function(elem){
-	return jQuery.grep(jQuery.timers, function(fn){
-		return elem === fn.elem;
-	}).length;
-};
-
-jQuery.multiFilter = function( expr, elems, not ) {
-	if ( not ) {
-		expr = ":not(" + expr + ")";
-	}
-
-	return Sizzle.matches(expr, elems);
-};
-
-jQuery.dir = function( elem, dir ){
-	var matched = [], cur = elem[dir];
-	while ( cur && cur != document ) {
-		if ( cur.nodeType == 1 )
-			matched.push( cur );
-		cur = cur[dir];
-	}
-	return matched;
-};
-
-jQuery.nth = function(cur, result, dir, elem){
-	result = result || 1;
-	var num = 0;
-
-	for ( ; cur; cur = cur[dir] )
-		if ( cur.nodeType == 1 && ++num == result )
-			break;
-
-	return cur;
-};
-
-jQuery.sibling = function(n, elem){
-	var r = [];
-
-	for ( ; n; n = n.nextSibling ) {
-		if ( n.nodeType == 1 && n != elem )
-			r.push( n );
-	}
-
-	return r;
-};
-
-return;
-
-window.Sizzle = Sizzle;
-
-})();
-/*
- * A number of helper functions used for managing events.
- * Many of the ideas behind this code originated from
- * Dean Edwards' addEvent library.
- */
-jQuery.event = {
-
-	// Bind an event to an element
-	// Original by Dean Edwards
-	add: function(elem, types, handler, data) {
-		if ( elem.nodeType == 3 || elem.nodeType == 8 )
-			return;
-
-		// For whatever reason, IE has trouble passing the window object
-		// around, causing it to be cloned in the process
-		if ( elem.setInterval && elem != window )
-			elem = window;
-
-		// Make sure that the function being executed has a unique ID
-		if ( !handler.guid )
-			handler.guid = this.guid++;
-
-		// if data is passed, bind to handler
-		if ( data !== undefined ) {
-			// Create temporary function pointer to original handler
-			var fn = handler;
-
-			// Create unique handler function, wrapped around original handler
-			handler = this.proxy( fn );
-
-			// Store data in unique handler
-			handler.data = data;
-		}
-
-		// Init the element's event structure
-		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
-			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
-				// Handle the second event of a trigger and when
-				// an event is called after a page has unloaded
-				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
-					jQuery.event.handle.apply(arguments.callee.elem, arguments) :
-					undefined;
-			});
-		// Add elem as a property of the handle function
-		// This is to prevent a memory leak with non-native
-		// event in IE.
-		handle.elem = elem;
-
-		// Handle multiple events separated by a space
-		// jQuery(...).bind("mouseover mouseout", fn);
-		jQuery.each(types.split(/\s+/), function(index, type) {
-			// Namespaced event handlers
-			var namespaces = type.split(".");
-			type = namespaces.shift();
-			handler.type = namespaces.slice().sort().join(".");
-
-			// Get the current list of functions bound to this event
-			var handlers = events[type];
-			
-			if ( jQuery.event.specialAll[type] )
-				jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
-
-			// Init the event handler queue
-			if (!handlers) {
-				handlers = events[type] = {};
-
-				// Check for a special event handler
-				// Only use addEventListener/attachEvent if the special
-				// events handler returns false
-				if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
-					// Bind the global event handler to the element
-					if (elem.addEventListener)
-						elem.addEventListener(type, handle, false);
-					else if (elem.attachEvent)
-						elem.attachEvent("on" + type, handle);
-				}
-			}
-
-			// Add the function to the element's handler list
-			handlers[handler.guid] = handler;
-
-			// Keep track of which events have been used, for global triggering
-			jQuery.event.global[type] = true;
-		});
-
-		// Nullify elem to prevent memory leaks in IE
-		elem = null;
-	},
-
-	guid: 1,
-	global: {},
-
-	// Detach an event or set of events from an element
-	remove: function(elem, types, handler) {
-		// don't do events on text and comment nodes
-		if ( elem.nodeType == 3 || elem.nodeType == 8 )
-			return;
-
-		var events = jQuery.data(elem, "events"), ret, index;
-
-		if ( events ) {
-			// Unbind all events for the element
-			if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
-				for ( var type in events )
-					this.remove( elem, type + (types || "") );
-			else {
-				// types is actually an event object here
-				if ( types.type ) {
-					handler = types.handler;
-					types = types.type;
-				}
-
-				// Handle multiple events seperated by a space
-				// jQuery(...).unbind("mouseover mouseout", fn);
-				jQuery.each(types.split(/\s+/), function(index, type){
-					// Namespaced event handlers
-					var namespaces = type.split(".");
-					type = namespaces.shift();
-					var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
-
-					if ( events[type] ) {
-						// remove the given handler for the given type
-						if ( handler )
-							delete events[type][handler.guid];
-
-						// remove all handlers for the given type
-						else
-							for ( var handle in events[type] )
-								// Handle the removal of namespaced events
-								if ( namespace.test(events[type][handle].type) )
-									delete events[type][handle];
-									
-						if ( jQuery.event.specialAll[type] )
-							jQuery.event.specialAll[type].teardown.call(elem, namespaces);
-
-						// remove generic event handler if no more handlers exist
-						for ( ret in events[type] ) break;
-						if ( !ret ) {
-							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
-								if (elem.removeEventListener)
-									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
-								else if (elem.detachEvent)
-									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
-							}
-							ret = null;
-							delete events[type];
-						}
-					}
-				});
-			}
-
-			// Remove the expando if it's no longer used
-			for ( ret in events ) break;
-			if ( !ret ) {
-				var handle = jQuery.data( elem, "handle" );
-				if ( handle ) handle.elem = null;
-				jQuery.removeData( elem, "events" );
-				jQuery.removeData( elem, "handle" );
-			}
-		}
-	},
-
-	// bubbling is internal
-	trigger: function( event, data, elem, bubbling ) {
-		// Event object or event type
-		var type = event.type || event;
-
-		if( !bubbling ){
-			event = typeof event === "object" ?
-				// jQuery.Event object
-				event[expando] ? event :
-				// Object literal
-				jQuery.extend( jQuery.Event(type), event ) :
-				// Just the event type (string)
-				jQuery.Event(type);
-
-			if ( type.indexOf("!") >= 0 ) {
-				event.type = type = type.slice(0, -1);
-				event.exclusive = true;
-			}
-
-			// Handle a global trigger
-			if ( !elem ) {
-				// Don't bubble custom events when global (to avoid too much overhead)
-				event.stopPropagation();
-				// Only trigger if we've ever bound an event for it
-				if ( this.global[type] )
-					jQuery.each( jQuery.cache, function(){
-						if ( this.events && this.events[type] )
-							jQuery.event.trigger( event, data, this.handle.elem );
-					});
-			}
-
-			// Handle triggering a single element
-
-			// don't do events on text and comment nodes
-			if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
-				return undefined;
-			
-			// Clean up in case it is reused
-			event.result = undefined;
-			event.target = elem;
-			
-			// Clone the incoming data, if any
-			data = jQuery.makeArray(data);
-			data.unshift( event );
-		}
-
-		event.currentTarget = elem;
-
-		// Trigger the event, it is assumed that "handle" is a function
-		var handle = jQuery.data(elem, "handle");
-		if ( handle )
-			handle.apply( elem, data );
-
-		// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
-		if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
-			event.result = false;
-
-		// Trigger the native events (except for clicks on links)
-		if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
-			this.triggered = true;
-			try {
-				elem[ type ]();
-			// prevent IE from throwing an error for some hidden elements
-			} catch (e) {}
-		}
-
-		this.triggered = false;
-
-		if ( !event.isPropagationStopped() ) {
-			var parent = elem.parentNode || elem.ownerDocument;
-			if ( parent )
-				jQuery.event.trigger(event, data, parent, true);
-		}
-	},
-
-	handle: function(event) {
-		// returned undefined or false
-		var all, handlers;
-
-		event = arguments[0] = jQuery.event.fix( event || window.event );
-		event.currentTarget = this;
-		
-		// Namespaced event handlers
-		var namespaces = event.type.split(".");
-		event.type = namespaces.shift();
-
-		// Cache this now, all = true means, any handler
-		all = !namespaces.length && !event.exclusive;
-		
-		var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
-
-		handlers = ( jQuery.data(this, "events") || {} )[event.type];
-
-		for ( var j in handlers ) {
-			var handler = handlers[j];
-
-			// Filter the functions by class
-			if ( all || namespace.test(handler.type) ) {
-				// Pass in a reference to the handler function itself
-				// So that we can later remove it
-				event.handler = handler;
-				event.data = handler.data;
-
-				var ret = handler.apply(this, arguments);
-
-				if( ret !== undefined ){
-					event.result = ret;
-					if ( ret === false ) {
-						event.preventDefault();
-						event.stopPropagation();
-					}
-				}
-
-				if( event.isImmediatePropagationStopped() )
-					break;
-
-			}
-		}
-	},
-
-	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
-
-	fix: function(event) {
-		if ( event[expando] )
-			return event;
-
-		// store a copy of the original event object
-		// and "clone" to set read-only properties
-		var originalEvent = event;
-		event = jQuery.Event( originalEvent );
-
-		for ( var i = this.props.length, prop; i; ){
-			prop = this.props[ --i ];
-			event[ prop ] = originalEvent[ prop ];
-		}
-
-		// Fix target property, if necessary
-		if ( !event.target )
-			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
-
-		// check if target is a textnode (safari)
-		if ( event.target.nodeType == 3 )
-			event.target = event.target.parentNode;
-
-		// Add relatedTarget, if necessary
-		if ( !event.relatedTarget && event.fromElement )
-			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
-
-		// Calculate pageX/Y if missing and clientX/Y available
-		if ( event.pageX == null && event.clientX != null ) {
-			var doc = document.documentElement, body = document.body;
-			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
-			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
-		}
-
-		// Add which for key events
-		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
-			event.which = event.charCode || event.keyCode;
-
-		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
-		if ( !event.metaKey && event.ctrlKey )
-			event.metaKey = event.ctrlKey;
-
-		// Add which for click: 1 == left; 2 == middle; 3 == right
-		// Note: button is not normalized, so don't use it
-		if ( !event.which && event.button )
-			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
-
-		return event;
-	},
-
-	proxy: function( fn, proxy ){
-		proxy = proxy || function(){ return fn.apply(this, arguments); };
-		// Set the guid of unique handler to the same of original handler, so it can be removed
-		proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
-		// So proxy can be declared as an argument
-		return proxy;
-	},
-
-	special: {
-		ready: {
-			// Make sure the ready event is setup
-			setup: bindReady,
-			teardown: function() {}
-		}
-	},
-	
-	specialAll: {
-		live: {
-			setup: function( selector, namespaces ){
-				jQuery.event.add( this, namespaces[0], liveHandler );
-			},
-			teardown:  function( namespaces ){
-				if ( namespaces.length ) {
-					var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
-					
-					jQuery.each( (jQuery.data(this, "events").live || {}), function(){
-						if ( name.test(this.type) )
-							remove++;
-					});
-					
-					if ( remove < 1 )
-						jQuery.event.remove( this, namespaces[0], liveHandler );
-				}
-			}
-		}
-	}
-};
-
-jQuery.Event = function( src ){
-	// Allow instantiation without the 'new' keyword
-	if( !this.preventDefault )
-		return new jQuery.Event(src);
-	
-	// Event object
-	if( src && src.type ){
-		this.originalEvent = src;
-		this.type = src.type;
-	// Event type
-	}else
-		this.type = src;
-
-	// timeStamp is buggy for some events on Firefox(#3843)
-	// So we won't rely on the native value
-	this.timeStamp = now();
-	
-	// Mark it as fixed
-	this[expando] = true;
-};
-
-function returnFalse(){
-	return false;
-}
-function returnTrue(){
-	return true;
-}
-
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
-	preventDefault: function() {
-		this.isDefaultPrevented = returnTrue;
-
-		var e = this.originalEvent;
-		if( !e )
-			return;
-		// if preventDefault exists run it on the original event
-		if (e.preventDefault)
-			e.preventDefault();
-		// otherwise set the returnValue property of the original event to false (IE)
-		e.returnValue = false;
-	},
-	stopPropagation: function() {
-		this.isPropagationStopped = returnTrue;
-
-		var e = this.originalEvent;
-		if( !e )
-			return;
-		// if stopPropagation exists run it on the original event
-		if (e.stopPropagation)
-			e.stopPropagation();
-		// otherwise set the cancelBubble property of the original event to true (IE)
-		e.cancelBubble = true;
-	},
-	stopImmediatePropagation:function(){
-		this.isImmediatePropagationStopped = returnTrue;
-		this.stopPropagation();
-	},
-	isDefaultPrevented: returnFalse,
-	isPropagationStopped: returnFalse,
-	isImmediatePropagationStopped: returnFalse
-};
-// Checks if an event happened on an element within another element
-// Used in jQuery.event.special.mouseenter and mouseleave handlers
-var withinElement = function(event) {
-	// Check if mouse(over|out) are still within the same parent element
-	var parent = event.relatedTarget;
-	// Traverse up the tree
-	while ( parent && parent != this )
-		try { parent = parent.parentNode; }
-		catch(e) { parent = this; }
-	
-	if( parent != this ){
-		// set the correct event type
-		event.type = event.data;
-		// handle event if we actually just moused on to a non sub-element
-		jQuery.event.handle.apply( this, arguments );
-	}
-};
-	
-jQuery.each({ 
-	mouseover: 'mouseenter', 
-	mouseout: 'mouseleave'
-}, function( orig, fix ){
-	jQuery.event.special[ fix ] = {
-		setup: function(){
-			jQuery.event.add( this, orig, withinElement, fix );
-		},
-		teardown: function(){
-			jQuery.event.remove( this, orig, withinElement );
-		}
-	};			   
-});
-
-jQuery.fn.extend({
-	bind: function( type, data, fn ) {
-		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
-			jQuery.event.add( this, type, fn || data, fn && data );
-		});
-	},
-
-	one: function( type, data, fn ) {
-		var one = jQuery.event.proxy( fn || data, function(event) {
-			jQuery(this).unbind(event, one);
-			return (fn || data).apply( this, arguments );
-		});
-		return this.each(function(){
-			jQuery.event.add( this, type, one, fn && data);
-		});
-	},
-
-	unbind: function( type, fn ) {
-		return this.each(function(){
-			jQuery.event.remove( this, type, fn );
-		});
-	},
-
-	trigger: function( type, data ) {
-		return this.each(function(){
-			jQuery.event.trigger( type, data, this );
-		});
-	},
-
-	triggerHandler: function( type, data ) {
-		if( this[0] ){
-			var event = jQuery.Event(type);
-			event.preventDefault();
-			event.stopPropagation();
-			jQuery.event.trigger( event, data, this[0] );
-			return event.result;
-		}		
-	},
-
-	toggle: function( fn ) {
-		// Save reference to arguments for access in closure
-		var args = arguments, i = 1;
-
-		// link all the functions, so any of them can unbind this click handler
-		while( i < args.length )
-			jQuery.event.proxy( fn, args[i++] );
-
-		return this.click( jQuery.event.proxy( fn, function(event) {
-			// Figure out which function to execute
-			this.lastToggle = ( this.lastToggle || 0 ) % i;
-
-			// Make sure that clicks stop
-			event.preventDefault();
-
-			// and execute the function
-			return args[ this.lastToggle++ ].apply( this, arguments ) || false;
-		}));
-	},
-
-	hover: function(fnOver, fnOut) {
-		return this.mouseenter(fnOver).mouseleave(fnOut);
-	},
-
-	ready: function(fn) {
-		// Attach the listeners
-		bindReady();
-
-		// If the DOM is already ready
-		if ( jQuery.isReady )
-			// Execute the function immediately
-			fn.call( document, jQuery );
-
-		// Otherwise, remember the function for later
-		else
-			// Add the function to the wait list
-			jQuery.readyList.push( fn );
-
-		return this;
-	},
-	
-	live: function( type, fn ){
-		var proxy = jQuery.event.proxy( fn );
-		proxy.guid += this.selector + type;
-
-		jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
-
-		return this;
-	},
-	
-	die: function( type, fn ){
-		jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
-		return this;
-	}
-});
-
-function liveHandler( event ){
-	var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
-		stop = true,
-		elems = [];
-
-	jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
-		if ( check.test(fn.type) ) {
-			var elem = jQuery(event.target).closest(fn.data)[0];
-			if ( elem )
-				elems.push({ elem: elem, fn: fn });
-		}
-	});
-
-	elems.sort(function(a,b) {
-		return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
-	});
-	
-	jQuery.each(elems, function(){
-		if ( this.fn.call(this.elem, event, this.fn.data) === false )
-			return (stop = false);
-	});
-
-	return stop;
-}
-
-function liveConvert(type, selector){
-	return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
-}
-
-jQuery.extend({
-	isReady: false,
-	readyList: [],
-	// Handle when the DOM is ready
-	ready: function() {
-		// Make sure that the DOM is not already loaded
-		if ( !jQuery.isReady ) {
-			// Remember that the DOM is ready
-			jQuery.isReady = true;
-
-			// If there are functions bound, to execute
-			if ( jQuery.readyList ) {
-				// Execute all of them
-				jQuery.each( jQuery.readyList, function(){
-					this.call( document, jQuery );
-				});
-
-				// Reset the list of functions
-				jQuery.readyList = null;
-			}
-
-			// Trigger any bound ready events
-			jQuery(document).triggerHandler("ready");
-		}
-	}
-});
-
-var readyBound = false;
-
-function bindReady(){
-	if ( readyBound ) return;
-	readyBound = true;
-
-	// Mozilla, Opera and webkit nightlies currently support this event
-	if ( document.addEventListener ) {
-		// Use the handy event callback
-		document.addEventListener( "DOMContentLoaded", function(){
-			document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
-			jQuery.ready();
-		}, false );
-
-	// If IE event model is used
-	} else if ( document.attachEvent ) {
-		// ensure firing before onload,
-		// maybe late but safe also for iframes
-		document.attachEvent("onreadystatechange", function(){
-			if ( document.readyState === "complete" ) {
-				document.detachEvent( "onreadystatechange", arguments.callee );
-				jQuery.ready();
-			}
-		});
-
-		// If IE and not an iframe
-		// continually check to see if the document is ready
-		if ( document.documentElement.doScroll && window == window.top ) (function(){
-			if ( jQuery.isReady ) return;
-
-			try {
-				// If IE is used, use the trick by Diego Perini
-				// http://javascript.nwbox.com/IEContentLoaded/
-				document.documentElement.doScroll("left");
-			} catch( error ) {
-				setTimeout( arguments.callee, 0 );
-				return;
-			}
-
-			// and execute any waiting functions
-			jQuery.ready();
-		})();
-	}
-
-	// A fallback to window.onload, that will always work
-	jQuery.event.add( window, "load", jQuery.ready );
-}
-
-jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
-	"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
-	"change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
-
-	// Handle event binding
-	jQuery.fn[name] = function(fn){
-		return fn ? this.bind(name, fn) : this.trigger(name);
-	};
-});
-
-// Prevent memory leaks in IE
-// And prevent errors on refresh with events like mouseover in other browsers
-// Window isn't included so as not to unbind existing unload events
-jQuery( window ).bind( 'unload', function(){ 
-	for ( var id in jQuery.cache )
-		// Skip the window
-		if ( id != 1 && jQuery.cache[ id ].handle )
-			jQuery.event.remove( jQuery.cache[ id ].handle.elem );
-}); 
-(function(){
-
-	jQuery.support = {};
-
-	var root = document.documentElement,
-		script = document.createElement("script"),
-		div = document.createElement("div"),
-		id = "script" + (new Date).getTime();
-
-	div.style.display = "none";
-	div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
-
-	var all = div.getElementsByTagName("*"),
-		a = div.getElementsByTagName("a")[0];
-
-	// Can't get basic test support
-	if ( !all || !all.length || !a ) {
-		return;
-	}
-
-	jQuery.support = {
-		// IE strips leading whitespace when .innerHTML is used
-		leadingWhitespace: div.firstChild.nodeType == 3,
-		
-		// Make sure that tbody elements aren't automatically inserted
-		// IE will insert them into empty tables
-		tbody: !div.getElementsByTagName("tbody").length,
-		
-		// Make sure that you can get all elements in an <object> element
-		// IE 7 always returns no results
-		objectAll: !!div.getElementsByTagName("object")[0]
-			.getElementsByTagName("*").length,
-		
-		// Make sure that link elements get serialized correctly by innerHTML
-		// This requires a wrapper element in IE
-		htmlSerialize: !!div.getElementsByTagName("link").length,
-		
-		// Get the style information from getAttribute
-		// (IE uses .cssText insted)
-		style: /red/.test( a.getAttribute("style") ),
-		
-		// Make sure that URLs aren't manipulated
-		// (IE normalizes it by default)
-		hrefNormalized: a.getAttribute("href") === "/a",
-		
-		// Make sure that element opacity exists
-		// (IE uses filter instead)
-		opacity: a.style.opacity === "0.5",
-		
-		// Verify style float existence
-		// (IE uses styleFloat instead of cssFloat)
-		cssFloat: !!a.style.cssFloat,
-
-		// Will be defined later
-		scriptEval: false,
-		noCloneEvent: true,
-		boxModel: null
-	};
-	
-	script.type = "text/javascript";
-	try {
-		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
-	} catch(e){}
-
-	root.insertBefore( script, root.firstChild );
-	
-	// Make sure that the execution of code works by injecting a script
-	// tag with appendChild/createTextNode
-	// (IE doesn't support this, fails, and uses .text instead)
-	if ( window[ id ] ) {
-		jQuery.support.scriptEval = true;
-		delete window[ id ];
-	}
-
-	root.removeChild( script );
-
-	if ( div.attachEvent && div.fireEvent ) {
-		div.attachEvent("onclick", function(){
-			// Cloning a node shouldn't copy over any
-			// bound event handlers (IE does this)
-			jQuery.support.noCloneEvent = false;
-			div.detachEvent("onclick", arguments.callee);
-		});
-		div.cloneNode(true).fireEvent("onclick");
-	}
-
-	// Figure out if the W3C box model works as expected
-	// document.body must exist before we can do this
-	jQuery(function(){
-		var div = document.createElement("div");
-		div.style.width = div.style.paddingLeft = "1px";
-
-		document.body.appendChild( div );
-		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
-		document.body.removeChild( div ).style.display = 'none';
-	});
-})();
-
-var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
-
-jQuery.props = {
-	"for": "htmlFor",
-	"class": "className",
-	"float": styleFloat,
-	cssFloat: styleFloat,
-	styleFloat: styleFloat,
-	readonly: "readOnly",
-	maxlength: "maxLength",
-	cellspacing: "cellSpacing",
-	rowspan: "rowSpan",
-	tabindex: "tabIndex"
-};
-jQuery.fn.extend({
-	// Keep a copy of the old load
-	_load: jQuery.fn.load,
-
-	load: function( url, params, callback ) {
-		if ( typeof url !== "string" )
-			return this._load( url );
-
-		var off = url.indexOf(" ");
-		if ( off >= 0 ) {
-			var selector = url.slice(off, url.length);
-			url = url.slice(0, off);
-		}
-
-		// Default to a GET request
-		var type = "GET";
-
-		// If the second parameter was provided
-		if ( params )
-			// If it's a function
-			if ( jQuery.isFunction( params ) ) {
-				// We assume that it's the callback
-				callback = params;
-				params = null;
-
-			// Otherwise, build a param string
-			} else if( typeof params === "object" ) {
-				params = jQuery.param( params );
-				type = "POST";
-			}
-
-		var self = this;
-
-		// Request the remote document
-		jQuery.ajax({
-			url: url,
-			type: type,
-			dataType: "html",
-			data: params,
-			complete: function(res, status){
-				// If successful, inject the HTML into all the matched elements
-				if ( status == "success" || status == "notmodified" )
-					// See if a selector was specified
-					self.html( selector ?
-						// Create a dummy div to hold the results
-						jQuery("<div/>")
-							// inject the contents of the document in, removing the scripts
-							// to avoid any 'Permission Denied' errors in IE
-							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
-
-							// Locate the specified elements
-							.find(selector) :
-
-						// If not, just inject the full result
-						res.responseText );
-
-				if( callback )
-					self.each( callback, [res.responseText, status, res] );
-			}
-		});
-		return this;
-	},
-
-	serialize: function() {
-		return jQuery.param(this.serializeArray());
-	},
-	serializeArray: function() {
-		return this.map(function(){
-			return this.elements ? jQuery.makeArray(this.elements) : this;
-		})
-		.filter(function(){
-			return this.name && !this.disabled &&
-				(this.checked || /select|textarea/i.test(this.nodeName) ||
-					/text|hidden|password|search/i.test(this.type));
-		})
-		.map(function(i, elem){
-			var val = jQuery(this).val();
-			return val == null ? null :
-				jQuery.isArray(val) ?
-					jQuery.map( val, function(val, i){
-						return {name: elem.name, value: val};
-					}) :
-					{name: elem.name, value: val};
-		}).get();
-	}
-});
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
-	jQuery.fn[o] = function(f){
-		return this.bind(o, f);
-	};
-});
-
-var jsc = now();
-
-jQuery.extend({
-  
-	get: function( url, data, callback, type ) {
-		// shift arguments if data argument was ommited
-		if ( jQuery.isFunction( data ) ) {
-			callback = data;
-			data = null;
-		}
-
-		return jQuery.ajax({
-			type: "GET",
-			url: url,
-			data: data,
-			success: callback,
-			dataType: type
-		});
-	},
-
-	getScript: function( url, callback ) {
-		return jQuery.get(url, null, callback, "script");
-	},
-
-	getJSON: function( url, data, callback ) {
-		return jQuery.get(url, data, callback, "json");
-	},
-
-	post: function( url, data, callback, type ) {
-		if ( jQuery.isFunction( data ) ) {
-			callback = data;
-			data = {};
-		}
-
-		return jQuery.ajax({
-			type: "POST",
-			url: url,
-			data: data,
-			success: callback,
-			dataType: type
-		});
-	},
-
-	ajaxSetup: function( settings ) {
-		jQuery.extend( jQuery.ajaxSettings, settings );
-	},
-
-	ajaxSettings: {
-		url: location.href,
-		global: true,
-		type: "GET",
-		contentType: "application/x-www-form-urlencoded",
-		processData: true,
-		async: true,
-		/*
-		timeout: 0,
-		data: null,
-		username: null,
-		password: null,
-		*/
-		// Create the request object; Microsoft failed to properly
-		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
-		// This function can be overriden by calling jQuery.ajaxSetup
-		xhr:function(){
-			return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
-		},
-		accepts: {
-			xml: "application/xml, text/xml",
-			html: "text/html",
-			script: "text/javascript, application/javascript",
-			json: "application/json, text/javascript",
-			text: "text/plain",
-			_default: "*/*"
-		}
-	},
-
-	// Last-Modified header cache for next request
-	lastModified: {},
-
-	ajax: function( s ) {
-		// Extend the settings, but re-extend 's' so that it can be
-		// checked again later (in the test suite, specifically)
-		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
-
-		var jsonp, jsre = /=\?(&|$)/g, status, data,
-			type = s.type.toUpperCase();
-
-		// convert data if not already a string
-		if ( s.data && s.processData && typeof s.data !== "string" )
-			s.data = jQuery.param(s.data);
-
-		// Handle JSONP Parameter Callbacks
-		if ( s.dataType == "jsonp" ) {
-			if ( type == "GET" ) {
-				if ( !s.url.match(jsre) )
-					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
-			} else if ( !s.data || !s.data.match(jsre) )
-				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
-			s.dataType = "json";
-		}
-
-		// Build temporary JSONP function
-		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
-			jsonp = "jsonp" + jsc++;
-
-			// Replace the =? sequence both in the query string and the data
-			if ( s.data )
-				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
-			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
-
-			// We need to make sure
-			// that a JSONP style response is executed properly
-			s.dataType = "script";
-
-			// Handle JSONP-style loading
-			window[ jsonp ] = function(tmp){
-				data = tmp;
-				success();
-				complete();
-				// Garbage collect
-				window[ jsonp ] = undefined;
-				try{ delete window[ jsonp ]; } catch(e){}
-				if ( head )
-					head.removeChild( script );
-			};
-		}
-
-		if ( s.dataType == "script" && s.cache == null )
-			s.cache = false;
-
-		if ( s.cache === false && type == "GET" ) {
-			var ts = now();
-			// try replacing _= if it is there
-			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
-			// if nothing was replaced, add timestamp to the end
-			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
-		}
-
-		// If data is available, append data to url for get requests
-		if ( s.data && type == "GET" ) {
-			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
-
-			// IE likes to send both get and post data, prevent this
-			s.data = null;
-		}
-
-		// Watch for a new set of requests
-		if ( s.global && ! jQuery.active++ )
-			jQuery.event.trigger( "ajaxStart" );
-
-		// Matches an absolute URL, and saves the domain
-		var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
-
-		// If we're requesting a remote document
-		// and trying to load JSON or Script with a GET
-		if ( s.dataType == "script" && type == "GET" && parts
-			&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
-
-			var head = document.getElementsByTagName("head")[0];
-			var script = document.createElement("script");
-			script.src = s.url;
-			if (s.scriptCharset)
-				script.charset = s.scriptCharset;
-
-			// Handle Script loading
-			if ( !jsonp ) {
-				var done = false;
-
-				// Attach handlers for all browsers
-				script.onload = script.onreadystatechange = function(){
-					if ( !done && (!this.readyState ||
-							this.readyState == "loaded" || this.readyState == "complete") ) {
-						done = true;
-						success();
-						complete();
-
-						// Handle memory leak in IE
-						script.onload = script.onreadystatechange = null;
-						head.removeChild( script );
-					}
-				};
-			}
-
-			head.appendChild(script);
-
-			// We handle everything using the script element injection
-			return undefined;
-		}
-
-		var requestDone = false;
-
-		// Create the request object
-		var xhr = s.xhr();
-
-		// Open the socket
-		// Passing null username, generates a login popup on Opera (#2865)
-		if( s.username )
-			xhr.open(type, s.url, s.async, s.username, s.password);
-		else
-			xhr.open(type, s.url, s.async);
-
-		// Need an extra try/catch for cross domain requests in Firefox 3
-		try {
-			// Set the correct header, if data is being sent
-			if ( s.data )
-				xhr.setRequestHeader("Content-Type", s.contentType);
-
-			// Set the If-Modified-Since header, if ifModified mode.
-			if ( s.ifModified )
-				xhr.setRequestHeader("If-Modified-Since",
-					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
-
-			// Set header so the called script knows that it's an XMLHttpRequest
-			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-
-			// Set the Accepts header for the server, depending on the dataType
-			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
-				s.accepts[ s.dataType ] + ", */*" :
-				s.accepts._default );
-		} catch(e){}
-
-		// Allow custom headers/mimetypes and early abort
-		if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
-			// Handle the global AJAX counter
-			if ( s.global && ! --jQuery.active )
-				jQuery.event.trigger( "ajaxStop" );
-			// close opended socket
-			xhr.abort();
-			return false;
-		}
-
-		if ( s.global )
-			jQuery.event.trigger("ajaxSend", [xhr, s]);
-
-		// Wait for a response to come back
-		var onreadystatechange = function(isTimeout){
-			// The request was aborted, clear the interval and decrement jQuery.active
-			if (xhr.readyState == 0) {
-				if (ival) {
-					// clear poll interval
-					clearInterval(ival);
-					ival = null;
-					// Handle the global AJAX counter
-					if ( s.global && ! --jQuery.active )
-						jQuery.event.trigger( "ajaxStop" );
-				}
-			// The transfer is complete and the data is available, or the request timed out
-			} else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
-				requestDone = true;
-
-				// clear poll interval
-				if (ival) {
-					clearInterval(ival);
-					ival = null;
-				}
-
-				status = isTimeout == "timeout" ? "timeout" :
-					!jQuery.httpSuccess( xhr ) ? "error" :
-					s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
-					"success";
-
-				if ( status == "success" ) {
-					// Watch for, and catch, XML document parse errors
-					try {
-						// process the data (runs the xml through httpData regardless of callback)
-						data = jQuery.httpData( xhr, s.dataType, s );
-					} catch(e) {
-						status = "parsererror";
-					}
-				}
-
-				// Make sure that the request was successful or notmodified
-				if ( status == "success" ) {
-					// Cache Last-Modified header, if ifModified mode.
-					var modRes;
-					try {
-						modRes = xhr.getResponseHeader("Last-Modified");
-					} catch(e) {} // swallow exception thrown by FF if header is not available
-
-					if ( s.ifModified && modRes )
-						jQuery.lastModified[s.url] = modRes;
-
-					// JSONP handles its own success callback
-					if ( !jsonp )
-						success();
-				} else
-					jQuery.handleError(s, xhr, status);
-
-				// Fire the complete handlers
-				complete();
-
-				if ( isTimeout )
-					xhr.abort();
-
-				// Stop memory leaks
-				if ( s.async )
-					xhr = null;
-			}
-		};
-
-		if ( s.async ) {
-			// don't attach the handler to the request, just poll it instead
-			var ival = setInterval(onreadystatechange, 13);
-
-			// Timeout checker
-			if ( s.timeout > 0 )
-				setTimeout(function(){
-					// Check to see if the request is still happening
-					if ( xhr && !requestDone )
-						onreadystatechange( "timeout" );
-				}, s.timeout);
-		}
-
-		// Send the data
-		try {
-			xhr.send(s.data);
-		} catch(e) {
-			jQuery.handleError(s, xhr, null, e);
-		}
-
-		// firefox 1.5 doesn't fire statechange for sync requests
-		if ( !s.async )
-			onreadystatechange();
-
-		function success(){
-			// If a local callback was specified, fire it and pass it the data
-			if ( s.success )
-				s.success( data, status );
-
-			// Fire the global callback
-			if ( s.global )
-				jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
-		}
-
-		function complete(){
-			// Process result
-			if ( s.complete )
-				s.complete(xhr, status);
-
-			// The request was completed
-			if ( s.global )
-				jQuery.event.trigger( "ajaxComplete", [xhr, s] );
-
-			// Handle the global AJAX counter
-			if ( s.global && ! --jQuery.active )
-				jQuery.event.trigger( "ajaxStop" );
-		}
-
-		// return XMLHttpRequest to allow aborting the request etc.
-		return xhr;
-	},
-
-	handleError: function( s, xhr, status, e ) {
-		// If a local callback was specified, fire it
-		if ( s.error ) s.error( xhr, status, e );
-
-		// Fire the global callback
-		if ( s.global )
-			jQuery.event.trigger( "ajaxError", [xhr, s, e] );
-	},
-
-	// Counter for holding the number of active queries
-	active: 0,
-
-	// Determines if an XMLHttpRequest was successful or not
-	httpSuccess: function( xhr ) {
-		try {
-			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
-			return !xhr.status && location.protocol == "file:" ||
-				( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
-		} catch(e){}
-		return false;
-	},
-
-	// Determines if an XMLHttpRequest returns NotModified
-	httpNotModified: function( xhr, url ) {
-		try {
-			var xhrRes = xhr.getResponseHeader("Last-Modified");
-
-			// Firefox always returns 200. check Last-Modified date
-			return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
-		} catch(e){}
-		return false;
-	},
-
-	httpData: function( xhr, type, s ) {
-		var ct = xhr.getResponseHeader("content-type"),
-			xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
-			data = xml ? xhr.responseXML : xhr.responseText;
-
-		if ( xml && data.documentElement.tagName == "parsererror" )
-			throw "parsererror";
-			
-		// Allow a pre-filtering function to sanitize the response
-		// s != null is checked to keep backwards compatibility
-		if( s && s.dataFilter )
-			data = s.dataFilter( data, type );
-
-		// The filter can actually parse the response
-		if( typeof data === "string" ){
-
-			// If the type is "script", eval it in global context
-			if ( type == "script" )
-				jQuery.globalEval( data );
-
-			// Get the JavaScript object, if JSON is used.
-			if ( type == "json" )
-				data = window["eval"]("(" + data + ")");
-		}
-		
-		return data;
-	},
-
-	// Serialize an array of form elements or a set of
-	// key/values into a query string
-	param: function( a ) {
-		var s = [ ];
-
-		function add( key, value ){
-			s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
-		};
-
-		// If an array was passed in, assume that it is an array
-		// of form elements
-		if ( jQuery.isArray(a) || a.jquery )
-			// Serialize the form elements
-			jQuery.each( a, function(){
-				add( this.name, this.value );
-			});
-
-		// Otherwise, assume that it's an object of key/value pairs
-		else
-			// Serialize the key/values
-			for ( var j in a )
-				// If the value is an array then the key names need to be repeated
-				if ( jQuery.isArray(a[j]) )
-					jQuery.each( a[j], function(){
-						add( j, this );
-					});
-				else
-					add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
-
-		// Return the resulting serialization
-		return s.join("&").replace(/%20/g, "+");
-	}
-
-});
-var elemdisplay = {},
-	timerId,
-	fxAttrs = [
-		// height animations
-		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
-		// width animations
-		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
-		// opacity animations
-		[ "opacity" ]
-	];
-
-function genFx( type, num ){
-	var obj = {};
-	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
-		obj[ this ] = type;
-	});
-	return obj;
-}
-
-jQuery.fn.extend({
-	show: function(speed,callback){
-		if ( speed ) {
-			return this.animate( genFx("show", 3), speed, callback);
-		} else {
-			for ( var i = 0, l = this.length; i < l; i++ ){
-				var old = jQuery.data(this[i], "olddisplay");
-				
-				this[i].style.display = old || "";
-				
-				if ( jQuery.css(this[i], "display") === "none" ) {
-					var tagName = this[i].tagName, display;
-					
-					if ( elemdisplay[ tagName ] ) {
-						display = elemdisplay[ tagName ];
-					} else {
-						var elem = jQuery("<" + tagName + " />").appendTo("body");
-						
-						display = elem.css("display");
-						if ( display === "none" )
-							display = "block";
-						
-						elem.remove();
-						
-						elemdisplay[ tagName ] = display;
-					}
-					
-					jQuery.data(this[i], "olddisplay", display);
-				}
-			}
-
-			// Set the display of the elements in a second loop
-			// to avoid the constant reflow
-			for ( var i = 0, l = this.length; i < l; i++ ){
-				this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
-			}
-			
-			return this;
-		}
-	},
-
-	hide: function(speed,callback){
-		if ( speed ) {
-			return this.animate( genFx("hide", 3), speed, callback);
-		} else {
-			for ( var i = 0, l = this.length; i < l; i++ ){
-				var old = jQuery.data(this[i], "olddisplay");
-				if ( !old && old !== "none" )
-					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
-			}
-
-			// Set the display of the elements in a second loop
-			// to avoid the constant reflow
-			for ( var i = 0, l = this.length; i < l; i++ ){
-				this[i].style.display = "none";
-			}
-
-			return this;
-		}
-	},
-
-	// Save the old toggle function
-	_toggle: jQuery.fn.toggle,
-
-	toggle: function( fn, fn2 ){
-		var bool = typeof fn === "boolean";
-
-		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
-			this._toggle.apply( this, arguments ) :
-			fn == null || bool ?
-				this.each(function(){
-					var state = bool ? fn : jQuery(this).is(":hidden");
-					jQuery(this)[ state ? "show" : "hide" ]();
-				}) :
-				this.animate(genFx("toggle", 3), fn, fn2);
-	},
-
-	fadeTo: function(speed,to,callback){
-		return this.animate({opacity: to}, speed, callback);
-	},
-
-	animate: function( prop, speed, easing, callback ) {
-		var optall = jQuery.speed(speed, easing, callback);
-
-		return this[ optall.queue === false ? "each" : "queue" ](function(){
-		
-			var opt = jQuery.extend({}, optall), p,
-				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
-				self = this;
-	
-			for ( p in prop ) {
-				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
-					return opt.complete.call(this);
-
-				if ( ( p == "height" || p == "width" ) && this.style ) {
-					// Store display property
-					opt.display = jQuery.css(this, "display");
-
-					// Make sure that nothing sneaks out
-					opt.overflow = this.style.overflow;
-				}
-			}
-
-			if ( opt.overflow != null )
-				this.style.overflow = "hidden";
-
-			opt.curAnim = jQuery.extend({}, prop);
-
-			jQuery.each( prop, function(name, val){
-				var e = new jQuery.fx( self, opt, name );
-
-				if ( /toggle|show|hide/.test(val) )
-					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
-				else {
-					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
-						start = e.cur(true) || 0;
-
-					if ( parts ) {
-						var end = parseFloat(parts[2]),
-							unit = parts[3] || "px";
-
-						// We need to compute starting value
-						if ( unit != "px" ) {
-							self.style[ name ] = (end || 1) + unit;
-							start = ((end || 1) / e.cur(true)) * start;
-							self.style[ name ] = start + unit;
-						}
-
-						// If a +=/-= token was provided, we're doing a relative animation
-						if ( parts[1] )
-							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
-
-						e.custom( start, end, unit );
-					} else
-						e.custom( start, val, "" );
-				}
-			});
-
-			// For JS strict compliance
-			return true;
-		});
-	},
-
-	stop: function(clearQueue, gotoEnd){
-		var timers = jQuery.timers;
-
-		if (clearQueue)
-			this.queue([]);
-
-		this.each(function(){
-			// go in reverse order so anything added to the queue during the loop is ignored
-			for ( var i = timers.length - 1; i >= 0; i-- )
-				if ( timers[i].elem == this ) {
-					if (gotoEnd)
-						// force the next step to be the last
-						timers[i](true);
-					timers.splice(i, 1);
-				}
-		});
-
-		// start the next in the queue if the last step wasn't forced
-		if (!gotoEnd)
-			this.dequeue();
-
-		return this;
-	}
-
-});
-
-// Generate shortcuts for custom animations
-jQuery.each({
-	slideDown: genFx("show", 1),
-	slideUp: genFx("hide", 1),
-	slideToggle: genFx("toggle", 1),
-	fadeIn: { opacity: "show" },
-	fadeOut: { opacity: "hide" }
-}, function( name, props ){
-	jQuery.fn[ name ] = function( speed, callback ){
-		return this.animate( props, speed, callback );
-	};
-});
-
-jQuery.extend({
-
-	speed: function(speed, easing, fn) {
-		var opt = typeof speed === "object" ? speed : {
-			complete: fn || !fn && easing ||
-				jQuery.isFunction( speed ) && speed,
-			duration: speed,
-			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
-		};
-
-		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
-			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
-
-		// Queueing
-		opt.old = opt.complete;
-		opt.complete = function(){
-			if ( opt.queue !== false )
-				jQuery(this).dequeue();
-			if ( jQuery.isFunction( opt.old ) )
-				opt.old.call( this );
-		};
-
-		return opt;
-	},
-
-	easing: {
-		linear: function( p, n, firstNum, diff ) {
-			return firstNum + diff * p;
-		},
-		swing: function( p, n, firstNum, diff ) {
-			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
-		}
-	},
-
-	timers: [],
-
-	fx: function( elem, options, prop ){
-		this.options = options;
-		this.elem = elem;
-		this.prop = prop;
-
-		if ( !options.orig )
-			options.orig = {};
-	}
-
-});
-
-jQuery.fx.prototype = {
-
-	// Simple function for setting a style value
-	update: function(){
-		if ( this.options.step )
-			this.options.step.call( this.elem, this.now, this );
-
-		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
-
-		// Set display property to block for height/width animations
-		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
-			this.elem.style.display = "block";
-	},
-
-	// Get the current size
-	cur: function(force){
-		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
-			return this.elem[ this.prop ];
-
-		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
-		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
-	},
-
-	// Start an animation from one number to another
-	custom: function(from, to, unit){
-		this.startTime = now();
-		this.start = from;
-		this.end = to;
-		this.unit = unit || this.unit || "px";
-		this.now = this.start;
-		this.pos = this.state = 0;
-
-		var self = this;
-		function t(gotoEnd){
-			return self.step(gotoEnd);
-		}
-
-		t.elem = this.elem;
-
-		if ( t() && jQuery.timers.push(t) && !timerId ) {
-			timerId = setInterval(function(){
-				var timers = jQuery.timers;
-
-				for ( var i = 0; i < timers.length; i++ )
-					if ( !timers[i]() )
-						timers.splice(i--, 1);
-
-				if ( !timers.length ) {
-					clearInterval( timerId );
-					timerId = undefined;
-				}
-			}, 13);
-		}
-	},
-
-	// Simple 'show' function
-	show: function(){
-		// Remember where we started, so that we can go back to it later
-		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
-		this.options.show = true;
-
-		// Begin the animation
-		// Make sure that we start at a small width/height to avoid any
-		// flash of content
-		this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
-
-		// Start by showing the element
-		jQuery(this.elem).show();
-	},
-
-	// Simple 'hide' function
-	hide: function(){
-		// Remember where we started, so that we can go back to it later
-		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
-		this.options.hide = true;
-
-		// Begin the animation
-		this.custom(this.cur(), 0);
-	},
-
-	// Each step of an animation
-	step: function(gotoEnd){
-		var t = now();
-
-		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
-			this.now = this.end;
-			this.pos = this.state = 1;
-			this.update();
-
-			this.options.curAnim[ this.prop ] = true;
-
-			var done = true;
-			for ( var i in this.options.curAnim )
-				if ( this.options.curAnim[i] !== true )
-					done = false;
-
-			if ( done ) {
-				if ( this.options.display != null ) {
-					// Reset the overflow
-					this.elem.style.overflow = this.options.overflow;
-
-					// Reset the display
-					this.elem.style.display = this.options.display;
-					if ( jQuery.css(this.elem, "display") == "none" )
-						this.elem.style.display = "block";
-				}
-
-				// Hide the element if the "hide" operation was done
-				if ( this.options.hide )
-					jQuery(this.elem).hide();
-
-				// Reset the properties, if the item has been hidden or shown
-				if ( this.options.hide || this.options.show )
-					for ( var p in this.options.curAnim )
-						jQuery.attr(this.elem.style, p, this.options.orig[p]);
-					
-				// Execute the complete function
-				this.options.complete.call( this.elem );
-			}
-
-			return false;
-		} else {
-			var n = t - this.startTime;
-			this.state = n / this.options.duration;
-
-			// Perform the easing function, defaults to swing
-			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
-			this.now = this.start + ((this.end - this.start) * this.pos);
-
-			// Perform the next step of the animation
-			this.update();
-		}
-
-		return true;
-	}
-
-};
-
-jQuery.extend( jQuery.fx, {
-	speeds:{
-		slow: 600,
- 		fast: 200,
- 		// Default speed
- 		_default: 400
-	},
-	step: {
-
-		opacity: function(fx){
-			jQuery.attr(fx.elem.style, "opacity", fx.now);
-		},
-
-		_default: function(fx){
-			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
-				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
-			else
-				fx.elem[ fx.prop ] = fx.now;
-		}
-	}
-});
-if ( document.documentElement["getBoundingClientRect"] )
-	jQuery.fn.offset = function() {
-		if ( !this[0] ) return { top: 0, left: 0 };
-		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
-		var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
-			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
-			top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
-			left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
-		return { top: top, left: left };
-	};
-else 
-	jQuery.fn.offset = function() {
-		if ( !this[0] ) return { top: 0, left: 0 };
-		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
-		jQuery.offset.initialized || jQuery.offset.initialize();
-
-		var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
-			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
-			body = doc.body, defaultView = doc.defaultView,
-			prevComputedStyle = defaultView.getComputedStyle(elem, null),
-			top = elem.offsetTop, left = elem.offsetLeft;
-
-		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
-			computedStyle = defaultView.getComputedStyle(elem, null);
-			top -= elem.scrollTop, left -= elem.scrollLeft;
-			if ( elem === offsetParent ) {
-				top += elem.offsetTop, left += elem.offsetLeft;
-				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
-					top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
-					left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
-				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
-			}
-			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
-				top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
-				left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
-			prevComputedStyle = computedStyle;
-		}
-
-		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
-			top  += body.offsetTop,
-			left += body.offsetLeft;
-
-		if ( prevComputedStyle.position === "fixed" )
-			top  += Math.max(docElem.scrollTop, body.scrollTop),
-			left += Math.max(docElem.scrollLeft, body.scrollLeft);
-
-		return { top: top, left: left };
-	};
-
-jQuery.offset = {
-	initialize: function() {
-		if ( this.initialized ) return;
-		var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
-			html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
-
-		rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
-		for ( prop in rules ) container.style[prop] = rules[prop];
-
-		container.innerHTML = html;
-		body.insertBefore(container, body.firstChild);
-		innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
-
-		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
-		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
-
-		innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
-		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
-
-		body.style.marginTop = '1px';
-		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
-		body.style.marginTop = bodyMarginTop;
-
-		body.removeChild(container);
-		this.initialized = true;
-	},
-
-	bodyOffset: function(body) {
-		jQuery.offset.initialized || jQuery.offset.initialize();
-		var top = body.offsetTop, left = body.offsetLeft;
-		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
-			top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
-			left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
-		return { top: top, left: left };
-	}
-};
-
-
-jQuery.fn.extend({
-	position: function() {
-		var left = 0, top = 0, results;
-
-		if ( this[0] ) {
-			// Get *real* offsetParent
-			var offsetParent = this.offsetParent(),
-
-			// Get correct offsets
-			offset       = this.offset(),
-			parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
-
-			// Subtract element margins
-			// note: when an element has margin: auto the offsetLeft and marginLeft 
-			// are the same in Safari causing offset.left to incorrectly be 0
-			offset.top  -= num( this, 'marginTop'  );
-			offset.left -= num( this, 'marginLeft' );
-
-			// Add offsetParent borders
-			parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
-			parentOffset.left += num( offsetParent, 'borderLeftWidth' );
-
-			// Subtract the two offsets
-			results = {
-				top:  offset.top  - parentOffset.top,
-				left: offset.left - parentOffset.left
-			};
-		}
-
-		return results;
-	},
-
-	offsetParent: function() {
-		var offsetParent = this[0].offsetParent || document.body;
-		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
-			offsetParent = offsetParent.offsetParent;
-		return jQuery(offsetParent);
-	}
-});
-
-
-// Create scrollLeft and scrollTop methods
-jQuery.each( ['Left', 'Top'], function(i, name) {
-	var method = 'scroll' + name;
-	
-	jQuery.fn[ method ] = function(val) {
-		if (!this[0]) return null;
-
-		return val !== undefined ?
-
-			// Set the scroll offset
-			this.each(function() {
-				this == window || this == document ?
-					window.scrollTo(
-						!i ? val : jQuery(window).scrollLeft(),
-						 i ? val : jQuery(window).scrollTop()
-					) :
-					this[ method ] = val;
-			}) :
-
-			// Return the scroll offset
-			this[0] == window || this[0] == document ?
-				self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
-					jQuery.boxModel && document.documentElement[ method ] ||
-					document.body[ method ] :
-				this[0][ method ];
-	};
-});
-// Create innerHeight, innerWidth, outerHeight and outerWidth methods
-jQuery.each([ "Height", "Width" ], function(i, name){
-
-	var tl = i ? "Left"  : "Top",  // top or left
-		br = i ? "Right" : "Bottom", // bottom or right
-		lower = name.toLowerCase();
-
-	// innerHeight and innerWidth
-	jQuery.fn["inner" + name] = function(){
-		return this[0] ?
-			jQuery.css( this[0], lower, false, "padding" ) :
-			null;
-	};
-
-	// outerHeight and outerWidth
-	jQuery.fn["outer" + name] = function(margin) {
-		return this[0] ?
-			jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
-			null;
-	};
-	
-	var type = name.toLowerCase();
-
-	jQuery.fn[ type ] = function( size ) {
-		// Get window width or height
-		return this[0] == window ?
-			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
-			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
-			document.body[ "client" + name ] :
-
-			// Get document width or height
-			this[0] == document ?
-				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
-				Math.max(
-					document.documentElement["client" + name],
-					document.body["scroll" + name], document.documentElement["scroll" + name],
-					document.body["offset" + name], document.documentElement["offset" + name]
-				) :
-
-				// Get or set width or height on the element
-				size === undefined ?
-					// Get width or height on the element
-					(this.length ? jQuery.css( this[0], type ) : null) :
-
-					// Set the width or height on the element (default to pixels if value is unitless)
-					this.css( type, typeof size === "string" ? size : size + "px" );
-	};
-
-});
-})();
diff --git a/static/js/jquery.galleriffic.js b/static/js/jquery.galleriffic.js
deleted file mode 100644
index 6d9e7fb..0000000
--- a/static/js/jquery.galleriffic.js
+++ /dev/null
@@ -1,979 +0,0 @@
-/**
- * jQuery Galleriffic plugin
- *
- * Copyright (c) 2008 Trent Foley (http://trentacular.com)
- * Licensed under the MIT License:
- *   http://www.opensource.org/licenses/mit-license.php
- *
- * Much thanks to primary contributer Ponticlaro (http://www.ponticlaro.com)
- */
-;(function($) {
-	// Globally keep track of all images by their unique hash.  Each item is an image data object.
-	var allImages = {};
-	var imageCounter = 0;
-
-	// Galleriffic static class
-	$.galleriffic = {
-		version: '2.0.1',
-
-		// Strips invalid characters and any leading # characters
-		normalizeHash: function(hash) {
-			return hash.replace(/^.*#/, '').replace(/\?.*$/, '');
-		},
-
-		getImage: function(hash) {
-			if (!hash)
-				return undefined;
-
-			hash = $.galleriffic.normalizeHash(hash);
-			return allImages[hash];
-		},
-
-		// Global function that looks up an image by its hash and displays the image.
-		// Returns false when an image is not found for the specified hash.
-		// @param {String} hash This is the unique hash value assigned to an image.
-		gotoImage: function(hash) {
-			var imageData = $.galleriffic.getImage(hash);
-			if (!imageData)
-				return false;
-
-			var gallery = imageData.gallery;
-			gallery.gotoImage(imageData);
-			
-			return true;
-		},
-
-		// Removes an image from its respective gallery by its hash.
-		// Returns false when an image is not found for the specified hash or the
-		// specified owner gallery does match the located images gallery.
-		// @param {String} hash This is the unique hash value assigned to an image.
-		// @param {Object} ownerGallery (Optional) When supplied, the located images
-		// gallery is verified to be the same as the specified owning gallery before
-		// performing the remove operation.
-		removeImageByHash: function(hash, ownerGallery) {
-			var imageData = $.galleriffic.getImage(hash);
-			if (!imageData)
-				return false;
-
-			var gallery = imageData.gallery;
-			if (ownerGallery && ownerGallery != gallery)
-				return false;
-
-			return gallery.removeImageByIndex(imageData.index);
-		}
-	};
-
-	var defaults = {
-		delay:                     3000,
-		numThumbs:                 20,
-		preloadAhead:              40, // Set to -1 to preload all images
-		enableTopPager:            false,
-		enableBottomPager:         true,
-		maxPagesToShow:            7,
-		imageContainerSel:         '',
-		captionContainerSel:       '',
-		controlsContainerSel:      '',
-		loadingContainerSel:       '',
-		renderSSControls:          true,
-		renderNavControls:         true,
-		playLinkText:              'Play',
-		pauseLinkText:             'Pause',
-		prevLinkText:              'Previous',
-		nextLinkText:              'Next',
-		nextPageLinkText:          'Next &rsaquo;',
-		prevPageLinkText:          '&lsaquo; Prev',
-		enableHistory:             false,
-		enableKeyboardNavigation:  true,
-		autoStart:                 false,
-		syncTransitions:           false,
-		defaultTransitionDuration: 1000,
-		onSlideChange:             undefined, // accepts a delegate like such: function(prevIndex, nextIndex) { ... }
-		onTransitionOut:           undefined, // accepts a delegate like such: function(slide, caption, isSync, callback) { ... }
-		onTransitionIn:            undefined, // accepts a delegate like such: function(slide, caption, isSync) { ... }
-		onPageTransitionOut:       undefined, // accepts a delegate like such: function(callback) { ... }
-		onPageTransitionIn:        undefined, // accepts a delegate like such: function() { ... }
-		onImageAdded:              undefined, // accepts a delegate like such: function(imageData, $li) { ... }
-		onImageRemoved:            undefined  // accepts a delegate like such: function(imageData, $li) { ... }
-	};
-
-	// Primary Galleriffic initialization function that should be called on the thumbnail container.
-	$.fn.galleriffic = function(settings) {
-		//  Extend Gallery Object
-		$.extend(this, {
-			// Returns the version of the script
-			version: $.galleriffic.version,
-
-			// Current state of the slideshow
-			isSlideshowRunning: false,
-			slideshowTimeout: undefined,
-
-			// This function is attached to the click event of generated hyperlinks within the gallery
-			clickHandler: function(e, link) {
-				this.pause();
-
-				if (!this.enableHistory) {
-					// The href attribute holds the unique hash for an image
-					var hash = $.galleriffic.normalizeHash($(link).attr('href'));
-					$.galleriffic.gotoImage(hash);
-					e.preventDefault();
-				}
-			},
-
-			// Appends an image to the end of the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
-			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
-			appendImage: function(listItem) {
-				this.addImage(listItem, false, false);
-				return this;
-			},
-
-			// Inserts an image into the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
-			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
-			// @param {Integer} position The index within the gallery where the item shouold be added.
-			insertImage: function(listItem, position) {
-				this.addImage(listItem, false, true, position);
-				return this;
-			},
-
-			// Adds an image to the gallery and optionally inserts/appends it to the DOM (thumbExists)
-			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
-			// @param {Boolean} thumbExists Specifies whether the thumbnail already exists in the DOM or if it needs to be added.
-			// @param {Boolean} insert Specifies whether the the image is appended to the end or inserted into the gallery.
-			// @param {Integer} position The index within the gallery where the item shouold be added.
-			addImage: function(listItem, thumbExists, insert, position) {
-				var $li = ( typeof listItem === "string" ) ? $(listItem) : listItem;				
-				var $aThumb = $li.find('a.thumb');
-				var slideUrl = $aThumb.attr('href');
-				var title = $aThumb.attr('title');
-				var $caption = $li.find('.caption').remove();
-				var hash = $aThumb.attr('name');
-
-				// Increment the image counter
-				imageCounter++;
-
-				// Autogenerate a hash value if none is present or if it is a duplicate
-				if (!hash || allImages[''+hash]) {
-					hash = imageCounter;
-				}
-
-				// Set position to end when not specified
-				if (!insert)
-					position = this.data.length;
-				
-				var imageData = {
-					title:title,
-					slideUrl:slideUrl,
-					caption:$caption,
-					hash:hash,
-					gallery:this,
-					index:position
-				};
-
-				// Add the imageData to this gallery's array of images
-				if (insert) {
-					this.data.splice(position, 0, imageData);
-
-					// Reset index value on all imageData objects
-					this.updateIndices(position);
-				}
-				else {
-					this.data.push(imageData);
-				}
-
-				var gallery = this;
-
-				// Add the element to the DOM
-				if (!thumbExists) {
-					// Update thumbs passing in addition post transition out handler
-					this.updateThumbs(function() {
-						var $thumbsUl = gallery.find('ul.thumbs');
-						if (insert)
-							$thumbsUl.children(':eq('+position+')').before($li);
-						else
-							$thumbsUl.append($li);
-						
-						if (gallery.onImageAdded)
-							gallery.onImageAdded(imageData, $li);
-					});
-				}
-
-				// Register the image globally
-				allImages[''+hash] = imageData;
-
-				// Setup attributes and click handler
-				$aThumb.attr('rel', 'history')
-					.attr('href', '#'+hash)
-					.removeAttr('name')
-					.click(function(e) {
-						gallery.clickHandler(e, this);
-					});
-
-				return this;
-			},
-
-			// Removes an image from the gallery based on its index.
-			// Returns false when the index is out of range.
-			removeImageByIndex: function(index) {
-				if (index < 0 || index >= this.data.length)
-					return false;
-				
-				var imageData = this.data[index];
-				if (!imageData)
-					return false;
-				
-				this.removeImage(imageData);
-				
-				return true;
-			},
-
-			// Convenience method that simply calls the global removeImageByHash method.
-			removeImageByHash: function(hash) {
-				return $.galleriffic.removeImageByHash(hash, this);
-			},
-
-			// Removes an image from the gallery.
-			removeImage: function(imageData) {
-				var index = imageData.index;
-				
-				// Remove the image from the gallery data array
-				this.data.splice(index, 1);
-				
-				// Remove the global registration
-				delete allImages[''+imageData.hash];
-				
-				// Remove the image's list item from the DOM
-				this.updateThumbs(function() {
-					var $li = gallery.find('ul.thumbs')
-						.children(':eq('+index+')')
-						.remove();
-
-					if (gallery.onImageRemoved)
-						gallery.onImageRemoved(imageData, $li);
-				});
-
-				// Update each image objects index value
-				this.updateIndices(index);
-
-				return this;
-			},
-
-			// Updates the index values of the each of the images in the gallery after the specified index
-			updateIndices: function(startIndex) {
-				for (i = startIndex; i < this.data.length; i++) {
-					this.data[i].index = i;
-				}
-				
-				return this;
-			},
-
-			// Scraped the thumbnail container for thumbs and adds each to the gallery
-			initializeThumbs: function() {
-				this.data = [];
-				var gallery = this;
-
-				this.find('ul.thumbs > li').each(function(i) {
-					gallery.addImage($(this), true, false);
-				});
-
-				return this;
-			},
-
-			isPreloadComplete: false,
-
-			// Initalizes the image preloader
-			preloadInit: function() {
-				if (this.preloadAhead == 0) return this;
-				
-				this.preloadStartIndex = this.currentImage.index;
-				var nextIndex = this.getNextIndex(this.preloadStartIndex);
-				return this.preloadRecursive(this.preloadStartIndex, nextIndex);
-			},
-
-			// Changes the location in the gallery the preloader should work
-			// @param {Integer} index The index of the image where the preloader should restart at.
-			preloadRelocate: function(index) {
-				// By changing this startIndex, the current preload script will restart
-				this.preloadStartIndex = index;
-				return this;
-			},
-
-			// Recursive function that performs the image preloading
-			// @param {Integer} startIndex The index of the first image the current preloader started on.
-			// @param {Integer} currentIndex The index of the current image to preload.
-			preloadRecursive: function(startIndex, currentIndex) {
-				// Check if startIndex has been relocated
-				if (startIndex != this.preloadStartIndex) {
-					var nextIndex = this.getNextIndex(this.preloadStartIndex);
-					return this.preloadRecursive(this.preloadStartIndex, nextIndex);
-				}
-
-				var gallery = this;
-
-				// Now check for preloadAhead count
-				var preloadCount = currentIndex - startIndex;
-				if (preloadCount < 0)
-					preloadCount = this.data.length-1-startIndex+currentIndex;
-				if (this.preloadAhead >= 0 && preloadCount > this.preloadAhead) {
-					// Do this in order to keep checking for relocated start index
-					setTimeout(function() { gallery.preloadRecursive(startIndex, currentIndex); }, 500);
-					return this;
-				}
-
-				var imageData = this.data[currentIndex];
-				if (!imageData)
-					return this;
-
-				// If already loaded, continue
-				if (imageData.image)
-					return this.preloadNext(startIndex, currentIndex); 
-				
-				// Preload the image
-				var image = new Image();
-				
-				image.onload = function() {
-					imageData.image = this;
-					gallery.preloadNext(startIndex, currentIndex);
-				};
-
-				image.alt = imageData.title;
-				image.src = imageData.slideUrl;
-
-				return this;
-			},
-			
-			// Called by preloadRecursive in order to preload the next image after the previous has loaded.
-			// @param {Integer} startIndex The index of the first image the current preloader started on.
-			// @param {Integer} currentIndex The index of the current image to preload.
-			preloadNext: function(startIndex, currentIndex) {
-				var nextIndex = this.getNextIndex(currentIndex);
-				if (nextIndex == startIndex) {
-					this.isPreloadComplete = true;
-				} else {
-					// Use setTimeout to free up thread
-					var gallery = this;
-					setTimeout(function() { gallery.preloadRecursive(startIndex, nextIndex); }, 100);
-				}
-
-				return this;
-			},
-
-			// Safe way to get the next image index relative to the current image.
-			// If the current image is the last, returns 0
-			getNextIndex: function(index) {
-				var nextIndex = index+1;
-				if (nextIndex >= this.data.length)
-					nextIndex = 0;
-				return nextIndex;
-			},
-
-			// Safe way to get the previous image index relative to the current image.
-			// If the current image is the first, return the index of the last image in the gallery.
-			getPrevIndex: function(index) {
-				var prevIndex = index-1;
-				if (prevIndex < 0)
-					prevIndex = this.data.length-1;
-				return prevIndex;
-			},
-
-			// Pauses the slideshow
-			pause: function() {
-				this.isSlideshowRunning = false;
-				if (this.slideshowTimeout) {
-					clearTimeout(this.slideshowTimeout);
-					this.slideshowTimeout = undefined;
-				}
-
-				if (this.$controlsContainer) {
-					this.$controlsContainer
-						.find('div.ss-controls a').removeClass().addClass('play')
-						.attr('title', this.playLinkText)
-						.attr('href', '#play')
-						.html(this.playLinkText);
-				}
-				
-				return this;
-			},
-
-			// Plays the slideshow
-			play: function() {
-				this.isSlideshowRunning = true;
-
-				if (this.$controlsContainer) {
-					this.$controlsContainer
-						.find('div.ss-controls a').removeClass().addClass('pause')
-						.attr('title', this.pauseLinkText)
-						.attr('href', '#pause')
-						.html(this.pauseLinkText);
-				}
-
-				if (!this.slideshowTimeout) {
-					var gallery = this;
-					this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
-				}
-
-				return this;
-			},
-
-			// Toggles the state of the slideshow (playing/paused)
-			toggleSlideshow: function() {
-				if (this.isSlideshowRunning)
-					this.pause();
-				else
-					this.play();
-
-				return this;
-			},
-
-			// Advances the slideshow to the next image and delegates navigation to the
-			// history plugin when history is enabled
-			// enableHistory is true
-			ssAdvance: function() {
-				if (this.isSlideshowRunning)
-					this.next(true);
-
-				return this;
-			},
-
-			// Advances the gallery to the next image.
-			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
-			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.  
-			next: function(dontPause, bypassHistory) {
-				this.gotoIndex(this.getNextIndex(this.currentImage.index), dontPause, bypassHistory);
-				return this;
-			},
-
-			// Navigates to the previous image in the gallery.
-			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
-			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
-			previous: function(dontPause, bypassHistory) {
-				this.gotoIndex(this.getPrevIndex(this.currentImage.index), dontPause, bypassHistory);
-				return this;
-			},
-
-			// Navigates to the next page in the gallery.
-			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
-			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
-			nextPage: function(dontPause, bypassHistory) {
-				var page = this.getCurrentPage();
-				var lastPage = this.getNumPages() - 1;
-				if (page < lastPage) {
-					var startIndex = page * this.numThumbs;
-					var nextPage = startIndex + this.numThumbs;
-					this.gotoIndex(nextPage, dontPause, bypassHistory);
-				}
-
-				return this;
-			},
-
-			// Navigates to the previous page in the gallery.
-			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
-			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
-			previousPage: function(dontPause, bypassHistory) {
-				var page = this.getCurrentPage();
-				if (page > 0) {
-					var startIndex = page * this.numThumbs;
-					var prevPage = startIndex - this.numThumbs;				
-					this.gotoIndex(prevPage, dontPause, bypassHistory);
-				}
-				
-				return this;
-			},
-
-			// Navigates to the image at the specified index in the gallery
-			// @param {Integer} index The index of the image in the gallery to display.
-			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
-			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
-			gotoIndex: function(index, dontPause, bypassHistory) {
-				if (!dontPause)
-					this.pause();
-				
-				if (index < 0) index = 0;
-				else if (index >= this.data.length) index = this.data.length-1;
-				
-				var imageData = this.data[index];
-				
-				if (!bypassHistory && this.enableHistory)
-					$.historyLoad(String(imageData.hash));  // At the moment, historyLoad only accepts string arguments
-				else
-					this.gotoImage(imageData);
-
-				return this;
-			},
-
-			// This function is garaunteed to be called anytime a gallery slide changes.
-			// @param {Object} imageData An object holding the image metadata of the image to navigate to.
-			gotoImage: function(imageData) {
-				var index = imageData.index;
-
-				if (this.onSlideChange)
-					this.onSlideChange(this.currentImage.index, index);
-				
-				this.currentImage = imageData;
-				this.preloadRelocate(index);
-				
-				this.refresh();
-				
-				return this;
-			},
-
-			// Returns the default transition duration value.  The value is halved when not
-			// performing a synchronized transition.
-			// @param {Boolean} isSync Specifies whether the transitions are synchronized.
-			getDefaultTransitionDuration: function(isSync) {
-				if (isSync)
-					return this.defaultTransitionDuration;
-				return this.defaultTransitionDuration / 2;
-			},
-
-			// Rebuilds the slideshow image and controls and performs transitions
-			refresh: function() {
-				var imageData = this.currentImage;
-				if (!imageData)
-					return this;
-
-				var index = imageData.index;
-
-				// Update Controls
-				if (this.$controlsContainer) {
-					this.$controlsContainer
-						.find('div.nav-controls a.prev').attr('href', '#'+this.data[this.getPrevIndex(index)].hash).end()
-						.find('div.nav-controls a.next').attr('href', '#'+this.data[this.getNextIndex(index)].hash);
-				}
-
-				var previousSlide = this.$imageContainer.find('span.current').addClass('previous').removeClass('current');
-				var previousCaption = 0;
-
-				if (this.$captionContainer) {
-					previousCaption = this.$captionContainer.find('span.current').addClass('previous').removeClass('current');
-				}
-
-				// Perform transitions simultaneously if syncTransitions is true and the next image is already preloaded
-				var isSync = this.syncTransitions && imageData.image;
-
-				// Flag we are transitioning
-				var isTransitioning = true;
-				var gallery = this;
-
-				var transitionOutCallback = function() {
-					// Flag that the transition has completed
-					isTransitioning = false;
-
-					// Remove the old slide
-					previousSlide.remove();
-
-					// Remove old caption
-					if (previousCaption)
-						previousCaption.remove();
-
-					if (!isSync) {
-						if (imageData.image && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
-							gallery.buildImage(imageData, isSync);
-						} else {
-							// Show loading container
-							if (gallery.$loadingContainer) {
-								gallery.$loadingContainer.show();
-							}
-						}
-					}
-				};
-
-				if (previousSlide.length == 0) {
-					// For the first slide, the previous slide will be empty, so we will call the callback immediately
-					transitionOutCallback();
-				} else {
-					if (this.onTransitionOut) {
-						this.onTransitionOut(previousSlide, previousCaption, isSync, transitionOutCallback);
-					} else {
-						previousSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0, transitionOutCallback);
-						if (previousCaption)
-							previousCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0);
-					}
-				}
-
-				// Go ahead and begin transitioning in of next image
-				if (isSync)
-					this.buildImage(imageData, isSync);
-
-				if (!imageData.image) {
-					var image = new Image();
-					
-					// Wire up mainImage onload event
-					image.onload = function() {
-						imageData.image = this;
-
-						// Only build image if the out transition has completed and we are still on the same image hash
-						if (!isTransitioning && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
-							gallery.buildImage(imageData, isSync);
-						}
-					};
-
-					// set alt and src
-					image.alt = imageData.title;
-					image.src = imageData.slideUrl;
-				}
-
-				// This causes the preloader (if still running) to relocate out from the currentIndex
-				this.relocatePreload = true;
-
-				return this.syncThumbs();
-			},
-
-			// Called by the refresh method after the previous image has been transitioned out or at the same time
-			// as the out transition when performing a synchronous transition.
-			// @param {Object} imageData An object holding the image metadata of the image to build.
-			// @param {Boolean} isSync Specifies whether the transitions are synchronized.
-			buildImage: function(imageData, isSync) {
-				var gallery = this;
-				var nextIndex = this.getNextIndex(imageData.index);
-
-				// Construct new hidden span for the image
-				var newSlide = this.$imageContainer
-					.append('<span class="image-wrapper current"><a class="advance-link" rel="history" href="#'+this.data[nextIndex].hash+'" title="'+imageData.title+'">&nbsp;</a></span>')
-					.find('span.current').css('opacity', '0');
-				
-				newSlide.find('a')
-					.append(imageData.image)
-					.click(function(e) {
-						gallery.clickHandler(e, this);
-					});
-				
-				var newCaption = 0;
-				if (this.$captionContainer) {
-					// Construct new hidden caption for the image
-					newCaption = this.$captionContainer
-						.append('<span class="image-caption current"></span>')
-						.find('span.current').css('opacity', '0')
-						.append(imageData.caption);
-				}
-
-				// Hide the loading conatiner
-				if (this.$loadingContainer) {
-					this.$loadingContainer.hide();
-				}
-
-				// Transition in the new image
-				if (this.onTransitionIn) {
-					this.onTransitionIn(newSlide, newCaption, isSync);
-				} else {
-					newSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
-					if (newCaption)
-						newCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
-				}
-				
-				if (this.isSlideshowRunning) {
-					if (this.slideshowTimeout)
-						clearTimeout(this.slideshowTimeout);
-
-					this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
-				}
-
-				return this;
-			},
-
-			// Returns the current page index that should be shown for the currentImage
-			getCurrentPage: function() {
-				return Math.floor(this.currentImage.index / this.numThumbs);
-			},
-
-			// Applies the selected class to the current image's corresponding thumbnail.
-			// Also checks if the current page has changed and updates the displayed page of thumbnails if necessary.
-			syncThumbs: function() {
-				var page = this.getCurrentPage();
-				if (page != this.displayedPage)
-					this.updateThumbs();
-
-				// Remove existing selected class and add selected class to new thumb
-				var $thumbs = this.find('ul.thumbs').children();
-				$thumbs.filter('.selected').removeClass('selected');
-				$thumbs.eq(this.currentImage.index).addClass('selected');
-
-				return this;
-			},
-
-			// Performs transitions on the thumbnails container and updates the set of
-			// thumbnails that are to be displayed and the navigation controls.
-			// @param {Delegate} postTransitionOutHandler An optional delegate that is called after
-			// the thumbnails container has transitioned out and before the thumbnails are rebuilt.
-			updateThumbs: function(postTransitionOutHandler) {
-				var gallery = this;
-				var transitionOutCallback = function() {
-					// Call the Post-transition Out Handler
-					if (postTransitionOutHandler)
-						postTransitionOutHandler();
-					
-					gallery.rebuildThumbs();
-
-					// Transition In the thumbsContainer
-					if (gallery.onPageTransitionIn)
-						gallery.onPageTransitionIn();
-					else
-						gallery.show();
-				};
-
-				// Transition Out the thumbsContainer
-				if (this.onPageTransitionOut) {
-					this.onPageTransitionOut(transitionOutCallback);
-				} else {
-					this.hide();
-					transitionOutCallback();
-				}
-
-				return this;
-			},
-
-			// Updates the set of thumbnails that are to be displayed and the navigation controls.
-			rebuildThumbs: function() {
-				var needsPagination = this.data.length > this.numThumbs;
-
-				// Rebuild top pager
-				if (this.enableTopPager) {
-					var $topPager = this.find('div.top');
-					if ($topPager.length == 0)
-						$topPager = this.prepend('<div class="top pagination"></div>').find('div.top');
-					else
-						$topPager.empty();
-
-					if (needsPagination)
-						this.buildPager($topPager);
-				}
-
-				// Rebuild bottom pager
-				if (this.enableBottomPager) {
-					var $bottomPager = this.find('div.bottom');
-					if ($bottomPager.length == 0)
-						$bottomPager = this.append('<div class="bottom pagination"></div>').find('div.bottom');
-					else
-						$bottomPager.empty();
-
-					if (needsPagination)
-						this.buildPager($bottomPager);
-				}
-
-				var page = this.getCurrentPage();
-				var startIndex = page*this.numThumbs;
-				var stopIndex = startIndex+this.numThumbs-1;
-				if (stopIndex >= this.data.length)
-					stopIndex = this.data.length-1;
-
-				// Show/Hide thumbs
-				var $thumbsUl = this.find('ul.thumbs');
-				$thumbsUl.find('li').each(function(i) {
-					var $li = $(this);
-					if (i >= startIndex && i <= stopIndex) {
-						$li.show();
-					} else {
-						$li.hide();
-					}
-				});
-
-				this.displayedPage = page;
-
-				// Remove the noscript class from the thumbs container ul
-				$thumbsUl.removeClass('noscript');
-				
-				return this;
-			},
-
-			// Returns the total number of pages required to display all the thumbnails.
-			getNumPages: function() {
-				return Math.ceil(this.data.length/this.numThumbs);
-			},
-
-			// Rebuilds the pager control in the specified matched element.
-			// @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
-			buildPager: function(pager) {
-				var gallery = this;
-				var numPages = this.getNumPages();
-				var page = this.getCurrentPage();
-				var startIndex = page * this.numThumbs;
-				var pagesRemaining = this.maxPagesToShow - 1;
-				
-				var pageNum = page - Math.floor((this.maxPagesToShow - 1) / 2) + 1;
-				if (pageNum > 0) {
-					var remainingPageCount = numPages - pageNum;
-					if (remainingPageCount < pagesRemaining) {
-						pageNum = pageNum - (pagesRemaining - remainingPageCount);
-					}
-				}
-
-				if (pageNum < 0) {
-					pageNum = 0;
-				}
-
-				// Prev Page Link
-				if (page > 0) {
-					var prevPage = startIndex - this.numThumbs;
-					pager.append('<a rel="history" href="#'+this.data[prevPage].hash+'" title="'+this.prevPageLinkText+'">'+this.prevPageLinkText+'</a>');
-				}
-
-				// Create First Page link if needed
-				if (pageNum > 0) {
-					this.buildPageLink(pager, 0, numPages);
-					if (pageNum > 1)
-						pager.append('<span class="ellipsis">&hellip;</span>');
-					
-					pagesRemaining--;
-				}
-
-				// Page Index Links
-				while (pagesRemaining > 0) {
-					this.buildPageLink(pager, pageNum, numPages);
-					pagesRemaining--;
-					pageNum++;
-				}
-
-				// Create Last Page link if needed
-				if (pageNum < numPages) {
-					var lastPageNum = numPages - 1;
-					if (pageNum < lastPageNum)
-						pager.append('<span class="ellipsis">&hellip;</span>');
-
-					this.buildPageLink(pager, lastPageNum, numPages);
-				}
-
-				// Next Page Link
-				var nextPage = startIndex + this.numThumbs;
-				if (nextPage < this.data.length) {
-					pager.append('<a rel="history" href="#'+this.data[nextPage].hash+'" title="'+this.nextPageLinkText+'">'+this.nextPageLinkText+'</a>');
-				}
-
-				pager.find('a').click(function(e) {
-					gallery.clickHandler(e, this);
-				});
-
-				return this;
-			},
-
-			// Builds a single page link within a pager.  This function is called by buildPager
-			// @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
-			// @param {Integer} pageNum The page number of the page link to build.
-			// @param {Integer} numPages The total number of pages required to display all thumbnails.
-			buildPageLink: function(pager, pageNum, numPages) {
-				var pageLabel = pageNum + 1;
-				var currentPage = this.getCurrentPage();
-				if (pageNum == currentPage)
-					pager.append('<span class="current">'+pageLabel+'</span>');
-				else if (pageNum < numPages) {
-					var imageIndex = pageNum*this.numThumbs;
-					pager.append('<a rel="history" href="#'+this.data[imageIndex].hash+'" title="'+pageLabel+'">'+pageLabel+'</a>');
-				}
-				
-				return this;
-			}
-		});
-
-		// Now initialize the gallery
-		$.extend(this, defaults, settings);
-		
-		// Verify the history plugin is available
-		if (this.enableHistory && !$.historyInit)
-			this.enableHistory = false;
-		
-		// Select containers
-		if (this.imageContainerSel) this.$imageContainer = $(this.imageContainerSel);
-		if (this.captionContainerSel) this.$captionContainer = $(this.captionContainerSel);
-		if (this.loadingContainerSel) this.$loadingContainer = $(this.loadingContainerSel);
-
-		// Initialize the thumbails
-		this.initializeThumbs();
-		
-		if (this.maxPagesToShow < 3)
-			this.maxPagesToShow = 3;
-
-		this.displayedPage = -1;
-		this.currentImage = this.data[0];
-		var gallery = this;
-
-		// Hide the loadingContainer
-		if (this.$loadingContainer)
-			this.$loadingContainer.hide();
-
-		// Setup controls
-		if (this.controlsContainerSel) {
-			this.$controlsContainer = $(this.controlsContainerSel).empty();
-			
-			if (this.renderSSControls) {
-				if (this.autoStart) {
-					this.$controlsContainer
-						.append('<div class="ss-controls"><a href="#pause" class="pause" title="'+this.pauseLinkText+'">'+this.pauseLinkText+'</a></div>');
-				} else {
-					this.$controlsContainer
-						.append('<div class="ss-controls"><a href="#play" class="play" title="'+this.playLinkText+'">'+this.playLinkText+'</a></div>');
-				}
-
-				this.$controlsContainer.find('div.ss-controls a')
-					.click(function(e) {
-						gallery.toggleSlideshow();
-						e.preventDefault();
-						return false;
-					});
-			}
-		
-			if (this.renderNavControls) {
-				this.$controlsContainer
-					.append('<div class="nav-controls"><a class="prev" rel="history" title="'+this.prevLinkText+'">'+this.prevLinkText+'</a><a class="next" rel="history" title="'+this.nextLinkText+'">'+this.nextLinkText+'</a></div>')
-					.find('div.nav-controls a')
-					.click(function(e) {
-						gallery.clickHandler(e, this);
-					});
-			}
-		}
-
-		var initFirstImage = !this.enableHistory || !location.hash;
-		if (this.enableHistory && location.hash) {
-			var hash = $.galleriffic.normalizeHash(location.hash);
-			var imageData = allImages[hash];
-			if (!imageData)
-				initFirstImage = true;
-		}
-
-		// Setup gallery to show the first image
-		if (initFirstImage)
-			this.gotoIndex(0, false, true);
-
-		// Setup Keyboard Navigation
-		if (this.enableKeyboardNavigation) {
-			$(document).keydown(function(e) {
-				var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
-				switch(key) {
-					case 32: // space
-						gallery.next();
-						e.preventDefault();
-						break;
-					case 33: // Page Up
-						gallery.previousPage();
-						e.preventDefault();
-						break;
-					case 34: // Page Down
-						gallery.nextPage();
-						e.preventDefault();
-						break;
-					case 35: // End
-						gallery.gotoIndex(gallery.data.length-1);
-						e.preventDefault();
-						break;
-					case 36: // Home
-						gallery.gotoIndex(0);
-						e.preventDefault();
-						break;
-					case 37: // left arrow
-						gallery.previous();
-						e.preventDefault();
-						break;
-					case 39: // right arrow
-						gallery.next();
-						e.preventDefault();
-						break;
-				}
-			});
-		}
-
-		// Auto start the slideshow
-		if (this.autoStart)
-			this.play();
-
-		// Kickoff Image Preloader after 1 second
-		setTimeout(function() { gallery.preloadInit(); }, 1000);
-
-		return this;
-	};
-})(jQuery);
diff --git a/static/js/jquery.history.js b/static/js/jquery.history.js
deleted file mode 100644
index 90f21fa..0000000
--- a/static/js/jquery.history.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * jQuery history plugin
- * 
- * sample page: http://www.mikage.to/jquery/jquery_history.html
- *
- * Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari)
- * Licensed under the MIT License:
- *   http://www.opensource.org/licenses/mit-license.php
- *
- * Modified by Lincoln Cooper to add Safari support and only call the callback once during initialization
- * for msie when no initial hash supplied.
- */
-
-
-jQuery.extend({
-	historyCurrentHash: undefined,
-	historyCallback: undefined,
-	historyIframeSrc: undefined,
-	
-	historyInit: function(callback, src){
-		jQuery.historyCallback = callback;
-		if (src) jQuery.historyIframeSrc = src;
-		var current_hash = location.hash.replace(/\?.*$/, '');
-		
-		jQuery.historyCurrentHash = current_hash;
-		// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
-		if (jQuery.browser.msie) {
-			// To stop the callback firing twice during initilization if no hash present
-			if (jQuery.historyCurrentHash == '') {
-			jQuery.historyCurrentHash = '#';
-		}
-		
-			// add hidden iframe for IE
-			jQuery("body").prepend('<iframe id="jQuery_history" style="display: none;"'+
-				(jQuery.historyIframeSrc ? ' src="'+jQuery.historyIframeSrc+'"' : '')
-				+'></iframe>'
-			);
-			var ihistory = jQuery("#jQuery_history")[0];
-			var iframe = ihistory.contentWindow.document;
-			iframe.open();
-			iframe.close();
-			iframe.location.hash = current_hash;
-		}
-		else if (jQuery.browser.safari) {
-			// etablish back/forward stacks
-			jQuery.historyBackStack = [];
-			jQuery.historyBackStack.length = history.length;
-			jQuery.historyForwardStack = [];
-			jQuery.lastHistoryLength = history.length;
-			
-			jQuery.isFirst = true;
-		}
-		if(current_hash)
-			jQuery.historyCallback(current_hash.replace(/^#/, ''));
-		setInterval(jQuery.historyCheck, 100);
-	},
-	
-	historyAddHistory: function(hash) {
-		// This makes the looping function do something
-		jQuery.historyBackStack.push(hash);
-		
-		jQuery.historyForwardStack.length = 0; // clear forwardStack (true click occured)
-		this.isFirst = true;
-	},
-	
-	historyCheck: function(){
-		// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
-		if (jQuery.browser.msie) {
-			// On IE, check for location.hash of iframe
-			var ihistory = jQuery("#jQuery_history")[0];
-			var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
-			var current_hash = iframe.location.hash.replace(/\?.*$/, '');
-			if(current_hash != jQuery.historyCurrentHash) {
-			
-				location.hash = current_hash;
-				jQuery.historyCurrentHash = current_hash;
-				jQuery.historyCallback(current_hash.replace(/^#/, ''));
-				
-			}
-		} else if (jQuery.browser.safari) {
-			if(jQuery.lastHistoryLength == history.length && jQuery.historyBackStack.length > jQuery.lastHistoryLength) {
-				jQuery.historyBackStack.shift();
-			}
-			if (!jQuery.dontCheck) {
-				var historyDelta = history.length - jQuery.historyBackStack.length;
-				jQuery.lastHistoryLength = history.length;
-				
-				if (historyDelta) { // back or forward button has been pushed
-					jQuery.isFirst = false;
-					if (historyDelta < 0) { // back button has been pushed
-						// move items to forward stack
-						for (var i = 0; i < Math.abs(historyDelta); i++) jQuery.historyForwardStack.unshift(jQuery.historyBackStack.pop());
-					} else { // forward button has been pushed
-						// move items to back stack
-						for (var i = 0; i < historyDelta; i++) jQuery.historyBackStack.push(jQuery.historyForwardStack.shift());
-					}
-					var cachedHash = jQuery.historyBackStack[jQuery.historyBackStack.length - 1];
-					if (cachedHash != undefined) {
-						jQuery.historyCurrentHash = location.hash.replace(/\?.*$/, '');
-						jQuery.historyCallback(cachedHash);
-					}
-				} else if (jQuery.historyBackStack[jQuery.historyBackStack.length - 1] == undefined && !jQuery.isFirst) {
-					// back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
-					// document.URL doesn't change in Safari
-					if (location.hash) {
-						var current_hash = location.hash;
-						jQuery.historyCallback(location.hash.replace(/^#/, ''));
-					} else {
-						var current_hash = '';
-						jQuery.historyCallback('');
-					}
-					jQuery.isFirst = true;
-				}
-			}
-		} else {
-			// otherwise, check for location.hash
-			var current_hash = location.hash.replace(/\?.*$/, '');
-			if(current_hash != jQuery.historyCurrentHash) {
-				jQuery.historyCurrentHash = current_hash;
-				jQuery.historyCallback(current_hash.replace(/^#/, ''));
-			}
-		}
-	},
-	historyLoad: function(hash){
-		var newhash;
-		hash = decodeURIComponent(hash.replace(/\?.*$/, ''));
-		
-		if (jQuery.browser.safari) {
-			newhash = hash;
-		}
-		else {
-			newhash = '#' + hash;
-			location.hash = newhash;
-		}
-		jQuery.historyCurrentHash = newhash;
-		
-		// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
-		if (jQuery.browser.msie) {
-			var ihistory = jQuery("#jQuery_history")[0];
-			var iframe = ihistory.contentWindow.document;
-			iframe.open();
-			iframe.close();
-			iframe.location.hash = newhash;
-			jQuery.lastHistoryLength = history.length;
-			jQuery.historyCallback(hash);
-		}
-		else if (jQuery.browser.safari) {
-			jQuery.dontCheck = true;
-			// Manually keep track of the history values for Safari
-			this.historyAddHistory(hash);
-			
-			// Wait a while before allowing checking so that Safari has time to update the "history" object
-			// correctly (otherwise the check loop would detect a false change in hash).
-			var fn = function() {jQuery.dontCheck = false;};
-			window.setTimeout(fn, 200);
-			jQuery.historyCallback(hash);
-			// N.B. "location.hash=" must be the last line of code for Safari as execution stops afterwards.
-			//      By explicitly using the "location.hash" command (instead of using a variable set to "location.hash") the
-			//      URL in the browser and the "history" object are both updated correctly.
-			location.hash = newhash;
-		}
-		else {
-		  jQuery.historyCallback(hash);
-		}
-	}
-});
-
-
diff --git a/static/js/jquery.opacityrollover.js b/static/js/jquery.opacityrollover.js
deleted file mode 100644
index 0c413fb..0000000
--- a/static/js/jquery.opacityrollover.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * jQuery Opacity Rollover plugin
- *
- * Copyright (c) 2009 Trent Foley (http://trentacular.com)
- * Licensed under the MIT License:
- *   http://www.opensource.org/licenses/mit-license.php
- */
-;(function($) {
-	var defaults = {
-		mouseOutOpacity:   0.67,
-		mouseOverOpacity:  1.0,
-		fadeSpeed:         'fast',
-		exemptionSelector: '.selected'
-	};
-
-	$.fn.opacityrollover = function(settings) {
-		// Initialize the effect
-		$.extend(this, defaults, settings);
-
-		var config = this;
-
-		function fadeTo(element, opacity) {
-			var $target = $(element);
-			
-			if (config.exemptionSelector)
-				$target = $target.not(config.exemptionSelector);	
-			
-			$target.fadeTo(config.fadeSpeed, opacity);
-		}
-
-		this.css('opacity', this.mouseOutOpacity)
-			.hover(
-				function () {
-					fadeTo(this, config.mouseOverOpacity);
-				},
-				function () {
-					fadeTo(this, config.mouseOutOpacity);
-				});
-
-		return this;
-	};
-})(jQuery);
diff --git a/static/js/jush.js b/static/js/jush.js
deleted file mode 100644
index 20f417a..0000000
--- a/static/js/jush.js
+++ /dev/null
@@ -1,515 +0,0 @@
-/** JUSH - JavaScript Syntax Highlighter
-* @link http://jush.sourceforge.net
-* @author Jakub Vrana, http://php.vrana.cz
-* @copyright 2007 Jakub Vrana
-* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
-* @version $Date:: 2009-01-29 12:28:10 +0100#$
-*/
-
-/* Limitations:
-<style> and <script> supposes CDATA or HTML comments
-unnecessary escaping (e.g. echo "\'" or ='&quot;') is removed
-*/
-
-var jush = {
-	sql_function: 'mysql_db_query|mysql_query|mysql_unbuffered_query|mysqli_master_query|mysqli_multi_query|mysqli_query|mysqli_real_query|mysqli_rpl_query_type|mysqli_send_query|mysqli_stmt_prepare',
-	sqlite_function: 'sqlite_query|sqlite_unbuffered_query|sqlite_single_query|sqlite_array_query|sqlite_exec',
-	pgsql_function: 'pg_prepare|pg_query|pg_query_params|pg_send_prepare|pg_send_query|pg_send_query_params',
-
-	style: function (href) {
-		var link = document.createElement('link');
-		link.rel = 'stylesheet';
-		link.type = 'text/css';
-		link.href = href;
-		document.getElementsByTagName('head')[0].appendChild(link);
-	},
-
-	highlight: function (language, text) {
-		this.last_tag = '';
-		return '<span class="jush">' + this.highlight_states([ language ], text.replace(/\r\n?/g, '\n'), (language != 'htm' && language != 'tag'))[0] + '</span>';
-	},
-
-	highlight_tag: function (tag, tab_width) {
-		var pre = document.getElementsByTagName(tag);
-		var tab = '';
-		for (var i = (tab_width !== undefined ? tab_width : 4); i--; ) {
-			tab += ' ';
-		}
-		for (var i=0; i < pre.length; i++) {
-			var match = /(^|\s)jush($|\s|-(\S+))/.exec(pre[i].className);
-			if (match) {
-				var s = this.highlight(match[3] ? match[3] : 'htm', this.html_entity_decode(pre[i].innerHTML.replace(/<br(\s+[^>]*)?>/gi, '\n').replace(/<[^>]*>/g, ''))).replace(/\t/g, tab.length ? tab : '\t').replace(/(^|\n| ) /g, '$1&nbsp;');
-				if (pre[i].outerHTML && /^pre$/i.test(tag)) {
-					pre[i].outerHTML = pre[i].outerHTML.match(/[^>]+>/)[0] + s + '</' + tag + '>';
-				} else {
-					pre[i].innerHTML = s.replace(/\n/g, '<br />');
-				}
-			}
-		}
-	},
-
-	keywords_links: function (state, s) {
-		if (state == 'js_write') {
-			state = 'js';
-		}
-		if (/^(php_quo_var|php_sql|php_sqlite|php_pgsql|php_echo|php_phpini)$/.test(state)) {
-			state = 'php';
-		}
-		if (this.links2 && this.links2[state]) {
-			var url = this.urls[state];
-			s = s.replace(this.links2[state], function (str) {
-				for (var i=arguments.length - 4; i > 0; i--) {
-					if (arguments[i]) {
-						var link = url[0].replace(/\$key/g, url[i]);
-						switch (state) {
-							case 'php': link = link.replace(/\$1/g, arguments[i].toLowerCase()); break;
-							case 'phpini': link = link.replace(/\$1/g, arguments[i].replace(/_/g, '-')); break;
-							case 'sql': link = link.replace(/\$1/g, arguments[i].toLowerCase().replace(/\s+|_/g, '-')); break;
-							case 'sqlite': link = link.replace(/\$1/g, arguments[i].toLowerCase().replace(/\s+/g, '')); break;
-							case 'pgsql': link = link.replace(/\$1/g, arguments[i].toLowerCase().replace(/\s+/g, (i == 1 ? '-' : ''))); break;
-							case 'cnf': link = link.replace(/\$1/g, arguments[i].toLowerCase()); break;
-							case 'js': link = link.replace(/\$1/g, arguments[i].replace(/\./g, '/')); break;
-							default: link = link.replace(/\$1/g, arguments[i]);
-						}
-						return '<a' + (url[i] ? ' href="' + link + '"' : '') + '>' + arguments[i] + '</a>' + (arguments[arguments.length - 3] ? arguments[arguments.length - 3] : '');
-					}
-				}
-			});
-		}
-		return s;
-	},
-
-	build_regexp: function (tr1, in_php, state) {
-		var re = [];
-		for (var k in tr1) {
-			var s = tr1[k].toString().replace(/^\/|\/[^\/]*$/g, '');
-			if ((!in_php || k != 'php') && (state == 'htm' || (s != '(<)(\\/script)(>)' && s != '(<)(\\/style)(>)'))) {
-				re.push(s);
-			} else {
-				delete tr1[k];
-			}
-		}
-		return new RegExp(re.join('|'), 'gi');
-	},
-	
-	highlight_states: function (states, text, in_php, escape) {
-		var php = /<\?(?!xml)(?:php)?|<script\s+language\s*=\s*(?:"php"|'php'|php)\s*>/i; // asp_tags=0, short_open_tag=1
-		var num = /(?:\b[0-9]+\.?[0-9]*|\.[0-9]+)(?:[eE][+-]?[0-9]+)?/;
-		var tr = { // transitions
-			htm: { php: php, tag_css: /(<)(style)\b/i, tag_js: /(<)(script)\b/i, htm_com: /<!--/, 0: /(<!)([^>]*)(>)/, tag: /(<)([^<>\s]+)/, ent: /&/ },
-			htm_com: { php: php, 1: /-->/ },
-			ent: { php: php, 1: /;/ },
-			tag: { php: php, att_css: /(\s+)(style)(\s*=\s*)/i, att_js: /(\s+)(on[^=<>\s]+)(\s*=\s*)/i, att: /(\s+)([^=<>\s]*)(\s*)/, 1: />/ },
-			tag_css: { php: php, att: /(\s+)([^=<>\s]*)(\s*)/, css: />/ },
-			tag_js: { php: php, att: /(\s+)([^=<>\s]*)(\s*)/, js: />/ },
-			att: { php: php, att_quo: /=\s*"/, att_apo: /=\s*'/, att_val: /=\s*/, 1: /\s/, 2: />/ },
-			att_css: { php: php, att_quo: /"/, att_apo: /'/, att_val: /\s*/ },
-			att_js: { php: php, att_quo: /"/, att_apo: /'/, att_val: /\s*/ },
-			att_quo: { php: php, 2: /"/ },
-			att_apo: { php: php, 2: /'/ },
-			att_val: { php: php, 2: /(?=>|\s)|$/ },
-			
-			css: { php: php, quo: /"/, apo: /'/, com: /\/\*/, css_at: /(@)([^;\s{]+)/, css_pro: /\{/, 2: /(<)(\/style)(>)/i },
-			css_at: { php: php, quo: /"/, apo: /'/, com: /\/\*/, css_at2: /\{/, 1: /;/ },
-			css_at2: { php: php, quo: /"/, apo: /'/, com: /\/\*/, css_at: /@/, css_pro: /\{/, 2: /}/ },
-			css_pro: { php: php, com: /\/\*/, css_val: /(\s*)([^:\s]+)(\s*:)/, 1: /}/ },
-			css_val: { php: php, quo: /"/, apo: /'/, css_js: /expression\s*\(/i, com: /\/\*/, clr: /#/, num: /[-+]?[0-9]*\.?[0-9]+(?:em|ex|px|in|cm|mm|pt|pc|%)?/, 1: /;|$/, 2: /}/ },
-			css_js: { php: php, css_js: /\(/, 1: /\)/ },
-			quo: { php: php, esc: /\\/, 1: /"/ },
-			apo: { php: php, esc: /\\/, 1: /'/ },
-			com: { php: php, 1: /\*\// },
-			esc: { 1: /./ }, //! php_quo allows [0-7]{1,3} and x[0-9A-Fa-f]{1,2}, Python allows newline, octal, hexa and Unicode
-			one: { 1: /\n/ },
-			clr: { 1: /(?=[^a-fA-F0-9])|$/ },
-			num: { 1: /()/ },
-			
-			js: { php: php, quo: /"/, apo: /'/, js_one: /\/\//, com: /\/\*/, js_reg: /\//, num: num, js_write: /(\b)(write(?:ln)?)(\()/, 2: /(<)(\/script)(>)/i },
-			js_write: { php: php, quo: /"/, apo: /'/, js_one: /\/\//, com: /\/\*/, js_reg: /\//, num: num, js_write: /\(/, 1: /\)/, 3: /(<)(\/script)(>)/i },
-			js_one: { php: php, 1: /\n/, 2: /(<)(\/script)(>)/i },
-			js_reg: { php: php, esc: /\\/, 1: /\/[a-z]*/i }, //! highlight regexp
-			
-			php: { php_quo: /"/, php_apo: /'/, php_bac: /`/, php_one: /\/\/|#/, php_com: /\/\*/, php_eot: /<<<[ \t]*/, php_new: /(\b)(new)\b/i, php_sql: new RegExp('(\\b)(' + this.sql_function + ')(\\s*\\()', 'i'), php_sqlite: new RegExp('(\\b)(' + this.sqlite_function + ')(\\s*\\()', 'i'), php_pgsql: new RegExp('(\\b)(' + this.pgsql_function + ')(\\s*\\()', 'i'), php_echo: /(\b)(echo|print)\b/i, php_halt: /(\b)(__halt_compiler)(\s*\(\s*\))/i, php_var: /\$/, num: num, php_phpini: /(\b)(ini_get|ini_set)(\s*\()/i, 1: /\?>|<\/script>/i }, //! matches ::echo
-			php_quo_var: { php_quo: /"/, php_apo: /'/, php_bac: /`/, php_one: /\/\/|#/, php_com: /\/\*/, php_eot: /<<<[ \t]*/, php_new: /(\b)(new)\b/i, php_sql: new RegExp('(\\b)(' + this.sql_function + ')(\\s*\\()', 'i'), php_sqlite: new RegExp('(\\b)(' + this.sqlite_function + ')(\\s*\\()', 'i'), php_pgsql: new RegExp('(\\b)(' + this.pgsql_function + ')(\\s*\\()', 'i'), 1: /}/ },
-			php_echo: { php_quo: /"/, php_apo: /'/, php_bac: /`/, php_one: /\/\/|#/, php_com: /\/\*/, php_eot: /<<<[ \t]*/, php_new: /(\b)(new)\b/i, php_sql: new RegExp('(\\b)(' + this.sql_function + ')(\\s*\\()', 'i'), php_sqlite: new RegExp('(\\b)(' + this.sqlite_function + ')(\\s*\\()', 'i'), php_pgsql: new RegExp('(\\b)(' + this.pgsql_function + ')(\\s*\\()', 'i'), php_echo: /\(/, php_var: /\$/, num: num, php_phpini: /(\b)(ini_get|ini_set)(\s*\()/i, 1: /\)|;/, 2: /\?>|<\/script>/i },
-			php_sql: { php_quo: /"/, php_apo: /'/, php_bac: /`/, php_one: /\/\/|#/, php_com: /\/\*/, php_eot: /<<<[ \t]*/, php_sql: /\(/, php_var: /\$/, num: num, 1: /\)/ },
-			php_sqlite: { php_quo: /"/, php_apo: /'/, php_bac: /`/, php_one: /\/\/|#/, php_com: /\/\*/, php_eot: /<<<[ \t]*/, php_sqlite: /\(/, php_var: /\$/, num: num, 1: /\)/ },
-			php_pgsql: { php_quo: /"/, php_apo: /'/, php_bac: /`/, php_one: /\/\/|#/, php_com: /\/\*/, php_eot: /<<<[ \t]*/, php_pgsql: /\(/, php_var: /\$/, num: num, 1: /\)/ },
-			php_phpini: { php_quo: /"/, php_apo: /'/, php_bac: /`/, php_one: /\/\/|#/, php_com: /\/\*/, php_eot: /<<<[ \t]*/, php_phpini: /\(/, php_var: /\$/, num: num, 1: /[,)]/ },
-			php_new: { php_one: /\/\/|#/, php_com: /\/\*/, 1: /[_a-zA-Z0-9\x7F-\xFF]+/ },
-			php_one: { 1: /\n/, 2: /\?>/ },
-			php_eot: { php_eot2: /([^'"]+)(['"]?)/ },
-			php_eot2: { php_quo_var: /\$\{|\{\$/, php_var: /\$/ }, // php_eot2[2] to be set in php_eot handler
-			php_quo: { php_quo_var: /\$\{|\{\$/, php_var: /\$/, esc: /\\/, 1: /"/ },
-			php_bac: { php_quo_var: /\$\{|\{\$/, php_var: /\$/, esc: /\\/, 1: /`/ }, //! highlight shell
-			php_var: { 1: /(?=[^_a-zA-Z0-9\x7F-\xFF])|$/ },
-			php_apo: { esc: /\\/, 1: /'/ },
-			php_com: { 1: /\*\// },
-			php_halt: { php_halt_one: /\/\/|#/, php_com: /\/\*/, php_halt2: /;|\?>\n?/ },
-			php_halt_one: { 1: /\n/, php_halt2: /\?>\n?/ },
-			php_halt2: { 3: /$/ },
-			
-			phpini: { 0: /$/ },
-			
-			py: { one: /#/, py_rlapo: /u?r'''/i, py_rlquo: /u?r"""/i, py_rapo: /u?r'/i, py_rquo: /u?r"/i, py_lapo: /u?'''/i, py_lquo: /u?"""/i, apo: /u?'/i, quo: /u?"/i, num: num },
-			py_rlapo: { 1: /'''/ },
-			py_rlquo: { 1: /"""/ },
-			py_rapo: { 1: /'/ },
-			py_rquo: { 1: /"/ },
-			py_lapo: { esc: /\\/, 1: /'''/ },
-			py_lquo: { esc: /\\/, 1: /"""/ },
-			
-			sql: { sql_apo: /'/, sql_quo: /"/, bac: /`/, one: /-- |#|--(?=\n|$)/, com: /\/\*/, sql_var: /\B@/, num: num },
-			sqlite: { sqlite_apo: /'/, sqlite_quo: /"/, bra: /\[/, one: /--/, com: /\/\*/, sql_var: /[:@$]/, num: num },
-			pgsql: { sql_apo: /'/, sqlite_quo: /"/, sql_eot: /\$/, one: /--/, com_nest: /\/\*/, num: num }, // standard_conforming_strings=off
-			sql_apo: { esc: /\\/, 0: /''/, 1: /'/ },
-			sql_quo: { esc: /\\/, 0: /""/, 1: /"/ },
-			sql_var: { 1: /(?=[^_.$a-zA-Z0-9])|$/ },
-			sqlite_apo: { 0: /''/, 1: /'/ },
-			sqlite_quo: { 0: /""/, 1: /"/ },
-			sql_eot: { sql_eot2: /\$/ },
-			sql_eot2: { }, // sql_eot2[2] to be set in sql_eot handler
-			com_nest: { com_nest: /\/\*/, 1: /\*\// },
-			bac: { 1: /`/ },
-			bra: { 1: /]/ },
-			
-			cnf: { quo: /"/, one: /#/, cnf_php: /(\b)(PHPIniDir)([ \t]+)/i, cnf_phpini: /(\b)(php_value|php_flag|php_admin_value|php_admin_flag)([ \t]+)/i },
-			cnf_php: { 1: /()/ },
-			cnf_phpini: { cnf_phpini_val: /[ \t]/ },
-			cnf_phpini_val: { apo: /'/, quo: /"/, 2: /($|\n)/ }
-		};
-		var regexps = { };
-		for (var key in tr) {
-			regexps[key] = this.build_regexp(tr[key], in_php, states[0]);
-		}
-		var ret = []; // return
-		for (var i=1; i < states.length; i++) {
-			ret.push('<span class="jush-' + states[i] + '">');
-		}
-		var state = states[states.length - 1];
-		var match;
-		var child_states = [ ];
-		var s_states;
-		var start = 0;
-		loop: while (start < text.length && (match = regexps[state].exec(text))) {
-			for (var key in tr[state]) {
-				var m;
-				if ((m = tr[state][key].exec(match[0])) && !m[0].index && m[0].length == match[0].length) { // check index and length to allow '/' before '</script>'
-					//~ console.log(states + ' (' + key + '): ' + text.substring(start).replace(/\n/g, '\\n'));
-					var division = match.index + (key == 'php_halt2' ? match[0].length : 0);
-					var s = text.substring(start, division);
-					
-					// highlight children
-					var prev_state = states[states.length - 2];
-					if ((state == 'att_quo' || state == 'att_apo' || state == 'att_val') && (prev_state == 'att_js' || prev_state == 'att_css' || /^\s*javascript:/i.test(s))) { // javascript: - easy but without own state //! should be checked only in %URI;
-						child_states.unshift(prev_state == 'att_css' ? 'css_pro' : 'js');
-						s_states = this.highlight_states(child_states, this.html_entity_decode(s), true, (state == 'att_apo' ? this.htmlspecialchars_apo : (state == 'att_quo' ? this.htmlspecialchars_quo : this.htmlspecialchars_quo_apo)));
-					} else if (state == 'css_js' || state == 'cnf_phpini') {
-						child_states.unshift(state.substr(4));
-						s_states = this.highlight_states(child_states, s, true);
-					} else if ((state == 'php_quo' || state == 'php_apo') && (prev_state == 'php_sql' || prev_state == 'php_sqlite' || prev_state == 'php_pgsql' || prev_state == 'php_phpini')) {
-						child_states.unshift(prev_state.substr(4));
-						s_states = this.highlight_states(child_states, this.stripslashes(s), true, (state == 'php_apo' ? this.addslashes_apo : this.addslashes_quo));
-					} else if (key == 'php_halt2') {
-						child_states.unshift('htm');
-						s_states = this.highlight_states(child_states, s, true);
-					} else if ((state == 'apo' || state == 'quo') && prev_state == 'js_write') {
-						child_states.unshift('htm');
-						s_states = this.highlight_states(child_states, s, true);
-					} else if (((state == 'php_quo' || state == 'php_apo') && prev_state == 'php_echo') || (state == 'php_eot2' && states[states.length - 3] == 'php_echo')) {
-						var i;
-						for (i=states.length; i--; ) {
-							prev_state = states[i];
-							if (prev_state.substring(0, 3) != 'php' && prev_state != 'att_quo' && prev_state != 'att_apo' && prev_state != 'att_val') {
-								break;
-							}
-							prev_state = '';
-						}
-						var f = (state == 'php_eot2' ? this.addslashes : (state == 'php_apo' ? this.addslashes_apo : this.addslashes_quo));
-						s = this.stripslashes(s);
-						if (prev_state == 'att_js' || prev_state == 'att_css') {
-							var g = (states[i+1] == 'att_quo' ? this.htmlspecialchars_quo : (states[i+1] == 'att_apo' ? this.htmlspecialchars_apo : this.htmlspecialchars_quo_apo));
-							child_states.unshift(prev_state == 'att_js' ? 'js' : 'css_pro');
-							s_states = this.highlight_states(child_states, this.html_entity_decode(s), true, function (string) { return f(g(string)); });
-						} else if (prev_state && child_states) {
-							child_states.unshift(prev_state);
-							s_states = this.highlight_states(child_states, s, true, f);
-						} else {
-							s = this.htmlspecialchars(s);
-							s_states = [ (escape ? escape(s) : s), (isNaN(+key) || !/^(att_js|att_css|css_js|js_write|php_sql|php_sqlite|php_pgsql|php_echo|php_phpini)$/.test(state) || /^(js_write|php_echo|php_sql|php_sqlite|php_pgsql|php_phpini|css_js)$/.test(prev_state) ? child_states : [ ]) ];
-						}
-					} else {
-						s = this.htmlspecialchars(s);
-						s_states = [ (escape ? escape(s) : s), (isNaN(+key) || !/^(att_js|att_css|css_js|js_write|php_sql|php_sqlite|php_pgsql|php_echo|php_phpini)$/.test(state) || /^(js_write|php_echo|php_sql|php_sqlite|php_pgsql|php_phpini|css_js)$/.test(prev_state) ? child_states : [ ]) ]; // reset child states when escaping construct
-					}
-					s = s_states[0];
-					child_states = s_states[1];
-					s = this.keywords_links(state, s);
-					ret.push(s);
-					
-					s = text.substring(division, match.index + match[0].length);
-					s = (m.length < 3 ? (s ? '<span class="jush-op">' + this.htmlspecialchars(escape ? escape(s) : s) + '</span>' : '') : (m[1] ? '<span class="jush-op">' + this.htmlspecialchars(escape ? escape(m[1]) : m[1]) + '</span>' : '') + this.htmlspecialchars(escape ? escape(m[2]) : m[2]) + (m[3] ? '<span class="jush-op">' + this.htmlspecialchars(escape ? escape(m[3]) : m[3]) + '</span>' : ''));
-					if (isNaN(+key)) {
-						if (this.links && this.links[key] && m[2]) {
-							if (/^tag/.test(key)) {
-								this.last_tag = m[2].toUpperCase();
-							}
-							var link = (/^tag/.test(key) && !/^(ins|del)$/i.test(m[2]) ? m[2].toUpperCase() : m[2].toLowerCase());
-							var k_link = '';
-							var att_mapping = {
-								'align-APPLET': 'IMG', 'align-IFRAME': 'IMG', 'align-INPUT': 'IMG', 'align-OBJECT': 'IMG',
-								'align-COL': 'TD', 'align-COLGROUP': 'TD', 'align-TBODY': 'TD', 'align-TFOOT': 'TD', 'align-TH': 'TD', 'align-THEAD': 'TD', 'align-TR': 'TD',
-								'border-OBJECT': 'IMG',
-								'cite-BLOCKQUOTE': 'Q',
-								'cite-DEL': 'INS',
-								'color-BASEFONT': 'FONT',
-								'face-BASEFONT': 'FONT',
-								'height-TD': 'TH',
-								'height-OBJECT': 'IMG',
-								'longdesc-IFRAME': 'FRAME',
-								'name-TEXTAREA': 'BUTTON',
-								'name-IFRAME': 'FRAME',
-								'name-OBJECT': 'INPUT',
-								'src-IFRAME': 'FRAME',
-								'type-LINK': 'A',
-								'width-OBJECT': 'IMG',
-								'width-TD': 'TH'
-							};
-							var att_tag = (att_mapping[link + '-' + this.last_tag] ? att_mapping[link + '-' + this.last_tag] : this.last_tag);
-							for (var k in this.links[key]) {
-								if (key == 'att' && this.links[key][k].test(link + '-' + att_tag)) {
-									link += '-' + att_tag;
-									k_link = k;
-									break;
-								} else if (this.links[key][k].test(m[2])) {
-									k_link = k;
-									if (key != 'att') {
-										break;
-									}
-								}
-							}
-							if (k_link) {
-								s = (m[1] ? '<span class="jush-op">' + this.htmlspecialchars(escape ? escape(m[1]) : m[1]) + '</span>' : '');
-								s += '<a href="' + this.urls[key].replace(/\$key/, k_link).replace(/\$val/, link) + '">' + this.htmlspecialchars(escape ? escape(m[2]) : m[2]) + '</a>';
-								s += (m[3] ? '<span class="jush-op">' + this.htmlspecialchars(escape ? escape(m[3]) : m[3]) + '</span>' : '');
-							}
-						}
-						ret.push('<span class="jush-' + key + '">', s);
-						states.push(key);
-						if (state == 'php_eot') {
-							tr.php_eot2[2] = new RegExp('(\n)(' + match[1] + ')(;?\n)');
-							regexps.php_eot2 = this.build_regexp((match[2] == "'" ? { 2: tr.php_eot2[2] } : tr.php_eot2));
-						} else if (state == 'sql_eot') {
-							tr.sql_eot2[2] = new RegExp('\\$' + text.substring(start, match.index) + '\\$');
-							regexps.sql_eot2 = this.build_regexp(tr.sql_eot2);
-						}
-					} else if (states.length <= key) {
-						return [ 'out of states' ];
-					} else {
-						ret.push(s);
-						for (var i=0; i < key; i++) {
-							ret.push('</span>');
-							states.pop();
-						}
-					}
-					start = regexps[state].lastIndex;
-					state = states[states.length - 1];
-					regexps[state].lastIndex = start;
-					continue loop;
-				}
-			}
-			return [ 'regexp not found' ];
-		}
-		ret.push(this.keywords_links(state, this.htmlspecialchars(text.substring(start))));
-		for (var i=1; i < states.length; i++) {
-			ret.push('</span>');
-		}
-		states.shift();
-		return [ ret.join(''), states ];
-	},
-
-	htmlspecialchars: function (string) {
-		return string.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
-	},
-	
-	htmlspecialchars_quo: function (string) {
-		return jush.htmlspecialchars(string).replace(/"/g, '&quot;'); // jush - this.htmlspecialchars_quo is passed as reference
-	},
-	
-	htmlspecialchars_apo: function (string) {
-		return jush.htmlspecialchars(string).replace(/'/g, '&#39;');
-	},
-	
-	htmlspecialchars_quo_apo: function (string) {
-		return jush.htmlspecialchars_quo(string).replace(/'/g, '&#39;');
-	},
-	
-	html_entity_decode: function (string) {
-		return string.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#(?:([0-9]+)|x([0-9a-f]+));/gi, function (str, p1, p2) { //! named entities
-			return String.fromCharCode(p1 ? p1 : parseInt(p2, 16));
-		}).replace(/&amp;/g, '&');
-	},
-	
-	addslashes: function (string) {
-		return string.replace(/\\/g, '\\$&');
-	},
-	
-	addslashes_apo: function (string) {
-		return string.replace(/[\\']/g, '\\$&');
-	},
-	
-	addslashes_quo: function (string) {
-		return string.replace(/[\\"]/g, '\\$&');
-	},
-	
-	stripslashes: function (string) {
-		return string.replace(/\\([\\"'])/g, '$1');
-	}
-};
-
-jush.urls = {
-	// $key stands for key in jush.links.class, $val stands for found string
-	tag: 'http://www.w3.org/TR/html4/$key.html#edef-$val',
-	tag_css: 'http://www.w3.org/TR/html4/$key.html#edef-$val',
-	tag_js: 'http://www.w3.org/TR/html4/$key.html#edef-$val',
-	att: 'http://www.w3.org/TR/html4/$key.html#adef-$val',
-	att_css: 'http://www.w3.org/TR/html4/$key.html#adef-$val',
-	att_js: 'http://www.w3.org/TR/html4/$key.html#adef-$val',
-	css_val: 'http://www.w3.org/TR/CSS21/$key.html#propdef-$val',
-	css_at: 'http://www.w3.org/TR/CSS21/$key',
-	js_write: 'http://developer.mozilla.org/En/docs/DOM/$key.$val',
-	php_new: 'http://www.php.net/$key.$val',
-	php_sql: 'http://www.php.net/$key.$val',
-	php_sqlite: 'http://www.php.net/$key.$val',
-	php_pgsql: 'http://www.php.net/$key.$val',
-	php_echo: 'http://www.php.net/$key.$val',
-	php_phpini: 'http://www.php.net/$key.$val',
-	php_halt: 'http://www.php.net/$key.halt-compiler',
-	cnf_php: 'http://www.php.net/$key',
-	cnf_phpini: 'http://www.php.net/configuration.changes#$key',
-	
-	// [0] is base, other elements correspond to () in jush.links2, $key stands for text of selected element, $1 stands for found string
-	php: [ 'http://www.php.net/$key',
-		'function.$1', 'control-structures.alternative-syntax', 'control-structures.$1', 'control-structures.do.while', 'control-structures.foreach', 'control-structures.switch', 'language.functions#functions.user-defined', 'language.oop', 'language.constants.predefined', 'language.exceptions', 'language.oop5.$1', 'language.oop5.basic#language.oop5.basic.$1', 'language.oop5.cloning', 'language.oop5.constants', 'language.oop5.interfaces', 'language.oop5.visibility', 'language.operators.logical', 'language.variables.scope#language.variables.scope.$1', 'language.namespaces',
-		'function.$1',
-		'function.socket-get-option', 'function.socket-set-option'
-	],
-	phpini: [ 'http://www.php.net/$key',
-		'features.safe-mode#ini.$1', 'ini.core#ini.$1', 'apache.configuration#ini.$1', 'apc.configuration#ini.$1', 'apd.configuration#ini.$1', 'bc.configuration#ini.$1', 'com.configuration#ini.$1', 'datetime.configuration#ini.$1', 'dbx.configuration#ini.$1', 'errorfunc.configuration#ini.$1', 'exif.configuration#ini.$1', 'expect.configuration#ini.$1', 'filesystem.configuration#ini.$1', 'ibase.configuration#ini.$1', 'ibm-db2.configuration#ini.$1', 'ifx.configuration#ini.$1', 'image.configuration#ini.image.jpeg-ignore-warning', 'info.configuration#ini.$1', 'mail.configuration#ini.$1', 'mail.configuration#ini.smtp', 'maxdb.configuration#ini.$1', 'mbstring.configuration#ini.$1', 'mime-magic.configuration#ini.$1', 'misc.configuration#ini.$1', 'misc.configuration#ini.syntax-highlighting', 'msql.configuration#ini.$1', 'mysql.configuration#ini.$1', 'mysqli.configuration#ini.$1', 'network.configuration#ini.$1', 'nsapi.configuration#ini.$1', 'oci8.configuration#ini.$1', 'outcontrol.configuration#ini.$1', 'pcre.configuration#ini.$1', 'pdo-odbc.configuration#ini.$1', 'pgsql.configuration#ini.$1', 'runkit.configuration#ini.$1', 'session.configuration#ini.$1', 'soap.configuration#ini.$1', 'sqlite.configuration#ini.$1', 'sybase.configuration#ini.$1', 'tidy.configuration#ini.$1', 'unicode.configuration#ini.$1', 'odbc.configuration#ini.$1', 'zlib.configuration#ini.$1'
-	],
-	py: [ 'http://docs.python.org/lib/$key.html',
-		'browser-controllers', 'built-in-funcs', 'csv-contents', 'ctypes-foreign-functions', 'ctypes-function-prototypes', 'ctypes-utility-functions', 'curses-functions', 'cursespanel-functions', 'decimal-decimal', 'defaultdict-objects', 'deque-objects', 'doctest-basic-api', 'doctest-debugging', 'doctest-options', 'doctest-unittest-api', 'elementtree-functions', 'inspect-classes-functions', 'inspect-source', 'inspect-stack', 'inspect-types', 'itertools-functions', 'logging-config-api', 'module--winreg', 'module-Bastion', 'module-aifc', 'module-al', 'module-anydbm', 'module-array', 'module-asyncore', 'module-atexit', 'module-audioop', 'module-base64', 'module-binascii', 'module-binhex', 'module-bisect', 'module-bsddb', 'module-calendar', 'module-cd', 'module-cgitb', 'module-cmath', 'module-code', 'module-codecs', 'module-codeop', 'module-colorsys', 'module-commands', 'module-compileall', 'module-compiler', 'module-compiler.visitor', 'module-contextlib', 'module-copyreg', 'module-crypt', 'module-curses.ascii', 'module-curses.textpad', 'module-curses.wrapper', 'module-dbhash', 'module-dbm', 'module-difflib', 'module-dircache', 'module-dis', 'module-dl', 'module-dumbdbm', 'module-email.charset', 'module-email.encoders', 'module-email.header', 'module-email.iterators', 'module-email.utils', 'module-encodings.idna', 'module-fcntl', 'module-filecmp', 'module-fileinput', 'module-fm', 'module-fnmatch', 'module-fpectl', 'module-fpformat', 'module-functools', 'module-gc', 'module-gdbm', 'module-getopt', 'module-getpass', 'module-gl', 'module-glob', 'module-gopherlib', 'module-grp', 'module-gzip', 'module-heapq', 'module-hmac', 'module-hotshot.stats', 'module-imageop', 'module-imaplib', 'module-imgfile', 'module-imghdr', 'module-imp', 'module-jpeg', 'module-keyword', 'module-linecache', 'module-locale', 'module-logging', 'module-mailcap', 'module-marshal', 'module-math', 'module-md5', 'module-mimetools', 'module-mimetypes', 'module-mimify', 'module-mmap', 'module-modulefinder', 'module-msilib', 'module-new', 'module-nis', 'module-operator', 'module-os.path', 'module-ossaudiodev', 'module-pdb', 'module-pickletools', 'module-pkgutil', 'module-popen2', 'module-posixfile', 'module-pprint', 'module-profile', 'module-pty', 'module-pwd', 'module-pyclbr', 'module-pycompile', 'module-quopri', 'module-random', 'module-readline', 'module-repr', 'module-rfc822', 'module-rgbimg', 'module-runpy', 'module-select', 'module-sha', 'module-shelve', 'module-shlex', 'module-shutil', 'module-signal', 'module-sndhdr', 'module-socket', 'module-spwd', 'module-stat', 'module-stringprep', 'module-struct', 'module-sunau', 'module-sunaudiodev', 'module-sys', 'module-syslog', 'module-tabnanny', 'module-tarfile', 'module-tempfile', 'module-termios', 'module-test.testsupport', 'module-textwrap', 'module-thread', 'module-threading', 'module-time', 'module-token', 'module-tokenize', 'module-traceback', 'module-tty', 'module-turtle', 'module-unicodedata', 'module-urllib', 'module-urllib2', 'module-urlparse', 'module-uu', 'module-uuid', 'module-wave', 'module-weakref', 'module-webbrowser', 'module-whichdb', 'module-winsound', 'module-wsgiref.simpleserver', 'module-wsgiref.util', 'module-wsgiref.validate', 'module-xml.dom.minidom', 'module-xml.dom.pulldom', 'module-xml.parsers.expat', 'module-xml.sax', 'module-xml.sax.saxutils', 'module-zipfile', 'module-zlib', 'msvcrt-console', 'msvcrt-files', 'msvcrt-other', 'node150', 'node217', 'node304', 'node317', 'node41', 'node42', 'node442', 'node443', 'node444', 'node445', 'node446', 'node447', 'node46', 'node522', 'node523', 'node530', 'node553', 'node563', 'node634', 'node635', 'node658', 'node686', 'node732', 'node733', 'node860', 'node861', 'node862', 'node908', 'non-essential-built-in-funcs', 'os-fd-ops', 'os-file-dir', 'os-miscfunc', 'os-newstreams', 'os-path', 'os-process', 'os-procinfo', 'sqlite3-Module-Contents', 'unittest-contents', 'warning-functions'
-	],
-	sql: [ 'http://dev.mysql.com/doc/mysql/en/$key',
-		'$1.html', 'commit.html', 'savepoints.html', 'lock-tables.html',
-		'numeric-type-overview.html', 'date-and-time-type-overview.html', 'string-type-overview.html',
-		'comparison-operators.html#operator_$1', 'comparison-operators.html#function_$1', 'any-in-some-subqueries.html', 'row-subqueries.html', 'group-by-modifiers.html', 'string-comparison-functions.html#operator_$1', 'logical-operators.html#operator_$1', 'control-flow-functions.html#operator_$1', 'arithmetic-functions.html#operator_$1', 'cast-functions.html#operator_$1',
-		'', // keywords without link
-		'comparison-operators.html#function_$1', 'control-flow-functions.html#function_$1', 'string-functions.html#function_$1', 'string-comparison-functions.html#function_$1', 'mathematical-functions.html#function_$1', 'date-and-time-functions.html#function_$1', 'cast-functions.html#function_$1', 'xml-functions.html#function_$1', 'bit-functions.html#function_$1', 'encryption-functions.html#function_$1', 'information-functions.html#function_$1', 'miscellaneous-functions.html#function_$1', 'group-by-functions.html#function_$1',
-		'fulltext-search.html#$1'
-	],
-	sqlite: [ 'http://www.sqlite.org/$key',
-		'lang_$1.html', 'pragma.html', 'lang_createvtab.html', 'lang_transaction.html',
-		'lang_createindex.html', 'lang_createtable.html', 'lang_createtrigger.html', 'lang_createview.html', 'lang_expr.html#$1',
-		'lang_expr.html#corefunctions', 'cvstrac/wiki?p=DateAndTimeFunctions#$1', 'lang_expr.html#aggregatefunctions'
-	],
-	pgsql: [ 'http://www.postgresql.org/docs/8.2/static/$key',
-		'sql-$1.html', 'sql-$1.html', 'sql-alteropclass.html', 'sql-createopclass.html', 'sql-dropopclass.html',
-		'functions-datetime.html', 'functions-info.html', 'functions-logical.html', 'functions-comparison.html', 'functions-matching.html', 'functions-conditional.html', 'functions-subquery.html',
-		'functions-math.html', 'functions-string.html', 'functions-binarystring.html', 'functions-formatting.html', 'functions-datetime.html', 'functions-geometry.html', 'functions-net.html', 'functions-sequence.html', 'functions-array.html', 'functions-aggregate.html', 'functions-srf.html', 'functions-info.html', 'functions-admin.html'
-	],
-	cnf: [ 'http://httpd.apache.org/docs/2.2/mod/$key.html#$1',
-		'beos', 'core', 'mod_actions', 'mod_alias', 'mod_auth_basic', 'mod_auth_digest', 'mod_authn_alias', 'mod_authn_anon', 'mod_authn_dbd', 'mod_authn_dbm', 'mod_authn_default', 'mod_authn_file', 'mod_authnz_ldap', 'mod_authz_dbm', 'mod_authz_default', 'mod_authz_groupfile', 'mod_authz_host', 'mod_authz_owner', 'mod_authz_user', 'mod_autoindex', 'mod_cache', 'mod_cern_meta', 'mod_cgi', 'mod_cgid', 'mod_dav', 'mod_dav_fs', 'mod_dav_lock', 'mod_dbd', 'mod_deflate', 'mod_dir', 'mod_disk_cache', 'mod_dumpio', 'mod_echo', 'mod_env', 'mod_example', 'mod_expires', 'mod_ext_filter', 'mod_file_cache', 'mod_filter', 'mod_headers', 'mod_charset_lite', 'mod_ident', 'mod_imagemap', 'mod_include', 'mod_info', 'mod_isapi', 'mod_ldap', 'mod_log_config', 'mod_log_forensic', 'mod_mem_cache', 'mod_mime', 'mod_mime_magic', 'mod_negotiation', 'mod_nw_ssl', 'mod_proxy', 'mod_rewrite', 'mod_setenvif', 'mod_so', 'mod_speling', 'mod_ssl', 'mod_status', 'mod_substitute', 'mod_suexec', 'mod_userdir', 'mod_usertrack', 'mod_version', 'mod_vhost_alias', 'mpm_common', 'mpm_netware', 'mpm_winnt', 'prefork'
-	],
-	js: [ 'http://developer.mozilla.org/En/$key',
-		'Core_JavaScript_1.5_Reference/Global_Objects/$1',
-		'Core_JavaScript_1.5_Reference/Global_Properties/$1',
-		'Core_JavaScript_1.5_Reference/Global_Functions/$1',
-		'Core_JavaScript_1.5_Reference/Statements/$1',
-		'Core_JavaScript_1.5_Reference/Statements/do...while',
-		'Core_JavaScript_1.5_Reference/Statements/if...else',
-		'Core_JavaScript_1.5_Reference/Statements/try...catch',
-		'Core_JavaScript_1.5_Reference/Operators/Special_Operators/$1_Operator',
-		'DOM/document.$1', 'DOM/element.$1', 'DOM/event.$1', 'DOM/form.$1', 'DOM/table.$1', 'DOM/window.$1',
-		'Core_JavaScript_1.5_Reference/Global_Objects/Array/$1',
-		'Core_JavaScript_1.5_Reference/Global_Objects/Date/$1',
-		'Core_JavaScript_1.5_Reference/Global_Objects/Function/$1',
-		'Core_JavaScript_1.5_Reference/Global_Objects/Number/$1',
-		'Core_JavaScript_1.5_Reference/Global_Objects/RegExp/$1',
-		'Core_JavaScript_1.5_Reference/Global_Objects/String/$1'
-	]
-};
-
-jush.links = {
-	tag: {
-		'interact/forms': /^(button|fieldset|form|input|isindex|label|legend|optgroup|option|select|textarea)$/i,
-		'interact/scripts': /^(noscript)$/i,
-		'present/frames': /^(frame|frameset|iframe|noframes)$/i,
-		'present/graphics': /^(b|basefont|big|center|font|hr|i|s|small|strike|tt|u)$/i,
-		'struct/dirlang': /^(bdo)$/i,
-		'struct/global': /^(address|body|div|h1|h2|h3|h4|h5|h6|head|html|meta|span|title)$/i,
-		'struct/links': /^(a|base|link)$/i,
-		'struct/lists': /^(dd|dir|dl|dt|li|menu|ol|ul)$/i,
-		'struct/objects': /^(applet|area|img|map|object|param)$/i,
-		'struct/tables': /^(caption|col|colgroup|table|tbody|td|tfoot|th|thead|tr)$/i,
-		'struct/text': /^(abbr|acronym|blockquote|br|cite|code|del|dfn|em|ins|kbd|p|pre|q|samp|strong|sub|sup|var)$/i
-	},
-	tag_css: { 'present/styles': /^(style)$/i },
-	tag_js: { 'interact/scripts': /^(script)$/i },
-	att_css: { 'present/styles': /^(style)$/i },
-	att_js: { 'interact/scripts': /^(onblur|onchange|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup|onload|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onreset|onselect|onsubmit|onunload|onunload)$/i },
-	att: {
-		'interact/forms': /^(accept-charset|accept|accesskey|action|align-LEGEND|checked|cols-TEXTAREA|disabled|enctype|for|label-OPTION|label-OPTGROUP|maxlength|method|multiple|name-BUTTON|name-SELECT|name-FORM|name-INPUT|prompt|readonly|readonly|rows-TEXTAREA|selected|size-INPUT|size-SELECT|src|tabindex|type-INPUT|type-BUTTON|value-INPUT|value-OPTION|value-BUTTON)$/i,
-		'interact/scripts': /^(defer|language|src-SCRIPT|type-SCRIPT)$/i,
-		'present/frames': /^(cols-FRAMESET|frameborder|height-IFRAME|longdesc-FRAME|marginheight|marginwidth|name-FRAME|noresize|rows-FRAMESET|scrolling|src-FRAME|target|width-IFRAME)$/i,
-		'present/graphics': /^(align-HR|align|bgcolor|bgcolor|bgcolor|bgcolor|clear|color-FONT|face-FONT|noshade|size-HR|size-FONT|size-BASEFONT|width-HR)$/i,
-		'present/styles': /^(media|media|type-STYLE)$/i,
-		'struct/dirlang': /^(dir|dir-BDO|lang)$/i,
-		'struct/global': /^(alink|background|class|content|http-equiv|id|link|name-META|profile|scheme|text|title|version|vlink)$/i,
-		'struct/links': /^(charset|href|href-BASE|hreflang|name-A|rel|rev|type-A)$/i,
-		'struct/lists': /^(compact|start|type-LI|type-OL|type-UL|value-LI)$/i,
-		'struct/objects': /^(align-IMG|alt|alt|alt|archive-APPLET|archive-OBJECT|border-IMG|classid|code|codebase-OBJECT|codebase-APPLET|codetype|coords|coords|data|declare|height-IMG|height-APPLET|hspace|ismap|longdesc-IMG|name-APPLET|name-IMG|name-MAP|name-PARAM|nohref|object|shape|shape|src-IMG|standby|type-OBJECT|type-PARAM|usemap|value-PARAM|valuetype|vspace|width-IMG|width-APPLET)$/i,
-		'struct/tables': /^(abbr|align-CAPTION|align-TABLE|align-TD|axis|border-TABLE|cellpadding|cellspacing|char|charoff|colspan|frame|headers|height-TH|nowrap|rowspan|rules|scope|span-COL|span-COLGROUP|summary|valign|width-TABLE|width-TH|width-COL|width-COLGROUP)$/i,
-		'struct/text': /^(cite-Q|cite-INS|datetime|width-PRE)$/i
-	},
-	css_val: {
-		'aural': /^(azimuth|cue-after|cue-before|cue|elevation|pause-after|pause-before|pause|pitch-range|pitch|play-during|richness|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|voice-family|volume)$/i,
-		'box': /^(border(?:-top|-right|-bottom|-left)?(?:-color|-style|-width)?|margin(?:-top|-right|-bottom|-left)?|padding(?:-top|-right|-bottom|-left)?)$/i,
-		'colors': /^(background-attachment|background-color|background-image|background-position|background-repeat|background|color)$/i,
-		'fonts': /^(font-family|font-size|font-style|font-variant|font-weight|font)$/i,
-		'generate': /^(content|counter-increment|counter-reset|list-style-image|list-style-position|list-style-type|list-style|quotes)$/i,
-		'page': /^(orphans|page-break-after|page-break-before|page-break-inside|widows)$/i,
-		'tables': /^(border-collapse|border-spacing|caption-side|empty-cells|table-layout)$/i,
-		'text': /^(letter-spacing|text-align|text-decoration|text-indent|text-transform|white-space|word-spacing)$/i,
-		'ui': /^(cursor|outline-color|outline-style|outline-width|outline)$/i,
-		'visudet': /^(height|line-height|max-height|max-width|min-height|min-width|vertical-align|width)$/i,
-		'visufx': /^(clip|overflow|visibility)$/i,
-		'visuren': /^(bottom|clear|direction|display|float|left|position|right|top|unicode-bidi|z-index)$/i
-	},
-	css_at: {
-		'page.html#page-box': /^page$/i,
-		'media.html#at-media-rule': /^media$/i,
-		'cascade.html#at-import': /^import$/i
-	},
-	js_write: { 'document': /^(write|writeln)$/ },
-	php_new: { 'language.oop5.basic#language.oop5.basic': /^new$/i },
-	php_sql: { 'function': new RegExp('^' + jush.sql_function + '$', 'i') },
-	php_sqlite: { 'function': new RegExp('^' + jush.sqlite_function + '$', 'i') },
-	php_pgsql: { 'function': new RegExp('^' + jush.pgsql_function + '$', 'i') },
-	php_phpini: { 'function': /^(ini_get|ini_set)$/i },
-	php_echo: { 'function': /^(echo|print)$/i },
-	php_halt: { 'function': /^__halt_compiler$/i },
-	cnf_php: { 'configuration.file': /.+/ },
-	cnf_phpini: { 'configuration.changes.apache': /.+/ }
-};
-
-// last () is used as delimiter
-jush.links2 = {
-	php: /\b((?:exit|die|return|(?:include|require)(?:_once)?|(end(?:for|foreach|if|switch|while|declare))|(break|continue|declare|else|elseif|for|foreach|if|switch|while|goto)|(do)|(as)|(case|default)|(function)|(var)|(__(?:CLASS|FILE|FUNCTION|LINE|METHOD|DIR|NAMESPACE)__)|(catch|throw|try)|(abstract|final)|(class|extends)|(clone)|(const)|(implements|interface)|(private|protected|public)|(and|x?or)|(global|static)|(namespace|use))\b|((?:a(?:cosh?|ddc?slashes|ggregat(?:e(?:_(?:methods(?:_by_(?:list|regexp))?|properties(?:_by_(?:list|regexp))?|info))?|ion_info)|p(?:ache_(?:get(?:_(?:modules|version)|env)|re(?:s(?:et_timeout|ponse_headers)|quest_headers)|(?:child_termina|no)te|lookup_uri|setenv)|d_(?:c(?:(?:allstac|lun|roa)k|ontinue)|dump_(?:function_table|(?:persistent|regular)_resources)|set_(?:s(?:ession(?:_trace)?|ocket_session_trace)|pprof_trace)|breakpoint|echo|get_active_symbols))|r(?:ray(?:_(?:c(?:h(?:ange_key_case|unk)|o(?:mbine|unt_values))|diff(?:_(?:u(?:assoc|key)|assoc|key))?|f(?:il(?:l|ter)|lip)|intersect(?:_(?:u(?:assoc|key)|assoc|key))?|key(?:_exist)?s|m(?:erge(?:_recursive)?|ap|ultisort)|p(?:ad|op|ush)|r(?:e(?:duc|vers)e|and)|s(?:earch|hift|p?lice|um)|u(?:diff(?:_u?assoc)?|intersect(?:_u?assoc)?|n(?:ique|shift))|walk(?:_recursive)?|values))?|sort)|s(?:inh?|pell_(?:check(?:_raw)?|new|suggest)|sert(?:_options)?|cii2ebcdic|ort)|tan[2h]?|bs)|b(?:ase(?:64_(?:de|en)code|_convert|name)|c(?:m(?:od|ul)|ompiler_(?:write_(?:f(?:unction(?:s_from_file)?|ile|ooter)|c(?:lass|onstant)|(?:exe_foot|head)er)|load(?:_exe)?|parse_class|read)|pow(?:mod)?|s(?:cale|qrt|ub)|add|comp|div)|in(?:d(?:_textdomain_codeset|ec|textdomain)|2hex)|z(?:c(?:lose|ompress)|err(?:no|(?:o|st)r)|decompress|flush|open|read|write))|c(?:al(?:_(?:days_in_month|(?:from|to)_jd|info)|l_user_(?:func(?:_array)?|method(?:_array)?))|cvs_(?:a(?:dd|uth)|co(?:mmand|unt)|d(?:elet|on)e|re(?:port|turn|verse)|s(?:ale|tatus)|init|lookup|new|textvalue|void)|h(?:eckd(?:ate|nsrr)|o(?:p|wn)|r(?:oot)?|dir|grp|mod|unk_split)|l(?:ass(?:_(?:exis|(?:implem|par)en)ts|kit_(?:method_(?:re(?:defin|mov|nam)e|add|copy)|import))|ose(?:dir|log)|earstatcache)|o(?:m(?:_(?:get(?:_active_object)?|i(?:nvoke|senum)|load(?:_typelib)?|pr(?:op(?:[gs]e|pu)t|int_typeinfo)|addref|create_guid|event_sink|message_pump|release|set)|pact)?|n(?:nection_(?:aborted|status|timeout)|vert_(?:uu(?:de|en)code|cyr_string)|stant)|sh?|unt(?:_chars)?|py)|pdf_(?:a(?:dd_(?:annotation|outline)|rc)|c(?:l(?:ose(?:path(?:_(?:fill_)?stroke)?)?|ip)|ircle|ontinue_text|urveto)|fi(?:ll(?:_stroke)?|nalize(?:_page)?)|o(?:pen|utput_buffer)|p(?:age_init|lace_inline_image)|r(?:e(?:ct|store)|otate(?:_text)?|(?:lin|mov)eto)|s(?:ave(?:_to_file)?|et(?:_(?:c(?:har_spacing|reator|urrent_page)|font(?:_(?:directories|map_file))?|t(?:ext_(?:r(?:endering|ise)|matrix|pos)|itle)|action_url|(?:horiz_scal|lead|word_spac)ing|(?:keyword|viewer_preference)s|page_animation|subject)|gray(?:_(?:fill|stroke))?|line(?:cap|join|width)|rgbcolor(?:_(?:fill|stroke))?|dash|(?:fla|miterlimi)t)|how(?:_xy)?|tr(?:ingwidth|oke)|cale)|t(?:ext|ranslate)|(?:begin|end)_text|global_set_document_limits|import_jpeg|(?:lin|mov)eto|newpath)|r(?:ack_(?:c(?:heck|losedict)|getlastmessage|opendict)|c32|eate_function|ypt)|type_(?:al(?:num|pha)|p(?:rin|unc)t|cntrl|x?digit|graph|(?:low|upp)er|space)|ur(?:l_(?:c(?:los|opy_handl)e|e(?:rr(?:no|or)|xec)|multi_(?:in(?:fo_read|it)|(?:(?:add|remove)_handl|clos)e|exec|(?:getconten|selec)t)|getinfo|(?:ini|setop)t|version)|rent)|y(?:bercash_(?:base64_(?:de|en)code|(?:de|en)cr)|rus_(?:c(?:lose|onnect)|authenticate|(?:un)?bind|query))|eil)|d(?:ate(?:_sun(?:rise|set))?|b(?:a(?:_(?:f(?:etch|irstkey)|op(?:en|timize)|(?:clos|delet|replac)e|(?:exist|handler)s|(?:inser|key_spli|lis)t|nextkey|popen|sync)|se_(?:c(?:los|reat)e|get_(?:record(?:_with_names)?|header_info)|num(?:fiel|recor)ds|(?:add|(?:delet|replac)e)_record|open|pack))|m(?:f(?:etch|irstkey)|(?:clos|delet|replac)e|exists|insert|nextkey|open)|plus_(?:a(?:dd|ql)|c(?:(?:hdi|ur)r|lose)|err(?:code|no)|f(?:i(?:nd|rst)|ree(?:(?:all|r)locks|lock)|lush)|get(?:lock|unique)|l(?:ast|ockrel)|r(?:c(?:r(?:t(?:exact|like)|eate)|hperm)|es(?:olve|torepos)|keys|open|query|rename|secindex|unlink|zap)|s(?:etindex(?:bynumber)?|avepos|ql)|t(?:cl|remove)|u(?:n(?:do(?:prepare)?|lockrel|select)|pdate)|x(?:un)?lockrel|info|next|open|prev)|x_(?:c(?:o(?:mpare|nnect)|lose)|e(?:rror|scape_string)|fetch_row|query|sort)|list)|cn?gettext|e(?:bug(?:_(?:(?:print_)?backtrace|zval_dump)|ger_o(?:ff|n))|c(?:bin|hex|oct)|fine(?:_syslog_variables|d)?|aggregate|g2rad)|i(?:o_(?:s(?:eek|tat)|t(?:csetattr|runcate)|(?:clos|writ)e|fcntl|open|read)|r(?:name)?|sk(?:_(?:free|total)_space|freespace))|n(?:s_(?:get_(?:mx|record)|check_record)|gettext)|o(?:m(?:xml_(?:open_(?:file|mem)|x(?:slt_stylesheet(?:_(?:doc|file))?|mltree)|new_doc|version)|_import_simplexml)|tnet(?:_load)?|ubleval)|gettext|l)|e(?:a(?:ster_da(?:te|ys)|ch)|r(?:eg(?:i(?:_replace)?|_replace)?|ror_(?:lo|reportin)g)|scapeshell(?:arg|cmd)|x(?:if_(?:t(?:agname|humbnail)|imagetype|read_data)|p(?:lode|m1)?|t(?:ension_loaded|ract)|ec)|bcdic2ascii|mpty|nd|val|zmlm_hash)|f(?:am_(?:c(?:ancel_monitor|lose)|monitor_(?:collection|directory|file)|next_event|open|pending|(?:resume|suspend)_monitor)|bsql_(?:a(?:ffected_rows|utocommit)|c(?:lo(?:b_siz|s)e|o(?:mmi|nnec)t|reate_(?:[bc]lo|d)b|hange_user)|d(?:ata(?:base(?:_password)?|_seek)|b_(?:query|status)|rop_db)|err(?:no|or)|f(?:etch_(?:a(?:rray|ssoc)|field|lengths|object|row)|ield_(?:t(?:abl|yp)e|flags|len|name|seek)|ree_result)|list_(?:db|field|table)s|n(?:um_(?:field|row)s|ext_result)|p(?:assword|connect)|r(?:e(?:ad_[bc]lob|sult)|ollback)|s(?:e(?:t_(?:lob_mode|password|transaction)|lect_db)|t(?:art|op)_db)|(?:blob_siz|(?:host|table|user)nam)e|get_autostart_info|insert_id|query|warnings)|df_(?:add_(?:doc_javascript|template)|c(?:los|reat)e|e(?:rr(?:no|or)|num_values)|get_(?:a(?:p|ttachment)|f(?:ile|lags)|v(?:alue|ersion)|encoding|opt|status)|open(?:_string)?|s(?:ave(?:_string)?|et_(?:f(?:ile|lags)|o(?:n_import_javascri)?pt|s(?:tatus|ubmit_form_action)|v(?:alue|ersion)|ap|encoding|javascript_action|target_frame))|header|next_field_name|remove_item)|get(?:c(?:sv)?|ss?)|ile(?:_(?:exis|(?:ge|pu)t_conten)ts|p(?:ro(?:_(?:field(?:count|(?:nam|typ)e|width)|r(?:etrieve|owcount)))?|erms)|(?:[acm]tim|inod|siz|typ)e|group|owner)?|l(?:o(?:atval|ck|or)|ush)|p(?:ut(?:csv|s)|assthru|rintf)|r(?:e(?:a|nchtoj)d|ibidi_log2vis)|s(?:canf|eek|ockopen|tat)|t(?:p_(?:c(?:h(?:dir|mod)|dup|lose|onnect)|f(?:ge|pu)t|get(?:_option)?|m(?:dtm|kdir)|n(?:b_(?:f(?:ge|pu)t|continue|(?:ge|pu)t)|list)|p(?:asv|ut|wd)|r(?:aw(?:list)?|ename|mdir)|s(?:i[tz]e|et_option|sl_connect|ystype)|(?:allo|exe)c|delete|login|quit)|ell|ok|runcate)|unc(?:_(?:get_args?|num_args)|tion_exists)|(?:clos|writ)e|eof|(?:flus|nmatc)h|mod|open)|g(?:et(?:_(?:c(?:lass(?:_(?:method|var)s)?|(?:fg_va|urrent_use)r)|de(?:clared_(?:class|interfac)es|fined_(?:constant|function|var)s)|h(?:eaders|tml_translation_table)|include(?:_path|d_files)|m(?:agic_quotes_(?:gpc|runtime)|eta_tags)|re(?:quired_files|source_type)|browser|(?:extension_func|loaded_extension|object_var|parent_clas)s)|hostby(?:namel?|addr)|m(?:y(?:[gpu]id|inode)|xrr)|protobyn(?:ame|umber)|r(?:andmax|usage)|servby(?:name|port)|t(?:ext|imeofday|ype)|allheaders|(?:cw|lastmo)d|(?:dat|imagesiz)e|env|opt)|m(?:p_(?:a(?:bs|[dn]d)|c(?:lrbit|mp|om)|div(?:_(?:qr?|r)|exact)?|gcd(?:ext)?|in(?:(?:i|ver)t|tval)|m(?:od|ul)|p(?:o(?:wm?|pcount)|(?:erfect_squar|rob_prim)e)|s(?:can[01]|qrt(?:rem)?|etbit|ign|trval|ub)|(?:fac|hamdis)t|jacobi|legendre|neg|x?or|random)|(?:dat|(?:mk|strf)tim)e)|z(?:c(?:lose|ompress)|e(?:ncode|of)|get(?:ss?|c)|p(?:assthru|uts)|re(?:a|win)d|(?:(?:(?:de|in)fla|wri)t|fil)e|open|seek|tell|uncompress)|d_info|lob|regoriantojd)|h(?:e(?:ader(?:s_(?:lis|sen)t)?|brevc?|xdec)|ighlight_(?:file|string)|t(?:ml(?:_entity_decode|(?:entitie|specialchar)s)|tp_build_query)|w(?:_(?:a(?:pi_(?:attribute|(?:conten|objec)t)|rray2objrec)|c(?:h(?:ildren(?:obj)?|angeobject)|onnect(?:ion_info)?|lose|p)|d(?:oc(?:byanchor(?:obj)?|ument_(?:s(?:etcontent|ize)|attributes|bodytag|content))|eleteobject|ummy)|e(?:rror(?:msg)?|dittext)|get(?:an(?:chors(?:obj)?|dlock)|child(?:coll(?:obj)?|doccoll(?:obj)?)|object(?:byquery(?:coll(?:obj)?|obj)?)?|parents(?:obj)?|re(?:mote(?:children)?|llink)|srcbydestobj|text|username)|i(?:n(?:s(?:ert(?:anchors|(?:documen|objec)t)|coll|doc)|collections|fo)|dentify)|m(?:apid|odifyobject|v)|o(?:bjrec2array|utput_document)|p(?:connec|ipedocumen)t|s(?:etlinkroo|ta)t|(?:(?:free|new)_documen|roo)t|unlock|who)|api_hgcsp)|ypot)|i(?:base_(?:a(?:dd_user|ffected_rows)|b(?:lob_(?:c(?:ancel|(?:los|reat)e)|i(?:mport|nfo)|add|echo|get|open)|ackup)|c(?:o(?:mmit(?:_ret)?|nnect)|lose)|d(?:b_info|elete_user|rop_db)|e(?:rr(?:code|msg)|xecute)|f(?:etch_(?:assoc|object|row)|ree_(?:event_handler|query|result)|ield_info)|m(?:aintain_db|odify_user)|n(?:um_(?:field|param)s|ame_result)|p(?:aram_info|connect|repare)|r(?:ollback(?:_ret)?|estore)|se(?:rv(?:ice_(?:at|de)tach|er_info)|t_event_handler)|t(?:imefmt|rans)|gen_id|query|wait_event)|conv(?:_(?:mime_(?:decode(?:_headers)?|encode)|s(?:tr(?:len|r?pos)|et_encoding|ubstr)|get_encoding))?|d(?:3_(?:get_(?:frame_(?:long|short)_name|genre_(?:id|list|name)|tag|version)|(?:remove|set)_tag)|ate)|fx(?:_(?:b(?:lobinfile_mode|yteasvarchar)|c(?:o(?:nnect|py_blob)|reate_(?:blob|char)|lose)|error(?:msg)?|f(?:ield(?:properti|typ)es|ree_(?:blob|char|result)|etch_row)|get(?:_(?:blob|char)|sqlca)|nu(?:m_(?:field|row)s|llformat)|p(?:connect|repare)|update_(?:blob|char)|affected_rows|do|htmltbl_result|query|textasvarchar)|us_(?:c(?:los|reat)e_slob|(?:(?:fre|writ)e|open|read|seek|tell)_slob))|m(?:a(?:ge(?:_type_to_(?:extension|mime_type)|a(?:lphablending|ntialias|rc)|c(?:har(?:up)?|o(?:lor(?:a(?:llocate(?:alpha)?|t)|closest(?:alpha|hwb)?|exact(?:alpha)?|resolve(?:alpha)?|s(?:et|forindex|total)|deallocate|match|transparent)|py(?:merge(?:gray)?|res(?:ampl|iz)ed)?)|reate(?:from(?:g(?:d(?:2(?:part)?)?|if)|x[bp]m|(?:jpe|(?:p|stri)n)g|wbmp)|truecolor)?)|d(?:ashedline|estroy)|f(?:il(?:l(?:ed(?:arc|(?:ellips|rectangl)e|polygon)|toborder)?|ter)|ont(?:height|width)|t(?:bbox|text))|g(?:d2?|ammacorrect|if)|i(?:nterlace|struecolor)|l(?:(?:ayereffec|oadfon)t|ine)|p(?:s(?:e(?:ncode|xtend)font|bbox|(?:(?:copy|free|load|slant)fon|tex)t)|alettecopy|ng|olygon)|r(?:ectangl|otat)e|s(?:et(?:t(?:hickness|ile)|brush|pixel|style)|tring(?:up)?|avealpha|[xy])|t(?:tf(?:bbox|text)|ruecolortopalette|ypes)|2?wbmp|ellipse|jpeg|xbm)|p_(?:a(?:lerts|ppend)|b(?:ody(?:struct)?|ase64|inary)|c(?:l(?:earflag_full|ose)|heck|reatemailbox)|delete(?:mailbox)?|e(?:rrors|xpunge)|fetch(?:_overview|body|header|structure)|get(?:_quota(?:root)?|acl|mailboxes|subscribed)|header(?:info|s)?|l(?:ist(?:s(?:can|ubscribed)|mailbox)?|ast_error|sub)|m(?:ail(?:_(?:co(?:mpose|py)|move)|boxmsginfo)?|ime_header_decode|sgno)|num_(?:msg|recent)|r(?:e(?:namemailbox|open)|fc822_(?:parse_(?:adrlist|headers)|write_address))|s(?:e(?:t(?:_quota|(?:ac|flag_ful)l)|arch)|canmailbox|ort|tatus|ubscribe)|t(?:hread|imeout)|u(?:n(?:delet|subscrib)e|tf(?:7_(?:de|en)code|8)|id)|(?:8bi|qprin)t|open|ping))|p(?:lode|ort_request_variables))|n(?:et_(?:ntop|pton)|gres_(?:c(?:o(?:mmi|nnec)t|lose)|f(?:etch_(?:array|object|row)|ield_(?:n(?:am|ullabl)e|length|precision|(?:scal|typ)e))|num_(?:field|row)s|(?:autocommi|pconnec)t|query|rollback)|i_(?:alter|get_all|restore)|t(?:erface_exists|val)|_array)|p(?:tc(?:embed|parse)|2long)|rcg_(?:i(?:gnore_(?:add|del)|(?:nvit|s_conn_aliv)e)|l(?:ist|(?:ookup_format_message|user)s)|n(?:ick(?:name_(?:un)?escape)?|ames|otice)|p(?:ar|connec)t|set_(?:current|(?:fil|on_di)e)|who(?:is)?|(?:(?:channel_m|html_enc)od|get_usernam)e|disconnect|(?:eval_ecmascript_param|register_format_message)s|(?:fetch_error_)?msg|join|kick|oper|topic)|s(?:_(?:a(?:rray)?|d(?:ir|ouble)|f(?:i(?:l|nit)e|loat)|in(?:t(?:eger)?|finite)|l(?:ink|ong)|n(?:u(?:ll|meric)|an)|re(?:a(?:dable|l)|source)|s(?:calar|oap_fault|tring|ubclass_of)|write?able|bool|(?:(?:call|execut)ab|uploaded_fi)le|object)|set)|(?:gnore_user_abor|terator_coun)t)|j(?:ava_last_exception_(?:clear|get)|d(?:to(?:j(?:ewish|ulian)|french|gregorian|unix)|dayofweek|monthname)|(?:ewish|ulian)tojd|oin|peg2wbmp)|k(?:ey|r?sort)|l(?:dap_(?:c(?:o(?:mpare|nnect|unt_entries)|lose)|d(?:elete|n2ufn)|e(?:rr(?:(?:2st|o)r|no)|xplode_dn)|f(?:irst_(?:(?:attribut|referenc)e|entry)|ree_result)|get_(?:values(?:_len)?|(?:attribut|entri)es|(?:d|optio)n)|mod(?:_(?:add|del|replace)|ify)|next_(?:(?:attribut|referenc)e|entry)|parse_re(?:ference|sult)|re(?:ad|name)|s(?:e(?:t_(?:option|rebind_proc)|arch)|asl_bind|ort|tart_tls)|8859_to_t61|(?:ad|(?:un)?bin)d|list|t61_to_8859)|i(?:nk(?:info)?|st)|o(?:cal(?:econv|time)|g(?:1[0p])?|ng2ip)|zf_(?:(?:de)?compress|optimized_for)|cg_value|evenshtein|stat|trim)|m(?:a(?:il(?:parse_(?:msg_(?:extract_part(?:_file)?|get_(?:part(?:_data)?|structure)|parse(?:_file)?|(?:creat|fre)e)|determine_best_xfer_encoding|rfc822_parse_addresses|stream_encode|uudecode_all))?|x)|b_(?:convert_(?:case|encoding|kana|variables)|de(?:code_(?:mimeheader|numericentity)|tect_(?:encoding|order))|e(?:ncode_(?:mimeheader|numericentity)|reg(?:_(?:search(?:_(?:get(?:po|reg)s|init|(?:(?:set)?po|reg)s))?|match|replace)|i(?:_replace)?)?)|http_(?:in|out)put|l(?:anguage|ist_encodings)|p(?:arse_str|referred_mime_name)|regex_(?:encoding|set_options)|s(?:tr(?:to(?:low|upp)er|cut|(?:im)?width|len|r?pos)|ubst(?:r(?:_count)?|itute_character)|end_mail|plit)|get_info|internal_encoding|output_handler)|c(?:al_(?:c(?:lose|reate_calendar)|d(?:a(?:te_(?:compare|valid)|y(?:_of_(?:week|year)|s_in_month))|elete_(?:calendar|event))|e(?:vent_(?:set_(?:c(?:ategory|lass)|recur_(?:monthly_[mw]day|(?:dai|week|year)ly|none)|alarm|description|end|start|title)|add_attribute|init)|xpunge)|fetch_(?:current_stream_)?event|list_(?:alarm|event)s|re(?:name_calendar|open)|s(?:nooze|tore_event)|append_event|(?:is_leap|week_of)_year|next_recurrence|p?open|time_valid)|rypt_(?:c(?:bc|fb|reate_iv)|e(?:nc(?:_(?:get_(?:(?:(?:algorithm|mode)s_nam|(?:block|iv|key)_siz)e|supported_key_sizes)|is_block_(?:algorithm(?:_mode)?|mode)|self_test)|rypt)|cb)|ge(?:neric(?:_(?:(?:de)?init|end))?|t_(?:(?:block|iv|key)_siz|cipher_nam)e)|list_(?:algorithm|mode)s|module_(?:get_(?:algo_(?:block|key)_size|supported_key_sizes)|is_block_(?:algorithm(?:_mode)?|mode)|close|open|self_test)|decrypt|ofb)|ve_(?:adduser(?:arg)?|c(?:h(?:eckstatus|(?:k|ng)pwd)|o(?:nnect(?:ionerror)?|mpleteauthorizations))|d(?:e(?:l(?:ete(?:response|trans|usersetup)|user)|stroy(?:conn|engine))|isableuser)|e(?:dit|nable)user|g(?:et(?:c(?:ell(?:bynum)?|ommadelimited)|user(?:arg|param)|header)|[fu]t|l)|i(?:nit(?:conn|engine|usersetup)|scommadelimited)|list(?:stat|user)s|m(?:axconntimeout|onitor)|num(?:column|row)s|p(?:reauth(?:completion)?|arsecommadelimited|ing)|re(?:turn(?:code|status)?|sponseparam)|s(?:et(?:ssl(?:_files)?|t(?:imeout|le)|blocking|dropfile|ip)|ale)|t(?:ext_(?:c(?:ode|v)|avs)|rans(?:action(?:a(?:uth|vs)|i(?:d|tem)|batch|cv|(?:ssen|tex)t)|inqueue|new|param|send))|u(?:b|wait)|v(?:erify(?:connection|sslcert)|oid)|bt|(?:forc|overrid)e|qc))|d(?:5(?:_file)?|ecrypt_generic)|e(?:m(?:cache_debug|ory_get_usage)|t(?:aphone|hod_exists))|hash(?:_(?:get_(?:block_siz|hash_nam)e|count|keygen_s2k))?|i(?:n(?:g_(?:set(?:cubicthreshold|scale)|useswfversion))?|(?:crotim|me_content_typ)e)|k(?:dir|time)|o(?:ney_format|ve_uploaded_file)|s(?:ession_(?:c(?:o(?:nnec|un)t|reate)|d(?:estroy|isconnect)|get(?:_(?:array|data))?|l(?:ist(?:var)?|ock)|set(?:_(?:array|data))?|un(?:iq|lock)|find|inc|plugin|randstr|timeout)|g_(?:re(?:ceiv|move_queu)e|s(?:e(?:nd|t_queue)|tat_queue)|get_queue)|ql(?:_(?:c(?:reate_?db|lose|onnect)|d(?:b(?:_query|name)|ata_seek|rop_db)|f(?:etch_(?:array|field|object|row)|ield(?:_(?:t(?:abl|yp)e|flags|len|name|seek)|t(?:abl|yp)e|flags|len|name)|ree_result)|list_(?:db|field|table)s|num(?:_(?:field|row)s|(?:field|row)s)|re(?:gcase|sult)|affected_rows|error|pconnect|query|select_db|tablename))?|sql_(?:c(?:lose|onnect)|f(?:etch_(?:a(?:rray|ssoc)|batch|field|object|row)|ield_(?:length|(?:nam|typ)e|seek)|ree_(?:resul|statemen)t)|g(?:et_last_message|uid_string)|min_(?:error|message)_severity|n(?:um_(?:field|row)s|ext_result)|r(?:esult|ows_affected)|bind|data_seek|execute|(?:ini|pconnec)t|query|select_db))|t_(?:getrandmax|s?rand)|uscat_(?:g(?:et|ive)|setup(?:_net)?|close)|ysql(?:_(?:c(?:l(?:ient_encoding|ose)|hange_user|onnect|reate_db)|d(?:ata_seek|b_name|rop_db)|e(?:rr(?:no|or)|scape_string)|f(?:etch_(?:a(?:rray|ssoc)|field|lengths|object|row)|ield_(?:t(?:abl|yp)e|flags|len|name|seek)|ree_result)|get_(?:(?:clien|hos)t|proto|server)_info|in(?:fo|sert_id)|list_(?:db|field|(?:process|tabl)e)s|num_(?:field|row)s|p(?:connect|ing)|re(?:al_escape_string|sult)|s(?:elect_db|tat)|t(?:ablename|hread_id)|affected_rows)|i_(?:a(?:ffected_rows|utocommit)|bind_(?:param|result)|c(?:ha(?:nge_user|racter_set_name)|l(?:ient_encoding|ose)|o(?:nnect(?:_err(?:no|or))?|mmit))|d(?:isable_r(?:eads_from_master|pl_parse)|ata_seek|ebug|ump_debug_info)|e(?:nable_r(?:eads_from_master|pl_parse)|rr(?:no|or)|mbedded_connect|scape_string|xecute)|f(?:etch(?:_(?:a(?:rray|ssoc)|field(?:_direct|s)?|lengths|object|row))?|ield_(?:count|seek|tell)|ree_result)|get_(?:client_(?:info|version)|server_(?:info|version)|(?:host|proto)_info|metadata)|in(?:fo|it|sert_id)|n(?:um_(?:field|row)s|ext_result)|p(?:aram_count|ing|repare)|r(?:e(?:al_(?:connect|escape_string)|port)|pl_p(?:arse_enabled|robe)|ollback)|s(?:e(?:rver_(?:end|init)|lect_db|nd_long_data|t_opt)|t(?:mt_(?:bind_(?:param|result)|e(?:rr(?:no|or)|xecute)|f(?:etch|ree_result)|res(?:et|ult_metadata)|s(?:end_long_data|qlstate|tore_result)|(?:affected|num)_rows|close|data_seek|(?:ini|param_coun)t)|(?:a|ore_resul)t)|qlstate|sl_set)|thread_(?:id|safe)|kill|(?:more_result|option)s|(?:use_resul|warning_coun)t)))|n(?:at(?:case)?sort|curses_(?:a(?:dd(?:ch(?:n?str)?|n?str)|ttr(?:o(?:ff|n)|set)|ssume_default_colors)|b(?:kgd(?:set)?|o(?:rder|ttom_panel)|audrate|eep)|c(?:l(?:rto(?:bot|eol)|ear)|olor_(?:conten|se)t|an_change_color|break|urs_set)|d(?:e(?:f(?:_(?:prog|shell)_mode|ine_key)|l(?:_panel|ay_output|ch|(?:etel|wi)n))|oupdate)|e(?:cho(?:char)?|rase(?:char)?|nd)|f(?:l(?:ash|ushinp)|ilter)|get(?:m(?:axyx|ouse)|ch|yx)|h(?:a(?:s_(?:i[cl]|colors|key)|lfdelay)|ide_panel|line)|i(?:n(?:it(?:_(?:colo|pai)r)?|s(?:ch|(?:del|ert)ln|s?tr)|ch)|sendwin)|k(?:ey(?:ok|pad)|illchar)|m(?:o(?:use(?:_trafo|interval|mask)|ve(?:_panel)?)|v(?:add(?:ch(?:n?str)?|n?str)|(?:cu|waddst)r|(?:del|get|in)ch|[hv]line)|eta)|n(?:ew(?:_panel|pad|win)|o(?:cbreak|echo|nl|qiflush|raw)|apms|l)|p(?:a(?:nel_(?:above|(?:bel|wind)ow)|ir_content)|(?:nout)?refresh|utp)|r(?:e(?:set(?:_(?:prog|shell)_mode|ty)|fresh|place_panel)|aw)|s(?:cr(?:_(?:dump|(?:ini|se)t|restore)|l)|lk_(?:attr(?:o(?:ff|n)|set)?|c(?:lea|olo)r|re(?:fresh|store)|(?:ini|se)t|(?:noutrefres|touc)h)|ta(?:nd(?:end|out)|rt_color)|avetty|how_panel)|t(?:erm(?:attrs|name)|imeout|op_panel|ypeahead)|u(?:nget(?:ch|mouse)|se_(?:e(?:nv|xtended_names)|default_colors)|pdate_panels)|v(?:idattr|line)|w(?:a(?:dd(?:ch|str)|ttr(?:o(?:ff|n)|set))|c(?:lear|olor_set)|mo(?:use_trafo|ve)|stand(?:end|out)|border|(?:eras|[hv]lin)e|(?:getc|(?:nout)?refres)h)|longname|qiflush)|l(?:2br|_langinfo)|otes_(?:c(?:reate_(?:db|note)|opy_db)|mark_(?:un)?read|body|drop_db|(?:find_no|nav_crea)te|header_info|list_msgs|search|unread|version)|sapi_(?:re(?:quest|sponse)_headers|virtual)|(?:(?:gett)?ex|umber_forma)t)|o(?:b_(?:end_(?:clean|flush)|g(?:et_(?:c(?:lean|ontents)|le(?:ngth|vel)|flush|status)|zhandler)|i(?:conv_handler|mplicit_flush)|clean|flush|list_handlers|start|tidyhandler)|c(?:i(?:_(?:c(?:o(?:mmi|nnec)t|ancel|lose)|e(?:rror|xecute)|f(?:etch(?:_(?:a(?:ll|rray|ssoc)|object|row))?|ield_(?:s(?:cal|iz)e|type(?:_raw)?|is_null|name|precision)|ree_statement)|lob_(?:copy|is_equal)|n(?:ew_(?:c(?:o(?:llection|nnect)|ursor)|descriptor)|um_(?:field|row)s)|p(?:a(?:rs|ssword_chang)e|connect)|r(?:esult|ollback)|s(?:e(?:rver_version|t_prefetch)|tatement_type)|(?:bind|define)_by_name|internal_debug)|c(?:o(?:l(?:l(?:a(?:ssign(?:elem)?|ppend)|(?:getele|tri)m|max|size)|umn(?:s(?:cal|iz)e|type(?:raw)?|isnull|name|precision))|mmit)|ancel|loselob)|e(?:rror|xecute)|f(?:etch(?:into|statement)?|ree(?:c(?:ollection|ursor)|desc|statement))|lo(?:go(?:ff|n)|adlob)|n(?:ew(?:c(?:ollection|ursor)|descriptor)|logon|umcols)|p(?:arse|logon)|r(?:o(?:llback|wcount)|esult)|s(?:avelob(?:file)?|e(?:rverversion|tprefetch)|tatementtype)|write(?:lobtofile|temporarylob)|(?:bind|define)byname|internaldebug)|tdec)|dbc_(?:c(?:lose(?:_all)?|o(?:lumn(?:privilege)?s|(?:mmi|nnec)t)|ursor)|d(?:ata_source|o)|e(?:rror(?:msg)?|xec(?:ute)?)|f(?:etch_(?:array|into|object|row)|ield_(?:n(?:ame|um)|(?:le|precisio)n|(?:scal|typ)e)|oreignkeys|ree_result)|n(?:um_(?:field|row)s|ext_result)|p(?:r(?:ocedure(?:column)?s|epare|imarykeys)|connect)|r(?:esult(?:_all)?|ollback)|s(?:etoption|(?:pecialcolumn|tatistic)s)|table(?:privilege)?s|autocommit|binmode|gettypeinfo|longreadlen)|pen(?:al_(?:buffer_(?:d(?:ata|estroy)|create|get|loadwav)|context_(?:c(?:reate|urrent)|destroy|process|suspend)|device_(?:close|open)|listener_[gs]et|s(?:ource_(?:p(?:ause|lay)|s(?:et|top)|create|destroy|get|rewind)|tream))|ssl_(?:csr_(?:export(?:_to_file)?|new|sign)|get_p(?:rivate|ublic)key|p(?:k(?:cs7_(?:(?:de|en)crypt|sign|verify)|ey_(?:export(?:_to_file)?|get_p(?:rivate|ublic)|new))|rivate_(?:de|en)crypt|ublic_(?:de|en)crypt)|s(?:eal|ign)|x509_(?:check(?:_private_key|purpose)|export(?:_to_file)?|(?:fre|pars)e|read)|error_string|(?:free_ke|verif)y|open)|dir|log)|r(?:a_(?:c(?:o(?:lumn(?:nam|siz|typ)e|mmit(?:o(?:ff|n))?)|lose)|e(?:rror(?:code)?|xec)|fetch(?:_into)?|logo(?:ff|n)|num(?:col|row)s|p(?:arse|logon)|bind|do|(?:getcolum|ope)n|rollback)|d)|utput_(?:add_rewrite_var|reset_rewrite_vars)|v(?:er(?:load|ride_function)|rimos_(?:c(?:o(?:mmi|nnec)t|lose|ursor)|exec(?:ute)?|f(?:etch_(?:into|row)|ield_(?:n(?:ame|um)|len|type)|ree_result)|num_(?:field|row)s|r(?:esult(?:_all)?|ollback)|longreadlen|prepare)))|p(?:a(?:rse(?:_(?:ini_file|str|url)|kit_(?:compile_(?:file|string)|func_arginfo))|ck|ssthru|thinfo)|c(?:ntl_(?:s(?:etpriority|ignal)|w(?:ait(?:pid)?|if(?:s(?:ignal|topp)ed|exited)|exitstatus|(?:stop|term)sig)|alarm|exec|fork|getpriority)|lose)|df_(?:a(?:dd_(?:l(?:aunch|ocal)link|annotation|(?:bookmar|(?:pdf|web)lin)k|(?:not|outlin)e|thumbnail)|rcn?|ttach_file)|begin_(?:pa(?:ge|ttern)|template)|c(?:l(?:ose(?:_(?:pdi(?:_page)?|image)|path(?:_(?:fill_)?stroke)?)?|ip)|on(?:ca|tinue_tex)t|ircle|urveto)|end(?:_(?:pa(?:ge|ttern)|template)|path)|fi(?:ll(?:_stroke)?|ndfont)|get_(?:font(?:(?:nam|siz)e)?|image_(?:height|width)|m(?:aj|in)orversion|p(?:di_(?:parameter|value)|arameter)|buffer|value)|m(?:akespotcolor|oveto)|open(?:_(?:image(?:_file)?|p(?:di(?:_page)?|ng)|ccitt|(?:fil|memory_imag)e|(?:gi|tif)f|jpeg))?|place_(?:im|pdi_p)age|r(?:e(?:ct|store)|otate)|s(?:et(?:_(?:border_(?:color|dash|style)|info(?:_(?:(?:auth|creat)or|keywords|subject|title))?|text_(?:r(?:endering|ise)|matrix|pos)|(?:(?:char|word)_spac|horiz_scal|lead)ing|duration|font|parameter|value)|f(?:la|on)t|gray(?:_(?:fill|stroke))?|line(?:cap|join|width)|m(?:atrix|iterlimit)|rgbcolor(?:_(?:fill|stroke))?|color|(?:poly)?dash)|how(?:_(?:boxed|xy))?|tr(?:ingwidth|oke)|(?:av|cal)e|kew)|(?:dele|transla)te|initgraphics|lineto|new)|f(?:pro_(?:process(?:_raw)?|cleanup|init|version)|sockopen)|g_(?:c(?:l(?:ient_encoding|ose)|o(?:n(?:nect(?:ion_(?:busy|reset|status))?|vert)|py_(?:from|to))|ancel_query)|d(?:bnam|elet)e|e(?:scape_(?:bytea|string)|nd_copy)|f(?:etch_(?:a(?:ll|rray|ssoc)|r(?:esult|ow)|object)|ield_(?:n(?:ame|um)|is_null|prtlen|(?:siz|typ)e)|ree_result)|get_(?:notify|pid|result)|l(?:ast_(?:error|notice|oid)|o_(?:c(?:los|reat)e|read(?:_all)?|(?:ex|im)port|open|(?:see|unlin)k|tell|write))|num_(?:field|row)s|p(?:arameter_status|(?:connec|or)t|ing|ut_line)|result_(?:s(?:eek|tatus)|error)|se(?:lect|t_client_encoding)|t(?:race|ty)|u(?:n(?:escape_bytea|trace)|pdate)|(?:affected_row|option)s|(?:hos|inser)t|meta_data|version)|hp(?:_(?:s(?:tr(?:eam_(?:c(?:a(?:n_ca)?st|lose(?:dir)?|opy_to_(?:me|strea)m)|f(?:ilter_(?:un)?register_factory|open_(?:t(?:emporary_|mp)file|from_file)|lush)|get[cs]|is(?:_persistent)?|open(?:_wrapper(?:_(?:as_file|ex))?|dir)|re(?:ad(?:dir)?|winddir)|s(?:ock_open_(?:(?:from_socke|hos)t|unix)|tat(?:_path)?|eek)|eof|(?:make_seekabl|writ)e|passthru|tell)|ip_whitespace)|api_name)|un(?:ame|register_url_stream_wrapper)|check_syntax|ini_scanned_files|logo_guid|register_url_stream_wrapper)|credits|info|version)|o(?:s(?:ix_(?:get(?:e[gu]id|g(?:r(?:gid|nam|oups)|id)|p(?:g(?:id|rp)|w(?:nam|uid)|p?id)|_last_error|(?:cw|[su]i)d|login|rlimit)|s(?:et(?:e[gu]id|(?:p?g|[su])id)|trerror)|t(?:imes|tyname)|ctermid|isatty|kill|mkfifo|uname))?|pen|w)|r(?:e(?:g_(?:match(?:_all)?|replace(?:_callback)?|grep|quote|split)|v)|int(?:er_(?:c(?:reate_(?:brush|dc|font|pen)|lose)|d(?:elete_(?:brush|dc|font|pen)|raw_(?:r(?:ectangle|oundrect)|bmp|chord|(?:elips|lin|pi)e|text))|end_(?:doc|page)|l(?:is|ogical_fontheigh)t|s(?:e(?:lect_(?:brush|font|pen)|t_option)|tart_(?:doc|page))|abort|(?:get_optio|ope)n|write)|_r|f)|oc_(?:(?:clos|nic|terminat)e|get_status|open))|spell_(?:add_to_(?:personal|session)|c(?:onfig_(?:d(?:ata|ict)_dir|r(?:epl|untogether)|(?:creat|ignor|mod)e|(?:persona|save_rep)l)|heck|lear_session)|new(?:_(?:config|personal))?|s(?:(?:ave_wordli|ugge)s|tore_replacemen)t)|i|ng2wbmp|utenv)|q(?:dom_(?:error|tree)|uote(?:d_printable_decode|meta))|r(?:a(?:n(?:d|ge)|r_(?:close|(?:entry_ge|lis)t|open)|wurl(?:de|en)code|d2deg)|e(?:a(?:d(?:lin(?:e(?:_(?:c(?:allback_(?:handler_(?:install|remove)|read_char)|lear_history|ompletion_function)|re(?:ad_histor|displa)y|(?:add|list|write)_history|info|on_new_line))?|k)|_exif_data|dir|(?:gz)?file)|lpath)|code(?:_(?:file|string))?|gister_(?:shutdown|tick)_function|name(?:_function)?|s(?:tore_(?:e(?:rror|xception)_handler|include_path)|et)|wind(?:dir)?|turn)|mdir|ound|sort|trim)|s(?:e(?:m_(?:re(?:leas|mov)e|acquire|get)|s(?:am_(?:co(?:mmi|nnec)t|di(?:agnostic|sconnect)|e(?:rrormsg|xecimm)|f(?:etch_(?:r(?:esult|ow)|array)|ield_(?:array|name)|ree_result)|se(?:ek_row|ttransaction)|(?:affected_row|num_field)s|query|rollback)|sion_(?:c(?:ache_(?:expire|limiter)|ommit)|de(?:code|stroy)|i(?:s_registere)?d|reg(?:enerate_id|ister)|s(?:et_(?:cookie_params|save_handler)|ave_path|tart)|un(?:register|set)|(?:encod|(?:module_)?nam|write_clos)e|get_cookie_params))|t(?:_(?:e(?:rror|xception)_handler|file_buffer|include_path|magic_quotes_runtime|time_limit)|(?:(?:raw)?cooki|local|typ)e)|rialize)|h(?:a1(?:_file)?|m(?:_(?:remove(?:_var)?|(?:at|de)tach|(?:ge|pu)t_var)|op_(?:(?:clos|(?:dele|wri)t|siz)e|open|read))|ell_exec|(?:ow_sourc|uffl)e)|i(?:m(?:plexml_(?:load_(?:file|string)|import_dom)|ilar_text)|nh?|zeof)|nmp(?:_(?:get_(?:quick_print|valueretrieval)|set_(?:(?:enum|oid_numeric|quick)_print|valueretrieval)|read_mib)|get(?:next)?|walk(?:oid)?|realwalk|set)|o(?:cket_(?:c(?:l(?:ear_error|ose)|reate(?:_(?:listen|pair))?|onnect)|get(?:_(?:option|status)|(?:peer|sock)name)|l(?:ast_error|isten)|re(?:cv(?:from)?|ad)|s(?:e(?:nd(?:to)?|t_(?:block(?:ing)?|nonblock|option|timeout)|lect)|hutdown|trerror)|accept|bind|write)|rt|undex)|p(?:l(?:iti?|_classes)|rintf)|q(?:l(?:ite_(?:c(?:reate_(?:aggregate|function)|hanges|lose|olumn|urrent)|e(?:rror|scape)_string|f(?:etch_(?:a(?:ll|rray)|s(?:ingle|tring)|column_types|object)|actory|ield_name)|has_(?:more|prev)|l(?:ast_(?:error|insert_rowid)|ib(?:encoding|version))|n(?:um_(?:field|row)s|ext)|p(?:open|rev)|udf_(?:de|en)code_binary|busy_timeout|open|rewind|seek)|_regcase)|rt)|s(?:h2_(?:auth_(?:p(?:assword|ubkey_file)|none)|f(?:etch_stream|ingerprint)|s(?:cp_(?:recv|send)|ftp(?:_(?:r(?:e(?:a(?:dlink|lpath)|name)|mdir)|s(?:tat|ymlink)|lstat|mkdir|unlink))?|hell)|connect|exec|methods_negotiated|tunnel)|canf)|t(?:r(?:_(?:r(?:ep(?:eat|lace)|ot13)|s(?:huffle|plit)|ireplace|pad|word_count)|c(?:(?:asec)?mp|hr|oll|spn)|eam_(?:co(?:ntext_(?:get_(?:default|options)|set_(?:option|params)|create)|py_to_stream)|filter_(?:re(?:gister|move)|(?:ap|pre)pend)|get_(?:(?:(?:conten|transpor)t|(?:filt|wrapp)er)s|line|meta_data)|s(?:e(?:t_(?:blocking|timeout|write_buffer)|lect)|ocket_(?:se(?:ndto|rver)|(?:accep|clien)t|enable_crypto|get_name|pair|recvfrom))|wrapper_(?:re(?:gister|store)|unregister)|register_wrapper)|i(?:p(?:_tag|c?slashe|o)s|str)|n(?:atc(?:asec)?mp|c(?:asec)?mp)|p(?:brk|os|time)|r(?:chr|ev|i?pos)|s(?:pn|tr)|t(?:o(?:k|(?:low|upp)er|time)|r)|ftime|len|val)|at)|ubstr(?:_(?:co(?:mpare|unt)|replace))?|wf(?:_(?:a(?:ction(?:g(?:oto(?:frame|label)|eturl)|p(?:lay|revframe)|s(?:ettarget|top)|(?:next|waitfor)frame|togglequality)|dd(?:buttonrecord|color))|define(?:bitmap|(?:fon|rec|tex)t|line|poly)|end(?:s(?:hape|ymbol)|(?:butt|doacti)on)|font(?:s(?:ize|lant)|tracking)|get(?:f(?:ontinfo|rame)|bitmapinfo)|l(?:abelframe|ookat)|m(?:odifyobject|ulcolor)|o(?:rtho2?|ncondition|penfile)|p(?:o(?:larview|pmatrix|sround)|erspective|laceobject|ushmatrix)|r(?:emoveobject|otate)|s(?:etf(?:ont|rame)|h(?:ape(?:curveto3?|fill(?:bitmap(?:clip|tile)|off|solid)|line(?:solid|to)|arc|moveto)|owframe)|tart(?:s(?:hape|ymbol)|(?:butt|doacti)on)|cale)|t(?:extwidth|ranslate)|closefile|nextid|viewport)|b(?:utton(?:_keypress)?|itmap)|f(?:ill|ont)|mo(?:rph|vie)|s(?:hap|prit)e|text(?:field)?|action|displayitem|gradient)|y(?:base_(?:c(?:lose|onnect)|d(?:ata_seek|eadlock_retry_count)|f(?:etch_(?:a(?:rray|ssoc)|field|object|row)|ield_seek|ree_result)|min_(?:client|(?:erro|serve)r|message)_severity|num_(?:field|row)s|se(?:lect_db|t_message_handler)|affected_rows|get_last_message|(?:pconnec|resul)t|(?:unbuffered_)?query)|s(?:log|tem)|mlink)|candir|leep|rand)|t(?:anh?|e(?:mpnam|xtdomain)|i(?:dy_(?:c(?:lean_repair|onfig_count)|get(?:_(?:h(?:tml(?:_ver)?|ead)|r(?:elease|oot)|body|config|error_buffer|output|status)|opt)|is_x(?:ht)?ml|parse_(?:file|string)|re(?:pair_(?:file|string)|set_config)|s(?:et(?:_encoding|opt)|ave_config)|(?:access|error|warning)_count|diagnose|load_config)|me(?:_nanosleep)?)|o(?:ken_(?:get_all|name)|uch)|ri(?:gger_error|m)|cpwrap_check|mpfile)|u(?:c(?:first|words)|dm_(?:a(?:lloc_agent(?:_array)?|dd_search_limit|pi_version)|c(?:at_(?:list|path)|heck_(?:charset|stored)|l(?:ear_search_limits|ose_stored)|rc32)|err(?:no|or)|f(?:ree_(?:agent|ispell_data|res)|ind)|get_(?:res_(?:field|param)|doc_count)|hash32|load_ispell_data|open_stored|set_agent_param)|n(?:i(?:qi|xtoj)d|se(?:rialize|t)|(?:lin|pac)k|register_tick_function)|rl(?:de|en)code|s(?:er_error|leep|ort)|tf8_(?:de|en)code|[ak]sort|mask)|v(?:ar(?:_(?:dump|export)|iant(?:_(?:a(?:bs|[dn]d)|c(?:as?t|mp)|d(?:ate_(?:from|to)_timestamp|iv)|i(?:div|mp|nt)|m(?:od|ul)|n(?:eg|ot)|s(?:et(?:_type)?|ub)|eqv|fix|get_type|x?or|pow|round))?)|p(?:opmail_(?:a(?:dd_(?:alias_domain(?:_ex)?|domain(?:_ex)?|user)|lias_(?:del(?:_domain)?|get(?:_all)?|add)|uth_user)|del_(?:domain(?:_ex)?|user)|error|passwd|set_user_quota)|rintf)|ersion_compare|[fs]printf|irtual)|w(?:32api_(?:in(?:it_dtype|voke_function)|deftype|register_function|set_call_method)|ddx_(?:packet_(?:end|start)|serialize_va(?:lue|rs)|add_vars|deserialize)|ordwrap)|x(?:attr_(?:s(?:et|upported)|(?:ge|lis)t|remove)|diff_(?:file_(?:diff(?:_binary)?|patch(?:_binary)?|merge3)|string_(?:diff(?:_binary)?|patch(?:_binary)?|merge3))|ml(?:_(?:get_(?:current_(?:byte_index|(?:column|line)_number)|error_code)|parse(?:r_(?:create(?:_ns)?|free|[gs]et_option)|_into_struct)?|set_(?:e(?:lement|nd_namespace_decl|xternal_entity_ref)_handler|(?:character_data|default|(?:notation|start_namespace|unparsed_entity)_decl|processing_instruction)_handler|object)|error_string)|rpc_(?:decode(?:_request)?|encode(?:_request)?|se(?:rver_(?:c(?:all_method|reate)|register_(?:introspection_callback|method)|add_introspection_data|destroy)|t_type)|get_type|is_fault|parse_method_descriptions))|p(?:ath_(?:eval(?:_expression)?|new_context)|tr_(?:eval|new_context))|sl(?:_xsltprocessor_(?:re(?:gister_php_functions|move_parameter)|transform_to_(?:doc|uri|xml)|[gs]et_parameter|(?:has_exslt_suppor|import_styleshee)t)|t_(?:backend_(?:info|name|version)|err(?:no|or)|set(?:_(?:e(?:ncoding|rror_handler)|s(?:ax_handlers?|cheme_handlers?)|base|log|object)|opt)|(?:creat|fre)e|getopt|process)))|y(?:az_(?:c(?:cl_(?:conf|parse)|lose|onnect)|e(?:rr(?:no|or)|(?:lemen|s_resul)t)|r(?:ange|ecord)|s(?:c(?:an(?:_result)?|hema)|e(?:arch|t_option)|ort|yntax)|addinfo|database|get_option|hits|itemorder|(?:presen|wai)t)|p_(?:err(?:_string|no)|ma(?:ster|tch)|all|(?:ca|firs|nex)t|get_default_domain|order))|z(?:end_(?:logo_guid|version)|ip_(?:entry_(?:c(?:ompress(?:edsize|ionmethod)|lose)|(?:filesiz|nam)e|open|read)|close|open|read)|lib_get_coding_type))|(socket_getopt)|(socket_setopt))(\s*(?:\(|$)))/gi, // collisions - while
-	phpini: /\b(disable_classes|disable_functions|open_basedir|safe_mode_allowed_env_vars|safe_mode_exec_dir|safe_mode_gid|safe_mode_include_dir|safe_mode_protected_env_vars|safe_mode|(allow_call_time_pass_reference|always_populate_raw_post_data|arg_separator\.input|arg_separator\.output|asp_tags|auto_append_file|auto_globals_jit|auto_prepend_file|cgi\.fix_pathinfo|cgi\.force_redirect|cgi\.check_shebang_line|cgi\.redirect_status_env|cgi\.rfc2616_headers|default_charset|default_mimetype|doc_root|expose_php|extension_dir|fastcgi\.impersonate|file_uploads|include_path|memory_limit|post_max_size|precision|register_argc_argv|register_globals|register_long_arrays|short_open_tag|sql\.safe_mode|upload_max_filesize|upload_tmp_dir|user_dir|variables_order|y2k_compliance|zend\.ze1_compatibility_mode)|(engine|child_terminate|last_modified|xbithack)|(apc\.cache_by_default|apc\.enable_cli|apc\.enabled|apc\.file_update_protection|apc\.filters|apc\.gc_ttl|apc\.mmap_file_mask|apc\.num_files_hint|apc\.optimization|apc\.shm_segments|apc\.shm_size|apc\.slam_defense|apc\.ttl)|(apd\.dumpdir|apd\.statement_tracing)|(bcmath\.scale)|(com\.allow_dcom|com\.autoregister_casesensitive|com\.autoregister_typelib|com\.autoregister_verbose|com\.code_page|com\.typelib_file)|(date\.default_latitude|date\.default_longitude|date\.sunrise_zenith|date\.sunset_zenith|date\.timezone)|(dbx\.colnames_case)|(display_errors|display_startup_errors|docref_ext|docref_root|error_append_string|error_log|error_prepend_string|error_reporting|html_errors|ignore_repeated_errors|ignore_repeated_source|log_errors_max_len|log_errors|report_memleaks|track_errors)|(exif\.decode_jis_intel|exif\.decode_jis_motorola|exif\.decode_unicode_intel|exif\.decode_unicode_motorola|exif\.encode_jis|exif\.encode_unicode)|(expect\.logfile|expect\.loguser|expect\.timeout)|(allow_url_fopen|allow_url_include|auto_detect_line_endings|default_socket_timeout|from|user_agent)|(ibase\.allow_persistent|ibase\.dateformat|ibase\.default_db|ibase\.default_charset|ibase\.default_password|ibase\.default_user|ibase\.max_links|ibase\.max_persistent|ibase\.timeformat|ibase\.timestampformat)|(ibm_db2\.binmode|ibm_db2\.instance_name)|(ifx\.allow_persistent|ifx\.blobinfile|ifx\.byteasvarchar|ifx\.default_host|ifx\.default_password|ifx\.default_user|ifx\.charasvarchar|ifx\.max_links|ifx\.max_persistent|ifx\.nullformat|ifx\.textasvarchar)|(gd.jpeg_ignore_warning)|(assert\.active|assert\.bail|assert\.callback|assert\.quiet_eval|assert\.warning|enable_dl|magic_quotes_gpc|magic_quotes_runtime|max_execution_time|max_input_nesting_level|max_input_time)|(sendmail_from|sendmail_path|smtp_port)|(SMTP)|(maxdb\.default_db|maxdb\.default_host|maxdb\.default_pw|maxdb\.default_user|maxdb\.long_readlen)|(mbstring\.detect_order|mbstring\.encoding_translation|mbstring\.func_overload|mbstring\.http_input|mbstring\.http_output|mbstring\.internal_encoding|mbstring\.language|mbstring\.substitute_character)|(mime_magic\.debug|mime_magic\.magicfile)|(browscap|ignore_user_abort)|(highlight.bg|highlight.comment|highlight.default|highlight.html|highlight.keyword|highlight.string)|(msql\.allow_persistent|msql\.max_links|msql\.max_persistent)|(mysql\.allow_persistent|mysql\.connect_timeout|mysql\.default_host|mysql\.default_password|mysql\.default_port|mysql\.default_socket|mysql\.default_user|mysql\.max_links|mysql\.max_persistent|mysql\.trace_mode)|(mysqli\.default_host|mysqli\.default_port|mysqli\.default_pw|mysqli\.default_socket|mysqli\.default_user|mysqli\.max_links)|(define_syslog_variables)|(nsapi\.read_timeout)|(oci8\.default_prefetch|oci8\.max_persistent|oci8\.old_oci_close_semantics|oci8\.persistent_timeout|oci8\.ping_interval|oci8\.privileged_connect|oci8\.statement_cache_size)|(implicit_flush|output_buffering|output_handler)|(pcre\.backtrack_limit|pcre\.recursion_limit)|(pdo_odbc\.connection_pooling|pdo_odbc\.db2_instance_name)|(pgsql\.allow_persistent|pgsql\.auto_reset_persistent|pgsql\.ignore_notice|pgsql\.log_notice|pgsql\.max_links|pgsql\.max_persistent)|(runkit\.superglobal)|(session\.auto_start|session\.bug_compat_42|session\.bug_compat_warn|session\.cache_expire|session\.cache_limiter|session\.cookie_domain|session\.cookie_httponly|session\.cookie_lifetime|session\.cookie_path|session\.cookie_secure|session\.entropy_file|session\.entropy_length|session\.gc_divisor|session\.gc_maxlifetime|session\.gc_probability|session\.hash_bits_per_character|session\.hash_function|session\.name|session\.referer_check|session\.save_handler|session\.save_path|session\.serialize_handler|session\.use_cookies|session\.use_only_cookies|session\.use_trans_sid|url_rewriter\.tags)|(soap\.wsdl_cache_dir|soap\.wsdl_cache_enabled|soap\.wsdl_cache_limit|soap\.wsdl_cache_ttl)|(sqlite\.assoc_case)|(magic_quotes_sybase|sybase\.allow_persistent|sybase\.compatability_mode|sybase\.max_links|sybase\.max_persistent|sybase\.min_error_severity|sybase\.min_message_severity|sybct\.allow_persistent|sybct\.deadlock_retry_count|sybct\.hostname|sybct\.login_timeout|sybct\.max_links|sybct\.max_persistent|sybct\.min_client_severity|sybct\.min_server_severity|sybct\.timeout)|(tidy\.clean_output|tidy\.default_config)|(unicode\.output_encoding)|(odbc.allow_persistent|odbc.default_db|odbc.default_pw|odbc.default_user|odbc.defaultbinmode|odbc.defaultlrl|odbc.check_persistent|odbc.max_links|odbc.max_persistent)|(zlib\.output_compression_level|zlib\.output_compression|zlib\.output_handler))\b/g,
-	py: /\b(open|open_new|open_new_tab|(__import__|abs|all|any|basestring|bool|callable|chr|classmethod|cmp|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|isinstance|issubclass|iter|len|list|locals|long|map|max|min|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|type|unichr|unicode|vars|xrange|zip)|(reader|writer|register_dialect|unregister_dialect|get_dialect|list_dialects|field_size_limit)|(callable)|(CFUNCTYPE|WINFUNCTYPE|PYFUNCTYPE|prototype|prototype|prototype|prototype)|(addressof|alignment|byref|cast|create_string_buffer|create_unicode_buffer|DllCanUnloadNow|DllGetClassObject|FormatError|GetLastError|memmove|memset|POINTER|pointer|resize|set_conversion_mode|sizeof|string_at|WinError|wstring_at)|(baudrate|beep|can_change_color|cbreak|color_content|color_pair|curs_set|def_prog_mode|def_shell_mode|delay_output|doupdate|echo|endwin|erasechar|filter|flash|flushinp|getmouse|getsyx|getwin|has_colors|has_ic|has_il|has_key|halfdelay|init_color|init_pair|initscr|isendwin|keyname|killchar|longname|meta|mouseinterval|mousemask|napms|newpad|newwin|nl|nocbreak|noecho|nonl|noqiflush|noraw|pair_content|pair_number|putp|qiflush|raw|reset_prog_mode|reset_shell_mode|setsyx|setupterm|start_color|termattrs|termname|tigetflag|tigetnum|tigetstr|tparm|typeahead|unctrl|ungetch|ungetmouse|use_env|use_default_colors)|(bottom_panel|new_panel|top_panel|update_panels)|(getcontext|setcontext|localcontext)|(defaultdict)|(deque)|(testfile|testmod|run_docstring_examples)|(script_from_examples|testsource|debug|debug_src)|(register_optionflag)|(DocFileSuite|DocTestSuite|set_unittest_reportflags)|(Comment|dump|Element|fromstring|iselement|iterparse|parse|ProcessingInstruction|SubElement|tostring|XML|XMLID)|(getclasstree|getargspec|getargvalues|formatargspec|formatargvalues|getmro)|(getdoc|getcomments|getfile|getmodule|getsourcefile|getsourcelines|getsource)|(getframeinfo|getouterframes|getinnerframes|currentframe|stack|trace)|(getmembers|getmoduleinfo|getmodulename|ismodule|isclass|ismethod|isfunction|istraceback|isframe|iscode|isbuiltin|isroutine|ismethoddescriptor|isdatadescriptor|isgetsetdescriptor|ismemberdescriptor)|(chain|count|cycle|dropwhile|groupby|ifilter|ifilterfalse|imap|islice|izip|repeat|starmap|takewhile|tee)|(fileConfig|listen|stopListening)|(CloseKey|ConnectRegistry|CreateKey|DeleteKey|DeleteValue|EnumKey|EnumValue|FlushKey|RegLoadKey|OpenKey|OpenKeyEx|QueryInfoKey|QueryValue|QueryValueEx|SaveKey|SetValue|SetValueEx)|(Bastion)|(open)|(openport|newconfig|queryparams|getparams|setparams)|(open)|(array)|(loop)|(register)|(add|adpcm2lin|alaw2lin|avg|avgpp|bias|cross|findfactor|findfit|findmax|getsample|lin2adpcm|lin2alaw|lin2lin|lin2ulaw|minmax|max|maxpp|mul|ratecv|reverse|rms|tomono|tostereo|ulaw2lin)|(b64encode|b64decode|standard_b64encode|standard_b64decode|urlsafe_b64encode|urlsafe_b64decode|b32encode|b32decode|b16encode|b16decode|decode|decodestring|encode|encodestring)|(a2b_uu|b2a_uu|a2b_base64|b2a_base64|a2b_qp|b2a_qp|a2b_hqx|rledecode_hqx|rlecode_hqx|b2a_hqx|crc_hqx|crc32|b2a_hex|hexlify|a2b_hex|unhexlify)|(binhex|hexbin)|(bisect_left|bisect_right|bisect|insort_left|insort_right|insort)|(hashopen|btopen|rnopen)|(setfirstweekday|firstweekday|isleap|leapdays|weekday|weekheader|monthrange|monthcalendar|prmonth|month|prcal|calendar|timegm)|(createparser|msftoframe|open)|(enable|handler)|(acos|acosh|asin|asinh|atan|atanh|cos|cosh|exp|log|log10|sin|sinh|sqrt|tan|tanh)|(interact|compile_command)|(register|lookup|getencoder|getdecoder|getincrementalencoder|getincrementaldecoder|getreader|getwriter|register_error|lookup_error|strict_errors|replace_errors|ignore_errors|xmlcharrefreplace_errors_errors|backslashreplace_errors_errors|open|EncodedFile|iterencode|iterdecode)|(compile_command)|(rgb_to_yiq|yiq_to_rgb|rgb_to_hls|hls_to_rgb|rgb_to_hsv|hsv_to_rgb)|(getstatusoutput|getoutput|getstatus)|(compile_dir|compile_path)|(parse|parseFile|walk|compile|compileFile)|(walk)|(contextmanager|nested|closing)|(constructor|pickle)|(crypt)|(isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit|isctrl|ismeta|ascii|ctrl|alt|unctrl)|(rectangle)|(wrapper)|(open)|(open)|(__init__|make_file|make_table|context_diff|get_close_matches|ndiff|restore|unified_diff|IS_LINE_JUNK|IS_CHARACTER_JUNK)|(reset|listdir|opendir|annotate)|(dis|distb|disassemble|disco)|(open)|(open)|(add_charset|add_alias|add_codec)|(encode_quopri|encode_base64|encode_7or8bit|encode_noop)|(decode_header|make_header)|(body_line_iterator|typed_subpart_iterator|_structure)|(quote|unquote|parseaddr|formataddr|getaddresses|parsedate|parsedate_tz|mktime_tz|formatdate|make_msgid|decode_rfc2231|encode_rfc2231|collapse_rfc2231_value|decode_params)|(nameprep|ToASCII|ToUnicode)|(fcntl|ioctl|flock|lockf)|(cmp|cmpfiles)|(input|filename|fileno|lineno|filelineno|isfirstline|isstdin|nextfile|close|hook_compressed|hook_encoded)|(init|findfont|enumerate|prstr|setpath|fontpath|scalefont|setfont|getfontname|getcomment|getfontinfo|getstrwidth)|(fnmatch|fnmatchcase|filter)|(turnon_sigfpe|turnoff_sigfpe)|(fix|sci)|(partial|update_wrapper|wraps)|(enable|disable|isenabled|collect|set_debug|get_debug|get_objects|set_threshold|get_count|get_threshold|get_referrers|get_referents)|(open|firstkey|nextkey|reorganize|sync)|(getopt|gnu_getopt)|(getpass|getuser)|(varray|nvarray|vnarray|nurbssurface|nurbscurve|pwlcurve|pick|select|endpick|endselect)|(glob|iglob)|(send_selector|send_query)|(getgrgid|getgrnam|getgrall)|(open)|(heappush|heappop|heapify|heapreplace|nlargest|nsmallest)|(new)|(load)|(crop|scale|tovideo|grey2mono|dither2mono|mono2grey|grey2grey4|grey2grey2|dither2grey2|grey42grey|grey22grey)|(Internaldate2tuple|Int2AP|ParseFlags|Time2Internaldate)|(getsizes|read|readscaled|ttob|write)|(what)|(get_magic|get_suffixes|find_module|load_module|new_module|lock_held|acquire_lock|release_lock|init_builtin|init_frozen|is_builtin|is_frozen|load_compiled|load_dynamic|load_source)|(compress|decompress|setoption)|(iskeyword)|(getline|clearcache|checkcache)|(setlocale|localeconv|nl_langinfo|getdefaultlocale|getlocale|getpreferredencoding|normalize|resetlocale|strcoll|strxfrm|format|format_string|currency|str|atof|atoi)|(getLogger|getLoggerClass|debug|info|warning|error|critical|exception|log|disable|addLevelName|getLevelName|makeLogRecord|basicConfig|shutdown|setLoggerClass)|(findmatch|getcaps)|(dump|load|dumps|loads)|(ceil|fabs|floor|fmod|frexp|ldexp|modf|exp|log|log10|pow|sqrt|acos|asin|atan|atan2|cos|hypot|sin|tan|degrees|radians|cosh|sinh|tanh)|(new|md5)|(choose_boundary|decode|encode|copyliteral|copybinary)|(guess_type|guess_all_extensions|guess_extension|init|read_mime_types|add_type)|(mimify|unmimify|mime_decode_header|mime_encode_header)|(mmap|mmap)|(AddPackagePath|ReplacePackage)|(FCICreate|UUIDCreate|OpenDatabase|CreateRecord|init_database|add_data|add_tables|add_stream|gen_uuid)|(instance|instancemethod|function|code|module|classobj)|(match|cat|maps|get_default_domain)|(lt|le|eq|ne|ge|gt|__lt__|__le__|__eq__|__ne__|__ge__|__gt__|not_|__not__|truth|is_|is_not|abs|__abs__|add|__add__|and_|__and__|div|__div__|floordiv|__floordiv__|inv|invert|__inv__|__invert__|lshift|__lshift__|mod|__mod__|mul|__mul__|neg|__neg__|or_|__or__|pos|__pos__|pow|__pow__|rshift|__rshift__|sub|__sub__|truediv|__truediv__|xor|__xor__|index|__index__|concat|__concat__|contains|__contains__|countOf|delitem|__delitem__|delslice|__delslice__|getitem|__getitem__|getslice|__getslice__|indexOf|repeat|__repeat__|sequenceIncludes|setitem|__setitem__|setslice|__setslice__|iadd|__iadd__|iand|__iand__|iconcat|__iconcat__|idiv|__idiv__|ifloordiv|__ifloordiv__|ilshift|__ilshift__|imod|__imod__|imul|__imul__|ior|__ior__|ipow|__ipow__|irepeat|__irepeat__|irshift|__irshift__|isub|__isub__|itruediv|__itruediv__|ixor|__ixor__|isCallable|isMappingType|isNumberType|isSequenceType|attrgetter|itemgetter)|(abspath|basename|commonprefix|dirname|exists|lexists|expanduser|expandvars|getatime|getmtime|getctime|getsize|isabs|isfile|isdir|islink|ismount|join|normcase|normpath|realpath|samefile|sameopenfile|samestat|split|splitdrive|splitext|splitunc|walk)|(open|openmixer)|(run|runeval|runcall|set_trace|post_mortem|pm)|(dis|genops)|(extend_path)|(popen2|popen3|popen4)|(open|fileopen|lock|flags|dup|dup2|file)|(pformat|pprint|isreadable|isrecursive|saferepr)|(run|runctx)|(fork|openpty|spawn)|(getpwuid|getpwnam|getpwall)|(readmodule|readmodule_ex)|(compile|main)|(decode|encode|decodestring|encodestring)|(seed|getstate|setstate|jumpahead|getrandbits|randrange|randint|choice|shuffle|sample|random|uniform|betavariate|expovariate|gammavariate|gauss|lognormvariate|normalvariate|vonmisesvariate|paretovariate|weibullvariate|whseed)|(parse_and_bind|get_line_buffer|insert_text|read_init_file|read_history_file|write_history_file|clear_history|get_history_length|set_history_length|get_current_history_length|get_history_item|remove_history_item|replace_history_item|redisplay|set_startup_hook|set_pre_input_hook|set_completer|get_completer|get_begidx|get_endidx|set_completer_delims|get_completer_delims|add_history)|(repr)|(quote|unquote|parseaddr|dump_address_pair|parsedate|parsedate_tz|mktime_tz)|(sizeofimage|longimagedata|longstoimage|ttob)|(run_module)|(poll|select)|(new)|(open)|(split)|(copyfile|copyfileobj|copymode|copystat|copy|copy2|copytree|rmtree|move)|(alarm|getsignal|pause|signal)|(what|whathdr)|(getaddrinfo|getfqdn|gethostbyname|gethostbyname_ex|gethostname|gethostbyaddr|getnameinfo|getprotobyname|getservbyname|getservbyport|socket|ssl|socketpair|fromfd|ntohl|ntohs|htonl|htons|inet_aton|inet_ntoa|inet_pton|inet_ntop|getdefaulttimeout|setdefaulttimeout)|(getspnam|getspall)|(S_ISDIR|S_ISCHR|S_ISBLK|S_ISREG|S_ISFIFO|S_ISLNK|S_ISSOCK|S_IMODE|S_IFMT)|(in_table_a1|in_table_b1|map_table_b2|map_table_b3|in_table_c11|in_table_c12|in_table_c11_c12|in_table_c21|in_table_c22|in_table_c21_c22|in_table_c3|in_table_c4|in_table_c5|in_table_c6|in_table_c7|in_table_c8|in_table_c9|in_table_d1|in_table_d2)|(pack|unpack|calcsize)|(open|openfp)|(open)|(_current_frames|displayhook|excepthook|exc_info|exc_clear|exit|getcheckinterval|getdefaultencoding|getdlopenflags|getfilesystemencoding|getrefcount|getrecursionlimit|_getframe|getwindowsversion|setcheckinterval|setdefaultencoding|setdlopenflags|setprofile|setrecursionlimit|settrace|settscdump)|(syslog|openlog|closelog|setlogmask)|(check|tokeneater)|(open|is_tarfile)|(TemporaryFile|NamedTemporaryFile|mkstemp|mkdtemp|mktemp|gettempdir|gettempprefix)|(tcgetattr|tcsetattr|tcsendbreak|tcdrain|tcflush|tcflow)|(forget|is_resource_enabled|requires|findfile|run_unittest|run_suite)|(wrap|fill|dedent)|(start_new_thread|interrupt_main|exit|allocate_lock|get_ident|stack_size)|(activeCount|Condition|currentThread|enumerate|Event|Lock|RLock|Semaphore|BoundedSemaphore|settrace|setprofile|stack_size)|(asctime|clock|ctime|gmtime|localtime|mktime|sleep|strftime|strptime|time|tzset)|(ISTERMINAL|ISNONTERMINAL|ISEOF)|(generate_tokens|tokenize|untokenize)|(print_tb|print_exception|print_exc|format_exc|print_last|print_stack|extract_tb|extract_stack|format_list|format_exception_only|format_exception|format_tb|format_stack|tb_lineno)|(setraw|setcbreak)|(degrees|radians|setup|title|done|reset|clear|tracer|speed|delay|forward|backward|left|right|up|down|width|color|color|color|write|fill|begin_fill|end_fill|circle|goto|goto|towards|heading|setheading|position|setx|sety|window_width|window_height|demo)|(lookup|name|decimal|digit|numeric|category|bidirectional|combining|east_asian_width|mirrored|decomposition|normalize)|(urlopen|urlretrieve|urlcleanup|quote|quote_plus|unquote|unquote_plus|urlencode|pathname2url|url2pathname)|(urlopen|install_opener|build_opener)|(urlparse|urlunparse|urlsplit|urlunsplit|urljoin|urldefrag)|(encode|decode)|(getnode|uuid1|uuid3|uuid4|uuid5)|(open|openfp)|(proxy|getweakrefcount|getweakrefs)|(open|open_new|open_new_tab|get|register)|(whichdb)|(Beep|PlaySound|MessageBeep)|(make_server|demo_app)|(guess_scheme|request_uri|application_uri|shift_path_info|setup_testing_defaults|is_hop_by_hop)|(validator)|(parse|parseString)|(parse|parseString)|(ErrorString|ParserCreate)|(make_parser|parse|parseString)|(escape|unescape|quoteattr|prepare_input_source)|(is_zipfile)|(adler32|compress|compressobj|crc32|decompress|decompressobj)|(kbhit|getch|getche|putch|ungetch)|(locking|setmode|open_osfhandle|get_osfhandle)|(heapmin)|(message_from_string|message_from_file)|(registerDOMImplementation|getDOMImplementation)|(compress|decompress)|(dump|load|dumps|loads)|(capwords|maketrans)|(atof|atoi|atol|capitalize|expandtabs|find|rfind|index|rindex|count|lower|split|rsplit|splitfields|join|joinfields|lstrip|rstrip|strip|swapcase|translate|upper|ljust|rjust|center|zfill|replace)|(architecture|machine|node|platform|processor|python_build|python_compiler|python_version|python_version_tuple|release|system|system_alias|version|uname)|(java_ver)|(win32_ver)|(popen)|(mac_ver)|(dist|libc_ver)|(compile|search|match|split|findall|finditer|sub|subn|escape)|(getrlimit|setrlimit)|(getrusage|getpagesize)|(call|check_call)|(find_prefix_at_end)|(parse|parse_qs|parse_qsl|parse_multipart|parse_header|test|print_environ|print_form|print_directory|print_environ_usage|escape)|(fileno|handle_request|serve_forever|finish_request|get_request|handle_error|process_request|server_activate|server_bind|verify_request)|(finish|handle|setup)|(boolean|dumps|loads)|(Tcl)|(bindtextdomain|bind_textdomain_codeset|textdomain|gettext|lgettext|dgettext|ldgettext|ngettext|lngettext|dngettext|ldngettext)|(find|translation|install)|(expr|suite|sequence2ast|tuple2ast)|(ast2list|ast2tuple|compileast)|(isexpr|issuite)|(make_form|do_forms|check_forms|set_event_call_back|set_graphics_mode|get_rgbmode|show_message|show_question|show_choice|show_input|show_file_selector|get_directory|get_pattern|get_filename|qdevice|unqdevice|isqueued|qtest|qread|qreset|qenter|get_mouse|tie|color|mapcolor|getmcolor)|(apply|buffer|coerce|intern)|(close|dup|dup2|fdatasync|fpathconf|fstat|fstatvfs|fsync|ftruncate|isatty|lseek|open|openpty|pipe|read|tcgetpgrp|tcsetpgrp|ttyname|write)|(access|chdir|fchdir|getcwd|getcwdu|chroot|chmod|chown|lchown|link|listdir|lstat|mkfifo|mknod|major|minor|makedev|mkdir|makedirs|pathconf|readlink|remove|removedirs|rename|renames|rmdir|stat|stat_float_times|statvfs|symlink|tempnam|tmpnam|unlink|utime|walk)|(urandom)|(fdopen|popen|tmpfile|popen2|popen3|popen4)|(confstr|getloadavg|sysconf)|(abort|execl|execle|execlp|execlpe|execv|execve|execvp|execvpe|_exit|fork|forkpty|kill|killpg|nice|plock|popen|popen2|popen3|popen4|spawnl|spawnle|spawnlp|spawnlpe|spawnv|spawnve|spawnvp|spawnvpe|startfile|system|times|wait|waitpid|wait3|wait4|WCOREDUMP|WIFCONTINUED|WIFSTOPPED|WIFSIGNALED|WIFEXITED|WEXITSTATUS|WSTOPSIG|WTERMSIG)|(chdir|fchdir|getcwd|ctermid|getegid|geteuid|getgid|getgroups|getlogin|getpgid|getpgrp|getpid|getppid|getuid|getenv|putenv|setegid|seteuid|setgid|setgroups|setpgrp|setpgid|setreuid|setregid|getsid|setsid|setuid|strerror|umask|uname|unsetenv)|(connect|register_converter|register_adapter|complete_statement|enable_callback_tracebacks)|(main)|(warn|warn_explicit|showwarning|formatwarning|filterwarnings|simplefilter|resetwarnings))\b/g, // lot of collisions
-	sql: /\b(ALTER\s+DATABASE|ALTER\s+EVENT|ALTER\s+LOGFILE\s+GROUP|ALTER\s+SERVER|ALTER\s+TABLE|ALTER\s+TABLESPACE|ALTER\s+VIEW|ANALYZE\s+TABLE|BACKUP\s+TABLE|CACHE\s+INDEX|CHANGE\s+MASTER\s+TO|CHECK\s+TABLE|CHECKSUM\s+TABLE|CREATE\s+DATABASE|CREATE\s+EVENT|CREATE\s+FUNCTION|CREATE\s+INDEX|CREATE\s+LOGFILE\s+GROUP|CREATE\s+SERVER|CREATE\s+TABLE|CREATE\s+TABLESPACE|CREATE\s+TRIGGER|CREATE\s+USER|CREATE\s+VIEW|DELETE|DESCRIBE|DO|DROP\s+DATABASE|DROP\s+EVENT|DROP\s+FUNCTION|DROP\s+INDEX|DROP\s+LOGFILE\s+GROUP|DROP\s+SERVER|DROP\s+TABLE|DROP\s+TABLESPACE|DROP\s+TRIGGER|DROP\s+USER|DROP\s+VIEW|EXPLAIN|FLUSH|GRANT|HANDLER|HELP|INSERT|INSERT\s+DELAYED|INSTALL\s+PLUGIN|JOIN|KILL|LOAD\s+DATA\s+FROM\s+MASTER|OPTIMIZE\s+TABLE|PURGE\s+MASTER\s+LOGS|RENAME\s+DATABASE|RENAME\s+TABLE|RENAME\s+USER|REPAIR\s+TABLE|REPLACE|RESET\s+MASTER|RESET\s+SLAVE|RESTORE\s+TABLE|REVOKE|SELECT|SET\s+PASSWORD|SET\s+TRANSACTION|SHOW\s+AUTHORS|SHOW\s+BINARY\s+LOGS|SHOW\s+BINLOG\s+EVENTS|SHOW\s+CHARACTER\s+SET|SHOW\s+COLLATION|SHOW\s+COLUMNS|SHOW\s+CONTRIBUTORS|SHOW\s+CREATE\s+DATABASE|SHOW\s+CREATE\s+TABLE|SHOW\s+CREATE\s+VIEW|SHOW\s+DATABASES|SHOW\s+ENGINE|SHOW\s+ENGINES|SHOW\s+ERRORS|SHOW\s+GRANTS|SHOW\s+INDEX|SHOW\s+MASTER\s+STATUS|SHOW\s+OPEN\s+TABLES|SHOW\s+PLUGINS|SHOW\s+PRIVILEGES|SHOW\s+PROCESSLIST|SHOW\s+SCHEDULER\s+STATUS|SHOW\s+SLAVE\s+HOSTS|SHOW\s+SLAVE\s+STATUS|SHOW\s+STATUS|SHOW\s+TABLE\s+STATUS|SHOW\s+TABLES|SHOW\s+TRIGGERS|SHOW\s+VARIABLES|SHOW\s+WARNINGS|SHOW|START\s+SLAVE|STOP\s+SLAVE|TRUNCATE|UNINSTALL\s+PLUGIN|UNION|UPDATE|USE|(START\s+TRANSACTION|COMMIT|ROLLBACK)|(SAVEPOINT|ROLLBACK\s+TO\s+SAVEPOINT)|((?:UN)?LOCK\s+TABLES?)|(bit|tinyint|bool|boolean|smallint|mediumint|int|integer|bigint|float|double\s+precision|double|real|decimal|dec|numeric|fixed)|(date|datetime|timestamp|time|year)|(char|varchar|binary|varbinary|tinyblob|tinytext|blob|text|mediumblob|mediumtext|longblob|longtext|enum)|(IS|IS\s+NULL)|(BETWEEN|NOT\s+BETWEEN|IN|NOT\s+IN)|(ANY|SOME)|(ROW)|(WITH\s+ROLLUP)|(LIKE|NOT\s+LIKE|NOT\s+REGEXP|REGEXP)|(NOT|AND|OR|XOR)|(CASE)|(DIV)|(BINARY)|(ACCESSIBLE|ADD|ALL|ALTER|ANALYZE|AND|AS|ASC|ASENSITIVE|BEFORE|BETWEEN|BIGINT|BINARY|BLOB|BOTH|BY|CALL|CASCADE|CASE|CHANGE|CHAR|CHARACTER|CHECK|COLLATE|COLUMN|CONDITION|CONSTRAINT|CONTINUE|CONVERT|CREATE|CROSS|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DATABASES|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DEC|DECIMAL|DECLARE|DEFAULT|DELAYED|DELETE|DESC|DESCRIBE|DETERMINISTIC|DISTINCT|DISTINCTROW|DIV|DOUBLE|DROP|DUAL|EACH|ELSE|ELSEIF|ENCLOSED|ESCAPED|EXISTS|EXIT|EXPLAIN|FALSE|FETCH|FLOAT|FLOAT4|FLOAT8|FOR|FORCE|FOREIGN|FROM|FULLTEXT|GRANT|GROUP|HAVING|HIGH_PRIORITY|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IF|IGNORE|IN|INDEX|INFILE|INNER|INOUT|INSENSITIVE|INSERT|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTERVAL|INTO|IS|ITERATE|JOIN|KEY|KEYS|KILL|LEADING|LEAVE|LEFT|LIKE|LIMIT|LINEAR|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOW_PRIORITY|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MIDDLEINT|MINUTE_MICROSECOND|MINUTE_SECOND|MOD|MODIFIES|NATURAL|NOT|NO_WRITE_TO_BINLOG|NULL|NUMERIC|ON|OPTIMIZE|OPTION|OPTIONALLY|OR|ORDER|OUT|OUTER|OUTFILE|PRECISION|PRIMARY|PROCEDURE|PURGE|RANGE|READ|READS|READ_WRITE|REAL|REFERENCES|REGEXP|RELEASE|RENAME|REPEAT|REPLACE|REQUIRE|RESTRICT|RETURN|REVOKE|RIGHT|RLIKE|SCHEMA|SCHEMAS|SECOND_MICROSECOND|SELECT|SENSITIVE|SEPARATOR|SET|SHOW|SMALLINT|SPATIAL|SPECIFIC|SQL|SQLEXCEPTION|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_CALC_FOUND_ROWS|SQL_SMALL_RESULT|SSL|STARTING|STRAIGHT_JOIN|TABLE|TERMINATED|THEN|TINYBLOB|TINYINT|TINYTEXT|TO|TRAILING|TRIGGER|TRUE|UNDO|UNION|UNIQUE|UNLOCK|UNSIGNED|UPDATE|USAGE|USE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALUES|VARBINARY|VARCHAR|VARCHARACTER|VARYING|WHEN|WHERE|WHILE|WITH|WRITE|XOR|YEAR_MONTH|ZEROFILL))\b|\b(coalesce|greatest|isnull|interval|least|(if|ifnull|nullif)|(ascii|bin|bit_length|char|char_length|character_length|concat|concat_ws|conv|elt|export_set|field|find_in_set|format|hex|insert|instr|lcase|left|length|load_file|locate|lower|lpad|ltrim|make_set|mid|oct|octet_length|ord|position|quote|repeat|replace|reverse|right|rpad|rtrim|soundex|sounds_like|space|substring|substring_index|trim|ucase|unhex|upper)|(strcmp)|(abs|acos|asin|atan|atan2|ceil|ceiling|cos|cot|crc32|degrees|exp|floor|ln|log|log2|log10|mod|pi|pow|power|radians|rand|round|sign|sin|sqrt|tan|truncate)|(adddate|addtime|convert_tz|curdate|current_date|curtime|current_time|current_timestamp|date|datediff|date_add|date_format|date_sub|day|dayname|dayofmonth|dayofweek|dayofyear|extract|from_days|from_unixtime|get_format|hour|last_day|localtime|localtimestamp|makedate|maketime|microsecond|minute|month|monthname|now|period_add|period_diff|quarter|second|sec_to_time|str_to_date|subdate|subtime|sysdate|time|timediff|timestamp|timestampadd|timestampdiff|time_format|time_to_sec|to_days|unix_timestamp|utc_date|utc_time|utc_timestamp|week|weekday|weekofyear|year|yearweek)|(cast)|(extractvalue|updatexml)|(bit_count)|(aes_encrypt|aes_decrypt|compress|decode|encode|des_decrypt|des_encrypt|encrypt|md5|old_password|password|sha|sha1|uncompress|uncompressed_length)|(benchmark|charset|coercibility|collation|connection_id|current_user|database|found_rows|last_insert_id|row_count|schema|session_user|system_user|user|version)|(default|get_lock|inet_aton|inet_ntoa|is_free_lock|is_used_lock|master_pos_wait|name_const|release_lock|sleep|uuid|values)|(avg|bit_and|bit_or|bit_xor|count|count_distinct|group_concat|min|max|std|stddev|stddev_pop|stddev_samp|sum|var_pop|var_samp|variance)|(match|against))(\s*\()/gi, //! allow modifiers - e.g. ALTER(?: IGNORE)? TABLE, collisions - binary, set, values, like, date, timestamp, time, year, char
-	sqlite: /\b(ALTER\s+TABLE|ANALYZE|ATTACH|COPY|DELETE|DETACH|DROP\s+INDEX|DROP\s+TABLE|DROP\s+TRIGGER|DROP\s+VIEW|EXPLAIN|INSERT|CONFLICT|REINDEX|REPLACE|SELECT|UPDATE|TRANSACTION|VACUUM|(PRAGMA)|(CREATE\s+VIRTUAL\s+TABLE)|(BEGIN|COMMIT|ROLLBACK)|(CREATE(?:\s+UNIQUE)?\s+INDEX)|(CREATE(?:\s+TEMP|\s+TEMPORARY)?\s+TABLE)|(CREATE(?:\s+TEMP|\s+TEMPORARY)?\s+TRIGGER)|(CREATE(?:\s+TEMP|\s+TEMPORARY)?\s+VIEW)|(like|glob|regexp|match|escape|isnull|isnotnull|between|exists|case|when|then|else|cast|collate|in|and|or|not))\b|\b(abs|coalesce|glob|ifnull|hex|last_insert_rowid|length|like|load_extension|lower|nullif|quote|random|randomblob|round|soundex|sqlite_version|substr|typeof|upper|(date|time|datetime|julianday|strftime)|(avg|count|max|min|sum|total))(\s*\()/gi, // collisions - min, max, end, like, glob
-	pgsql: /\b(COMMIT\s+PREPARED|DROP\s+OWNED|PREPARE\s+TRANSACTION|REASSIGN\s+OWNED|RELEASE\s+SAVEPOINT|ROLLBACK\s+PREPARED|ROLLBACK\s+TO|SET\s+CONSTRAINTS|SET\s+ROLE|SET\s+SESSION\s+AUTHORIZATION|SET\s+TRANSACTION|START\s+TRANSACTION|(ABORT|ALTER\s+AGGREGATE|ALTER\s+CONVERSION|ALTER\s+DATABASE|ALTER\s+DOMAIN|ALTER\s+FUNCTION|ALTER\s+GROUP|ALTER\s+INDEX|ALTER\s+LANGUAGE|ALTER\s+OPERATOR|ALTER\s+ROLE|ALTER\s+SCHEMA|ALTER\s+SEQUENCE|ALTER\s+TABLE|ALTER\s+TABLESPACE|ALTER\s+TRIGGER|ALTER\s+TYPE|ALTER\s+USER|ANALYZE|BEGIN|CHECKPOINT|CLOSE|CLUSTER|COMMENT|COMMIT|COPY|CREATE\s+AGGREGATE|CREATE\s+CAST|CREATE\s+CONSTRAINT|CREATE\s+CONVERSION|CREATE\s+DATABASE|CREATE\s+DOMAIN|CREATE\s+FUNCTION|CREATE\s+GROUP|CREATE\s+INDEX|CREATE\s+LANGUAGE|CREATE\s+OPERATOR|CREATE\s+ROLE|CREATE\s+RULE|CREATE\s+SCHEMA|CREATE\s+SEQUENCE|CREATE\s+TABLE|CREATE\s+TABLE\s+AS|CREATE\s+TABLESPACE|CREATE\s+TRIGGER|CREATE\s+TYPE|CREATE\s+USER|CREATE\s+VIEW|DEALLOCATE|DECLARE|DELETE|DROP\s+AGGREGATE|DROP\s+CAST|DROP\s+CONVERSION|DROP\s+DATABASE|DROP\s+DOMAIN|DROP\s+FUNCTION|DROP\s+GROUP|DROP\s+INDEX|DROP\s+LANGUAGE|DROP\s+OPERATOR|DROP\s+ROLE|DROP\s+RULE|DROP\s+SCHEMA|DROP\s+SEQUENCE|DROP\s+TABLE|DROP\s+TABLESPACE|DROP\s+TRIGGER|DROP\s+TYPE|DROP\s+USER|DROP\s+VIEW|END|EXECUTE|EXPLAIN|FETCH|GRANT|INSERT|LISTEN|LOAD|LOCK|MOVE|NOTIFY|PREPARE|REINDEX|RESET|REVOKE|ROLLBACK|SAVEPOINT|SELECT|SELECT\s+INTO|SET|SHOW|TRUNCATE|UNLISTEN|UPDATE|VACUUM|VALUES)|(ALTER\s+OPERATOR\s+CLASS)|(CREATE\s+OPERATOR\s+CLASS)|(DROP\s+OPERATOR\s+CLASS)|(current_date|current_time|current_timestamp|localtime|localtimestamp|AT\s+TIME\s+ZONE)|(current_user|session_user|user)|(AND|NOT|OR)|(BETWEEN)|(LIKE|SIMILAR\s+TO)|(CASE|WHEN|THEN|ELSE)|(EXISTS|IN|ANY|SOME|ALL))\b|\b(abs|cbrt|ceil|ceiling|degrees|exp|floor|ln|log|mod|pi|power|radians|random|round|setseed|sign|sqrt|trunc|width_bucket|acos|asin|atan|atan2|cos|cot|sin|tan|(bit_length|char_length|convert|lower|octet_length|overlay|position|substring|trim|upper|ascii|btrim|chr|decode|encode|initcap|length|lpad|ltrim|md5|pg_client_encoding|quote_ident|quote_literal|regexp_replace|repeat|replace|rpad|rtrim|split_part|strpos|substr|to_ascii|to_hex|translate)|(get_bit|get_byte|set_bit|set_byte|md5)|(to_char|to_date|to_number|to_timestamp)|(age|clock_timestamp|date_part|date_trunc|extract|isfinite|justify_days|justify_hours|justify_interval|now|statement_timestamp|timeofday|transaction_timestamp)|(area|center|diameter|height|isclosed|isopen|npoints|pclose|popen|radius|width|box|circle|lseg|path|point|polygon)|(abbrev|broadcast|family|host|hostmask|masklen|netmask|network|set_masklen|text|trunc)|(currval|nextval|setval)|(array_append|array_cat|array_dims|array_lower|array_prepend|array_to_string|array_upper|string_to_array)|(avg|bit_and|bit_or|bool_and|bool_or|count|every|max|min|sum|corr|covar_pop|covar_samp|regr_avgx|regr_avgy|regr_count|regr_intercept|regr_r2|regr_slope|regr_sxx|regr_sxy|regr_syy|stddev|stddev_pop|stddev_samp|variance|var_pop|var_samp)|(generate_series)|(current_database|current_schema|current_schemas|inet_client_addr|inet_client_port|inet_server_addr|inet_server_port|pg_my_temp_schema|pg_is_other_temp_schema|pg_postmaster_start_time|version|has_database_privilege|has_function_privilege|has_language_privilege|has_schema_privilege|has_table_privilege|has_tablespace_privilege|pg_has_role|pg_conversion_is_visible|pg_function_is_visible|pg_operator_is_visible|pg_opclass_is_visible|pg_table_is_visible|pg_type_is_visible|format_type|pg_get_constraintdef|pg_get_expr|pg_get_indexdef|pg_get_ruledef|pg_get_serial_sequence|pg_get_triggerdef|pg_get_userbyid|pg_get_viewdef|pg_tablespace_databases|col_description|obj_description|shobj_description)|(current_setting|set_config|pg_cancel_backend|pg_reload_conf|pg_rotate_logfile|pg_start_backup|pg_stop_backup|pg_switch_xlog|pg_current_xlog_location|pg_current_xlog_insert_location|pg_xlogfile_name_offset|pg_xlogfile_name|pg_column_size|pg_database_size|pg_relation_size|pg_size_pretty|pg_tablespace_size|pg_total_relation_size|pg_ls_dir|pg_read_file|pg_stat_file|pg_advisory_lock|pg_advisory_lock_shared|pg_try_advisory_lock|pg_try_advisory_lock_shared|pg_advisory_unlock|pg_advisory_unlock_shared|pg_advisory_unlock_all))(\s*\()/gi, // collisions: IN, ANY, SOME, ALL (array), trunc, md5, abbrev
-	cnf: /\b(MaxRequestsPerThread|(AcceptFilter|AcceptPathInfo|AccessFileName|AddDefaultCharset|AddOutputFilterByType|AllowEncodedSlashes|AllowOverride|AuthName|AuthType|CGIMapExtension|ContentDigest|DefaultType|Directory|DirectoryMatch|DocumentRoot|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|FileETag|Files|FilesMatch|ForceType|HostnameLookups|IfDefine|IfModule|Include|KeepAlive|KeepAliveTimeout|Limit|LimitExcept|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine|LimitXMLRequestBody|Location|LocationMatch|LogLevel|MaxKeepAliveRequests|NameVirtualHost|Options|Require|RLimitCPU|RLimitMEM|RLimitNPROC|Satisfy|ScriptInterpreterSource|ServerAdmin|ServerAlias|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetHandler|SetInputFilter|SetOutputFilter|TimeOut|TraceEnable|UseCanonicalName|UseCanonicalPhysicalPort|VirtualHost)|(Action|Script)|(Alias|AliasMatch|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ScriptAlias|ScriptAliasMatch)|(AuthBasicAuthoritative|AuthBasicProvider)|(AuthDigestAlgorithm|AuthDigestDomain|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestProvider|AuthDigestQop|AuthDigestShmemSize)|(AuthnProviderAlias)|(Anonymous|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID|Anonymous_VerifyEmail)|(AuthDBDUserPWQuery|AuthDBDUserRealmQuery)|(AuthDBMType|AuthDBMUserFile)|(AuthDefaultAuthoritative)|(AuthUserFile)|(AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserAttribute|AuthLDAPRemoteUserIsDN|AuthLDAPUrl|AuthzLDAPAuthoritative)|(AuthDBMGroupFile|AuthzDBMAuthoritative|AuthzDBMType)|(AuthzDefaultAuthoritative)|(AuthGroupFile|AuthzGroupFileAuthoritative)|(Allow|Deny|Order)|(AuthzOwnerAuthoritative)|(AuthzUserAuthoritative)|(AddAlt|AddAltByEncoding|AddAltByType|AddDescription|AddIcon|AddIconByEncoding|AddIconByType|DefaultIcon|HeaderName|IndexHeadInsert|IndexIgnore|IndexOptions|IndexOrderDefault|IndexStyleSheet|ReadmeName)|(CacheDefaultExpire|CacheDisable|CacheEnable|CacheIgnoreCacheControl|CacheIgnoreHeaders|CacheIgnoreNoLastMod|CacheIgnoreQueryString|CacheLastModifiedFactor|CacheMaxExpire|CacheStoreNoStore|CacheStorePrivate)|(MetaDir|MetaFiles|MetaSuffix)|(ScriptLog|ScriptLogBuffer|ScriptLogLength)|(ScriptSock)|(Dav|DavDepthInfinity|DavMinTimeout)|(DavLockDB)|(DavGenericLockDB)|(DBDExptime|DBDKeep|DBDMax|DBDMin|DBDParams|DBDPersist|DBDPrepareSQL|DBDriver)|(DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize)|(DirectoryIndex|DirectorySlash)|(CacheDirLength|CacheDirLevels|CacheMaxFileSize|CacheMinFileSize|CacheRoot)|(DumpIOInput|DumpIOLogLevel|DumpIOOutput)|(ProtocolEcho)|(PassEnv|SetEnv|UnsetEnv)|(Example)|(ExpiresActive|ExpiresByType|ExpiresDefault)|(ExtFilterDefine|ExtFilterOptions)|(CacheFile|MMapFile)|(FilterChain|FilterDeclare|FilterProtocol|FilterProvider|FilterTrace)|(Header|RequestHeader)|(CharsetDefault|CharsetOptions|CharsetSourceEnc)|(IdentityCheck|IdentityCheckTimeout)|(ImapBase|ImapDefault|ImapMenu)|(SSIEnableAccess|SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|XBitHack)|(AddModuleInfo)|(ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer)|(LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize|LDAPTrustedClientCert|LDAPTrustedGlobalCert|LDAPTrustedMode|LDAPVerifyServerCert)|(BufferedLogs|CookieLog|CustomLog|LogFormat|TransferLog)|(ForensicLog)|(MCacheMaxObjectCount|MCacheMaxObjectSize|MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize)|(AddCharset|AddEncoding|AddHandler|AddInputFilter|AddLanguage|AddOutputFilter|AddType|DefaultLanguage|ModMimeUsePathInfo|MultiviewsMatch|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|TypesConfig)|(MimeMagicFile)|(CacheNegotiatedDocs|ForceLanguagePriority|LanguagePriority)|(NWSSLTrustedCerts|NWSSLUpgradeable|SecureListen)|(AllowCONNECT|BalancerMember|NoProxy|Proxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyFtpDirCharset|ProxyIOBufferSize|ProxyMatch|ProxyMaxForwards|ProxyPass|ProxyPassInterpolateEnv|ProxyPassMatch|ProxyPassReverse|ProxyPassReverseCookieDomain|ProxyPassReverseCookiePath|ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxySet|ProxyStatus|ProxyTimeout|ProxyVia)|(RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule)|(BrowserMatch|BrowserMatchNoCase|SetEnvIf|SetEnvIfNoCase)|(LoadFile|LoadModule)|(CheckCaseOnly|CheckSpelling)|(SSLCACertificateFile|SSLCACertificatePath|SSLCADNRequestFile|SSLCADNRequestPath|SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLCryptoDevice|SSLEngine|SSLHonorCipherOrder|SSLMutex|SSLOptions|SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite|SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire|SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth)|(ExtendedStatus|SeeRequestTail)|(Substitute)|(SuexecUserGroup)|(UserDir)|(CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking)|(IfVersion)|(VirtualDocumentRoot|VirtualDocumentRootIP|VirtualScriptAlias|VirtualScriptAliasIP)|(AcceptMutex|ChrootDir|CoreDumpDirectory|EnableExceptionHook|GracefulShutdownTimeout|Group|Listen|ListenBackLog|LockFile|MaxClients|MaxMemFree|MaxRequestsPerChild|MaxSpareThreads|MinSpareThreads|PidFile|ReceiveBufferSize|ScoreBoardFile|SendBufferSize|ServerLimit|StartServers|StartThreads|ThreadLimit|ThreadsPerChild|ThreadStackSize|User)|(MaxThreads)|(Win32DisableAcceptEx)|(MaxSpareServers|MinSpareServers))\b/g,
-	js: /\b(String\.fromCharCode|Date\.(?:parse|UTC)|Math\.(?:E|LN2|LN10|LOG2E|LOG10E|PI|SQRT1_2|SQRT2|abs|acos|asin|atan|atan2|ceil|cos|exp|floor|log|max|min|pow|random|round|sin|sqrt|tan)|Array|Boolean|Date|Error|Function|JavaArray|JavaClass|JavaObject|JavaPackage|Math|Number|Object|Packages|RegExp|String|(Infinity|NaN|undefined)|(decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt)|(break|continue|for|function|return|switch|throw|var|while|with)|(do)|(if|else)|(try|catch|finally)|(delete|in|instanceof|new|this|typeof|void)|(alinkColor|anchors|applets|bgColor|body|characterSet|compatMode|contentType|cookie|defaultView|designMode|doctype|documentElement|domain|embeds|fgColor|forms|height|images|implementation|lastModified|linkColor|links|plugins|popupNode|referrer|styleSheets|title|tooltipNode|URL|vlinkColor|width|clear|createAttribute|createDocumentFragment|createElement|createElementNS|createEvent|createNSResolver|createRange|createTextNode|createTreeWalker|evaluate|execCommand|getElementById|getElementsByName|importNode|loadOverlay|queryCommandEnabled|queryCommandIndeterm|queryCommandState|queryCommandValue|write|writeln)|(attributes|childNodes|className|clientHeight|clientLeft|clientTop|clientWidth|dir|firstChild|id|innerHTML|lang|lastChild|length|localName|name|namespaceURI|nextSibling|nodeName|nodeType|nodeValue|offsetHeight|offsetLeft|offsetParent|offsetTop|offsetWidth|ownerDocument|parentNode|prefix|previousSibling|scrollHeight|scrollLeft|scrollTop|scrollWidth|style|tabIndex|tagName|textContent|addEventListener|appendChild|blur|click|cloneNode|dispatchEvent|focus|getAttribute|getAttributeNS|getAttributeNode|getAttributeNodeNS|getElementsByTagName|getElementsByTagNameNS|hasAttribute|hasAttributeNS|hasAttributes|hasChildNodes|insertBefore|item|normalize|removeAttribute|removeAttributeNS|removeAttributeNode|removeChild|removeEventListener|replaceChild|scrollIntoView|setAttribute|setAttributeNS|setAttributeNode|setAttributeNodeNS|supports|onblur|onchange|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onresize)|(altKey|bubbles|button|cancelBubble|cancelable|clientX|clientY|ctrlKey|currentTarget|detail|eventPhase|explicitOriginalTarget|isChar|layerX|layerY|metaKey|originalTarget|pageX|pageY|relatedTarget|screenX|screenY|shiftKey|target|timeStamp|type|view|which|initEvent|initKeyEvent|initMouseEvent|initUIEvent|stopPropagation|preventDefault)|(elements|length|name|acceptCharset|action|enctype|encoding|method|submit|reset)|(caption|tHead|tFoot|rows|tBodies|align|bgColor|border|cellPadding|cellSpacing|frame|rules|summary|width|createTHead|deleteTHead|createTFoot|deleteTFoot|createCaption|deleteCaption|insertRow|deleteRow)|(content|closed|controllers|crypto|defaultStatus|directories|document|frameElement|frames|history|innerHeight|innerWidth|length|location|locationbar|menubar|name|navigator|opener|outerHeight|outerWidth|pageXOffset|pageYOffset|parent|personalbar|pkcs11|screen|availTop|availLeft|availHeight|availWidth|colorDepth|height|left|pixelDepth|top|width|scrollbars|scrollMaxX|scrollMaxY|scrollX|scrollY|self|sidebar|status|statusbar|toolbar|window|alert|atob|back|btoa|captureEvents|clearInterval|clearTimeout|close|confirm|dump|escape|find|forward|getAttention|getComputedStyle|getSelection|home|moveBy|moveTo|open|openDialog|print|prompt|releaseEvents|resizeBy|resizeTo|scroll|scrollBy|scrollByLines|scrollByPages|scrollTo|setInterval|setTimeout|sizeToContent|stop|unescape|updateCommands|onabort|onclose|ondragdrop|onerror|onload|onpaint|onreset|onscroll|onselect|onsubmit|onunload))\b|\b(pop|push|reverse|shift|sort|splice|unshift|concat|join|slice|(getDate|getDay|getFullYear|getHours|getMilliseconds|getMinutes|getMonth|getSeconds|getTime|getTimezoneOffset|getUTCDate|getUTCDay|getUTCFullYear|getUTCHours|getUTCMilliseconds|getUTCMinutes|getUTCMonth|getUTCSeconds|setDate|setFullYear|setHours|setMilliseconds|setMinutes|setMonth|setSeconds|setTime|setUTCDate|setUTCFullYear|setUTCHours|setUTCMilliseconds|setUTCMinutes|setUTCMonth|setUTCSeconds|toDateString|toLocaleDateString|toLocaleTimeString|toTimeString|toUTCString)|(apply|call)|(toExponential|toFixed|toPrecision)|(exec|test)|(charAt|charCodeAt|concat|indexOf|lastIndexOf|localeCompare|match|replace|search|slice|split|substr|substring|toLocaleLowerCase|toLocaleUpperCase|toLowerCase|toUpperCase))(\s*\()/g // collisions: bgColor, height, width,length, name
-};
diff --git a/static/style.css b/static/style.css
deleted file mode 100644
index 489ac72..0000000
--- a/static/style.css
+++ /dev/null
@@ -1,48 +0,0 @@
-
-body {
-	padding: 0 20pt 1em 0;
-	background-image: url('vector_abstract_floral_background.jpg');
-	background-repeat: no-repeat;
-	background-position: right bottom;
-	background-attachment: fixed;
-	font-family: sans-serif;
-	/* text-shadow: white 0.2em 0.1em 0; */
-	text-shadow: -0.1em 0 0.1em white, 0 0.1em 0.1em white, 0.1em 0 0.1em white, 0 -0.1em 0.1em white;
-	color: #094b24;
-
-	margin: 1em auto 1em 10em;
-	padding: 0 20pt 1em 20pt;
-	width: 40em;
-}
-
-div.introduction {
-	font-size: x-large;
-}
-
-div.album-list {
-	margin: 2em auto 2em auto;
-}
-
-div.album-item {
-	margin: 1.5em auto 1.5em auto;
-}
-
-div.album-item div.title {
-	font-weight: bold;
-	font-size: large;
-}
-
-div.album-item div.text {
-	margin-left: 2em;
-}
-
-div.album-item a {
-	text-decoration: none;
-	color: #09aa24;
-}
-
-div.album-item a:hover {
-	text-decoration: none;
-	color: #0c0;
-}
-
diff --git a/static/vector_abstract_floral_background.jpg b/static/vector_abstract_floral_background.jpg
deleted file mode 100644
index 8966789..0000000
Binary files a/static/vector_abstract_floral_background.jpg and /dev/null differ
diff --git a/templates/album.html b/templates/album.html
index 15d2da4..ce5cfdd 100644
--- a/templates/album.html
+++ b/templates/album.html
@@ -1,158 +1,46 @@
 <html>
-    <head>
-		<meta http-equiv="Content-type" content="text/html; charset=utf-8">
-        <title>{{title}} - {{album.title}}</title>
-		<link rel="stylesheet" href="static/css/basic.css" type="text/css" />
-        <link rel="stylesheet" href="static/css/galleriffic-galala.css"
-            type="text/css" />
-		<script type="text/javascript" src="static/js/jquery-1.3.2.js"></script>
-		<script type="text/javascript" src="static/js/jquery.history.js"></script>
-		<script type="text/javascript" src="static/js/jquery.galleriffic.js"></script>
-		<script type="text/javascript" src="static/js/jquery.opacityrollover.js"></script>
-		<!-- We only want the thunbnails to display when javascript is disabled -->
-		<script type="text/javascript">
-			document.write('<style>.noscript { display: none; }</style>');
-		</script>
-	</head>
-	<body>
-		<div id="page">
-			<div id="container">
-                <h1><a href="index.html">{{title}}</a>
-                    &mdash; {{album.title}}
-                </h1>
-
-                <hr />
-
-				<!-- Start Advanced Gallery Html Containers -->
-				<div id="gallery" class="content">
-					<div id="controls" class="controls"></div>
-					<div class="slideshow-container">
-						<div id="loading" class="loader"></div>
-						<div id="slideshow" class="slideshow"></div>
-					</div>
-					<div id="caption" class="caption-container"></div>
-				</div>
-				<div id="thumbs" class="navigation">
-					<ul class="thumbs noscript">
-                        %for i in album.images:
-                            <li>
-                            <a class="thumb"
-                                name="{{i.normalpath.split('/')[-1]}}"
-                                href="{{i.normalpath}}"
-                                title="{{i.title}}">
-                                    <img src="{{i.thumbpath}}"
-                                        alt="{{i.title}}"/>
-                                </a>
-                                <div class="caption">
-                                    <div class="download">
-                                        <a href="{{i.normalpath}}">original</a>
-                                    </div>
-                                    <div class="image-title">{{i.title}}</div>
-                                    <div class="image-desc">
-                                        {{i.description}}
-                                    </div>
-                                </div>
-                            </li>
-                        %end
-					</ul>
-				</div>
-				<!-- End Advanced Gallery Html Containers -->
-				<div style="clear: both;"></div>
-			</div>
-		</div>
-		<div id="footer">Galala!</div>
-		<script type="text/javascript">
-			jQuery(document).ready(function($) {
-				// We only want these styles applied when javascript is enabled
-				$('div.navigation').css({'width' : '200px', 'float' : 'left'});
-				$('div.content').css('display', 'block');
-
-				// Initially set opacity on thumbs and add
-				// additional styling for hover effect on thumbs
-				var onMouseOutOpacity = 0.67;
-				$('#thumbs ul.thumbs li').opacityrollover({
-					mouseOutOpacity:   onMouseOutOpacity,
-					mouseOverOpacity:  1.0,
-					fadeSpeed:         'fast',
-					exemptionSelector: '.selected'
-				});
-				
-				// Initialize Advanced Galleriffic Gallery
-				var gallery = $('#thumbs').galleriffic({
-					delay:                     2500,
-					numThumbs:                 12,
-					preloadAhead:              10,
-					enableTopPager:            true,
-					enableBottomPager:         true,
-					maxPagesToShow:            4,
-					imageContainerSel:         '#slideshow',
-					controlsContainerSel:      '#controls',
-					captionContainerSel:       '#caption',
-					loadingContainerSel:       '#loading',
-					renderSSControls:          true,
-					renderNavControls:         true,
-					playLinkText:              'PresentaciĆ³n',
-					pauseLinkText:             'Pausa',
-					prevLinkText:              '&lsaquo; anterior',
-					nextLinkText:              'siguiente &rsaquo;',
-					nextPageLinkText:          '&rsaquo;&rsaquo;',
-					prevPageLinkText:          '&lsaquo;&lsaquo;',
-					enableHistory:             true,
-					autoStart:                 false,
-					syncTransitions:           true,
-					defaultTransitionDuration: 900,
-					onSlideChange:             function(prevIndex, nextIndex) {
-						// 'this' refers to the gallery, which is an extension of $('#thumbs')
-						this.find('ul.thumbs').children()
-							.eq(prevIndex).fadeTo('fast', onMouseOutOpacity).end()
-							.eq(nextIndex).fadeTo('fast', 1.0);
-					},
-					onPageTransitionOut:       function(callback) {
-						this.fadeTo('fast', 0.0, callback);
-					},
-					onPageTransitionIn:        function() {
-						this.fadeTo('fast', 1.0);
-					}
-				});
-
-				/**** Functions to support integration of galleriffic with the jquery.history plugin ****/
-
-				// PageLoad function
-				// This function is called when:
-				// 1. after calling $.historyInit();
-				// 2. after calling $.historyLoad();
-				// 3. after pushing "Go Back" button of a browser
-				function pageload(hash) {
-					// alert("pageload: " + hash);
-					// hash doesn't contain the first # character.
-					if(hash) {
-						$.galleriffic.gotoImage(hash);
-					} else {
-						gallery.gotoIndex(0);
-					}
-				}
-
-				// Initialize history plugin.
-				// The callback is called at once by present location.hash. 
-				$.historyInit(pageload, "advanced.html");
-
-				// set onlick event for buttons using the jQuery 1.3 live method
-				$("a[rel='history']").live('click', function(e) {
-					if (e.button != 0) return true;
-					
-					var hash = this.href;
-					hash = hash.replace(/^.*#/, '');
-
-					// moves to a new page. 
-					// pageload is called at once. 
-					// hash don't contain "#", "?"
-					$.historyLoad(hash);
-
-					return false;
-				});
-
-				/****************************************************************************************/
-			});
-		</script>
-	</body>
+<head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+    <title>{{title}} - {{album.title}}</title>
+    <link rel="stylesheet" href="static/album.css" type="text/css" />
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
+    <script type="text/javascript" src="static/jquery.touchSwipe.js"></script>
+    <script type="text/javascript" src="static/galala.js"></script>
+</head>
+<body>
+
+<div class="container">
+    <div class="mainpic">
+        <h1><a href=".">{{title}}</a> -
+            <a href="">{{album.title}}</a></h1>
+
+        % fst = album.images[0]
+        <img id="main"
+             src="{{fst.normalpath}}"
+             alt=""
+             data-anchor="{{fst.anchor}}"/>
+
+        <p><span id="title"></span><br>
+           <span id="desc"></span></p>
+    </div>
+
+    <div class="thumbnails">
+        %for i in album.images:
+            <img class="thumb" id="{{i.anchor}}" src="{{i.thumbpath}}"/>
+        %end
+    </div>
+
+</div>
+
+<div class="preload">
+    <img id="preload1"/>
+    <img id="preload2"/>
+</div>
+
+
+<script type="text/javascript">
+images = {{album.images_to_json()}}
+</script>
+
+</body>
 </html>
diff --git a/templates/index.html b/templates/index.html
index b9a1acd..3ac5bf9 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -3,7 +3,7 @@
 
 <html xmlns="http://www.w3.org/1999/xhtml">
     <head>
-        <link rel="stylesheet" type="text/css" href="static/style.css" />
+        <link rel="stylesheet" type="text/css" href="static/index.css" />
         <meta http-equiv="content-type" content="text/html; charset=utf-8" />
         <title>{{title}}</title>
     </head>